Redis笔记(持续更新)
如果有错误,请大佬们帮忙指出。
1. Redis支持的数据类型
支持字符串、哈希、列表、集合、有序集合。
2. Redis过期策略和内存淘汰机制(8种)
- 过期策略
Redis是使用定期删除和惰性删除两种配合的过期策略。
所谓定期删除就是每隔一段时间,redis会默认随机抽取一些设置了过期时间的key进行检查,如果过期了,就进行删除。
但有时候定期删除会导致,有一些key过期了却没被删除,这时候就需要配合惰性删除了,当使用这个key的时候,会先检测他有没有过期,如果过期了就会删除掉,不会给你返回任何东西。所以惰性删除,顾名思义就是用到的时候再进行删除。
但有时候会出现这种情况,定期删除没有检测到,惰性删除也没有使用到,这就会积攒了大量的key在内存中,当内训快满的时候就需要配合内存淘汰机制了。 * 内存淘汰机制 + 这个是配置文件中的(新版本(5.0)由6种变为8种)
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
- 网络找的解释
3. 什么是cache aside pattern(边路缓存)?
边路缓存方案的实践,又分为读实践和写实践, * 对于读请求 + 先读缓存,再读数据库 + 如果缓存有数据,则直接返回数据 + 如果缓存没有数据,则去读数据库中的数据,并将数据存到缓存中 * 对于写请求 + 是先操作数据库,在操作缓存好。还是先操作缓存,再操作数据库好 应该是先操作缓存再操作数据库好,因为如果先操作数据库,再操作缓存的时候(delete或set),有可能第一步成功,而第二步失败,就会导致数据库中是新数据,而缓存中是旧数据。 而先操作缓存,再操作数据库,如果第一步失败,直接返回错误,这样就可以确保数据的一致性。 + 那删除缓存好还是还是更新缓存好 如果set的时候,操作缓存成功,而操作数据库失败,就会导致缓存中是新数据而数据库中是旧数据,这样写缓存成功,并不算成功。 如果delete的话,先操作缓存成功,再操作数据库成功,会造成缓存中没有数据,而数据库中是旧数据,这样并不会造成数据的不一致,最多造成下次读取的时候去读取数据库。
4. Redis 支持的持久化策略
Redis支持两种持久化策略,RDB和AOF。 默认的策略模式是RDB,可以在指定的时间间隔内生成数据快照,用户也可以使用同步SAVE和异步BGSAVE手动保存数据,他的优点是数据保存会由一个子进程保存,不会影响到父进程的操作,回复数据的效率也会高于AOF。缺点就是有时redis不可意料的关闭,可能会丢失数据。 AOF是默认关闭的需要手动开启,如果AOF和RDB同时存在,AOF的优先级要高于RDB。 AOF是通过监听执行的命令,如果发现修改了数据的操作,会直接同步到数据库文件中,并记录在日志中,即使遇到突发情况,也无需担心。也导致了他的缺点,性能会低于RDB
5. Spring Redis 集群原理
集群在搭建完成后,由集群节点平分16384个槽,不能平分时,前面的几个节点可以多一个槽,在写代码时吧集群的所有节点都配置上,这样客户就可以访问集群的任意一个节点。当集群在新增或查询一个键值对时,会对key进行Crc16算法得出一个小于16384的值,只在哪个节点上,就操作哪个节点。
6. Redis 缓存击穿
在实际开发中,会考虑redis的服务器的内存压力,所以都会设置key的有效时间。但有可能会出现key正好过期,又同时出现大量并发访问,这些访问就回去访问数据库,这种情况就称为缓存击穿。解决办法是永久数据或加锁,防止出现数据库的并发访问。
7. Redis 缓存穿透
在实际开发中,添加缓存工具就是为了减少访问数据库的次数,提高访问效率,但还是会出现redis中不存在的数据,还是需要频繁的访问数据库,这种就称为缓存穿透,可以通过将查询出来的空数据也缓存进去,只是比正常的有限时间短一些,就可以解决这个问题了。 解决缓存穿透的代码(加锁)
//创建一个锁。final描述 不能再次赋值
private final Lock lock = new ReentrantLock();
//计算几个线程访问过
private ThreadLocal<Integer> nums = new ThreadLocal<>();
@Override
public Map<String, Object> findContens4Portal() {
//先在redis中查询,如果有直接返回,没有的话,再让一个请求去数据库查询,并将数据缓存到数据库中
//需要加锁,防止大量请求并发访问数据库,导致数据库压力大,造成访问慢,最严重有可能宕机
/**
*这是查询redis的代码,有则返回数据,没有继续执行下面的代码
**/
//方法里面写的 准备执行方法之前加锁
//查询数据库的操作,尽量不要并发
//同步代码块加锁
//自旋锁+Lock锁标记
boolean isLocked = this.lock.tryLock();
//没有获得锁标记就等待,等待结束后返回这个方法,重新从redis中获取
if (!isLocked) {
//未获取到锁标记,等待获取锁的线程查询,并保存缓存数据
Integer i = nums.get();
if (i < 0) {
nums.set(i+1);
try {
//睡眠30ms
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//等待结束后,重新调用这个方法
return findContens4Portal();
}
try{
}finally{
//释放锁标记保证后续访问数据库的时候保证可以获取锁标记
lock.unlock();
}
}
8. Redis 缓存雪崩
在一段时间出现大量缓存数据失效,使访问数据库的频率突增,这种情况就叫缓存雪崩。 可以通过设置永久有效时间或者利用算法随机一个有效时间,不让他们同一时间失效来解决这个问题。