一 redis过期策略
Redis的过期策略是指当Redis中的缓存数据(即key)达到其设定的过期时间后,Redis如何对这些数据进行处理的一系列规则和方法。Redis提供了多种过期策略,主要包括以下几种方式:
1. 定时删除
- 做法:为每个设置了过期时间的key创建一个定时器,当过期时间到达时,定时器触发,Redis立即删除该key。
- 优点:可以立即释放内存,对内存使用友好。
- 缺点:占用大量CPU资源,因为每个key都需要一个独立的定时器,这在key数量很多时会导致CPU负载过高,从而影响Redis的性能。因此,Redis并不推荐这种方式作为主要的过期策略。
2. 惰性删除
- 做法:Redis不主动删除过期的key,而是在每次访问key时,检查该key是否过期。如果已过期,则删除该key。
- 优点:可以节省CPU资源,因为只有在实际需要访问key时才会进行检查。
- 缺点:可能导致大量过期的key仍然占用内存,特别是如果这些key在过期后很长时间内都没有被访问。
3. 定期删除
- 做法:Redis将设置了过期时间的key放入一个特定的字典中,并周期性地(默认是100ms)从这个字典中随机选取一定数量的key进行检查,删除其中的过期key。如果删除的key数量超过一定比例(如1/4),则重复这个过程,直到删除的key数量少于这个比例。
- 优点:是定时删除和惰性删除的折中方案,可以在不过度消耗CPU资源的情况下,有效地释放内存。
- 缺点:可能存在一些过期的key在一段时间内仍然被使用,特别是在key过期时间集中分布时。此外,如果过期key数量非常多,可能导致扫描和删除操作频繁,从而影响Redis的性能。
4. 内存淘汰策略
当Redis的内存达到限制时,除了上述过期策略外,Redis还提供了多种内存淘汰策略来选择删除哪些键以腾出空间。这些策略包括:
- noeviction:当内存超出限制时,不保存新的数据,返回错误。
- allkeys-lru:根据最近最少使用(LRU)算法,删除最久未使用的键。
- allkeys-lfu:根据最不经常使用(LFU)算法,删除使用频率最低的键。
- volatile-lru:在设置了过期时间的键集合中,使用LRU算法删除最久未使用的键。
- volatile-lfu:在设置了过期时间的键集合中,使用LFU算法删除使用频率最低的键。
- allkeys-random:随机删除任意键。
- volatile-random:随机删除设置了过期时间的任意键。
- volatile-ttl:删除设置了过期时间且剩余生存时间最短的键。
二 TCP和UDP区别
1. 连接性
- TCP:TCP是一种面向连接的协议。在数据传输之前,TCP要求发送方和接收方之间先建立一个可靠的连接。这个连接过程通常包括三次握手,确保双方都已准备好接收数据。
- UDP:UDP则是一种无连接的协议。发送方在发送数据之前不需要与接收方建立连接,可以直接将数据发送出去。这种无连接特性使得UDP的通信过程更加简单和高效。
2. 可靠性
- TCP:TCP对数据的可靠性要求非常严格。它采用了一系列机制来确保数据的完整性和正确性,包括确认机制、重传机制和流量控制机制等。如果接收方没有收到数据或数据有误,TCP会要求发送方重新发送,直到数据正确接收为止。
- UDP:UDP对数据的可靠性要求较低,它不提供确认、重传和流量控制等机制。因此,如果发送的数据丢失或损坏,UDP不会进行任何处理,而是直接由接收方承担可能的数据错误或丢失的风险。
3. 速度和效率
- TCP:由于TCP需要建立连接和进行确认重传等操作,因此其速度和效率相对较低。特别是在网络拥堵的情况下,TCP的拥塞控制机制会进一步降低其传输速度。
- UDP:UDP不受连接建立和确认重传等开销的影响,因此其传输速度通常比TCP更快。同时,UDP也不受拥塞控制算法的限制,可以在网络拥堵时继续发送数据。
4. 数据包大小
- TCP:TCP将数据划分为较小的数据包(称为TCP段)进行传输,并根据网络状况进行调整。TCP没有固定的数据报大小限制,可以根据需要动态调整数据包的大小。
- UDP:UDP允许将多个数据包打包成一个较大的数据报(称为UDP数据报)进行传输。UDP数据报的大小通常由应用层决定,但受到网络MTU(最大传输单元)的限制。
5. 适用场景
- TCP:由于TCP提供可靠的数据传输服务,因此适用于对数据可靠性要求较高的应用场景,如文件传输、电子邮件和网页浏览等。
- UDP:UDP由于其快速传输和较低的开销特性,适用于对数据实时性要求较高的应用场景,如音频和视频流传输、网络游戏和实时通信等。此外,UDP还支持广播和多播传输方式,适用于需要向多个主机发送相同数据的场景。
三 MySQL索引适用场景
1. 经常被查询的字段
- 场景描述:对于经常被查询的字段,如用户ID、订单号等,建立索引可以显著提高查询效率。
- 应用实例:在电商网站中,用户经常通过订单号查询订单信息,为订单号字段建立索引可以加快查询速度。
2. 需要进行范围查询的字段
- 场景描述:对于需要进行范围查询的字段,如日期范围、价格范围等,建立索引可以加快查询速度。
- 应用实例:在新闻网站中,用户经常通过日期范围查询新闻,为日期字段建立索引可以提高查询效率。
3. 外键字段
- 场景描述:对于外键字段,建立索引可以加快关联查询的速度。
- 应用实例:在一个订单系统中,订单表和用户表通过用户ID进行关联查询,为用户ID字段建立索引可以提高查询效率。
4. 需要进行排序操作的字段
- 场景描述:对于需要进行排序操作的字段,建立索引可以加快排序速度。
- 应用实例:在一个论坛系统中,用户经常通过帖子的发布时间进行排序,为发布时间字段建立索引可以提高排序效率。
5. 需要进行统计操作的字段
- 场景描述:对于需要进行统计操作的字段,建立索引可以加快统计的速度。
- 应用实例:在一个销售系统中,需要统计每个月的销售额,为销售日期字段建立索引可以提高统计效率。
6. 大表中的查询字段
- 场景描述:在处理大量数据的情况下,索引的作用更加明显。对于大表中的查询字段,建立索引可以加快查询速度。
- 应用实例:在一个电商平台中,商品表可能包含上百万条数据,为商品名称字段建立索引可以提高查询效率。
7. 唯一性索引
- 场景描述:唯一性索引确保索引列中的所有值都是唯一的,适用于需要保证数据唯一性的场景,如用户的手机号、身份证号等。
- 应用实例:创建表时添加唯一索引,或者在已存在的表上添加唯一索引,以确保数据的唯一性。
8. 组合索引
- 场景描述:组合索引涉及多个列,可以通过多个列的组合来提高查询性能。
- 应用实例:在订单表中同时对用户ID和订单状态创建复合索引,以减少数据库的扫描范围,提高查询速度。
四 两个有序数组合并
1.暴力破解法:直接合并两个数组,再对新数组进行排序
public class MergeSortedArrays {
public static int[] mergeArrays(int[] arr1, int[] arr2) {
int[] merged = new int[arr1.length + arr2.length];
// 复制数组1
System.arraycopy(arr1, 0, merged, 0, arr1.length);
// 复制数组2
System.arraycopy(arr2, 0, merged, arr1.length, arr2.length);
// 对合并后的数组进行排序
Arrays.sort(merged);
return merged;
}
public static void main(String[] args) {
int[] arr1 = {1, 3, 5, 7};
int[] arr2 = {2, 4, 6, 8};
int[] merged = mergeArrays(arr1, arr2);
System.out.println(Arrays.toString(merged));
}
}
2.双指针法
public class MergeSortedArraysEfficient {
public static int[] mergeSortedArrays(int[] arr1, int[] arr2) {
int len1 = arr1.length, len2 = arr2.length;
int[] merged = new int[len1 + len2];
int i = 0, j = 0, k = 0;
// 使用三个指针分别指向两个输入数组和输出数组
while (i < len1 && j < len2) {
if (arr1[i] <= arr2[j]) {
merged[k++] = arr1[i++];
} else {
merged[k++] = arr2[j++];
}
}
// 如果第一个数组还有剩余,复制剩余部分
while (i < len1) {
merged[k++] = arr1[i++];
}
// 如果第二个数组还有剩余,复制剩余部分
while (j < len2) {
merged[k++] = arr2[j++];
}
return merged;
}
public static void main(String[] args) {
int[] arr1 = {1, 3, 5, 7};
int[] arr2 = {2, 4, 6, 8};
int[] merged = mergeSortedArrays(arr1, arr2);
System.out.println(Arrays.toString(merged));
}
}