redis中有哪些过期策略
定期删除 + 惰性删除
- 定期删除:是指redis默认每100ms就随机检查设置了过期时间的key,如果过期就删除。假设redis中有10w条key设置了过期时间,每隔几百毫秒就检查这10w个key,cpu负载太高了,redis可能就会挂掉。实际上是随机抽取这10w个中的某些key进行检查删除。
- 惰性删除:若这10w条数据中有的过期了,而没被redis删除,那么当下次获取这个key的时候,redis会先检查这个key是否过期,若过期就删除该key,返回null
当要过期的key没有经过惰性删除删除掉,或者长期保存的key大量积压在内存,导致redis内存耗尽,该怎么办
redis为提供了内存淘汰机制,若redis占用过多的内存,此redis本身会进行内存淘汰。删除一些key给内存腾地儿。
- noeviction:当内存不足以容纳新的key插入时,就会插入报错。
- allkeys-lru:当内存不足时,在键空间中,移除最近最少使用的key(常用)
- allkeys-random:随机删除key
- volatile-lru:删除设置了过期时间且最少使用到的key
- volatile-random:随机删除设置了过期时间的key
- volatile-ttl:删除设置了过期时间中快要过期的key
手写LRU算法
我们可以根据LinkedHashMap的热点词汇进行模拟LRU算法的实现
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
public LRUCache(int cacheSize) {
// 初始map的大小,true表示让linkedHashMap按照key的访问热度进行排序
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
CACHE_SIZE = cacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > CACHE_SIZE; // map中指的数量大于指定的数量时,就会删除最老的数据
}
public static void main(String[] args) {
LRUCache<Object, Object> lruCache = new LRUCache<>(3);
lruCache.put("name",23);
lruCache.put("home","潍坊");
lruCache.put("degree","本科");
//todo 如果此时新添加一个元素,此时map中并没有热词,就会把最新插入的元素的删除,插入新的元素
// lruCache.put("department","开发部");
// System.out.println(lruCache); // {home=潍坊, degree=本科, department=开发部}
for (int i = 0; i < 10; i++) {
lruCache.get("name"); // 此时name就会成为热词并保留下, 那么home就会被删除
}
lruCache.put("department","开发部");
System.out.println(lruCache); // {degree=本科, name=23, department=开发部}
}
}
redis的高并发和高可用,redis的主从复制
单机redis并发量QPS最多也就几万吧,简单的k v形式,读写分离,缓存写相对于读会少很多。 主从复制 - maste slave可水平扩容 请求量增加,增加slave即可。
注意:
- master必须要有持久化机制,若没有,宕机重启时,就会把其他的salve也置空。
- master及时备份,如果本地的数据丢失,就可以把备份的rdb去恢复master中的数据,重启master就会重新加载备份的数据。