缓存雪崩:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7bc801a69db0c2f3b617040c609f97da.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/00b053176f97d09d6de6bd2d2506d376.png)
双写一致性:
看业务需要:
- 强一致:redission读写锁
- 可以允许短暂的数据不一致:延迟双删
- 可以接受一定延时:canal、MQ
延时双删:先删除缓存再更新数据库,再延时删除缓存,一般不是要求强一致性基本采用的这种方式,虽然说在延时这部分时间内,还可能会读到脏数据:更新了数据库,这时还没同步到slave,但这时读了数据,读到的还是旧数据,并吧这个旧数据写到了缓存。
还可以采用Canal和MQ实现最终一致性:canal的话跟我们的代码更解耦。
RDB执行原理:执行bgsave非阻塞的这种方式,会fork一个子进程,将主进程的页表复制一份,由页表找到内存中的数据,然后写入RDB文件,fork采用的是copy-on-write,当此时主进程有写操作时,会拷贝一份数据执行写操作。
Redis数据淘汰策略:
红锁能解决分布式锁的主从一致性吗?
不能,两位大佬的争论,红锁为了实现一致性损耗了性能,与AP思想冲突吧,要保证一致性,可以不使用红锁,只不过我们在代码中定义这种逻辑判断,避免有问题,或者选择CP的zookeeper。
zookeeper的分布式锁怎么实现的?
基于临时的顺序节点和监听机制来实现的分布式锁,因为是顺序节点的方式,如果不是序号最小的节点的话,就会对前一个节点创建监听器,当它释放锁后就会通知自己。
redis哨兵模式脑裂问题:由于master与slave在不同的分区,master这里网络波动,使得sentinel心跳测试不成功了,那么sentinel执行故障转移,重新选出一个master,但是客户端还是对老的master进行操作,当网络恢复过来后,老的master成为新的master的slave,就会造成老的master中的数据的丢失。
解决脑裂
redis中的io模型:
redis基本数据类型
String------>>>SDS 简单字符串
- 缓存json
- 计数(redis是单线程,执行命令过程是原子性的)
- 分布式锁(setNx)
- 共享session信息(避免重复登陆情况)
List--------->>>quickList ,双向链表中每个节点了entry用压缩列表
- 消息队列
set--------->>>> Hashtable、intSet
- 点赞(一个用户只能点一次)
- 共同关注
Hash----->>>压缩列表listpack或哈希表
- 购物车
zSet------>>>跳表 OR 压缩列表
- 最新列表、最新排行榜等更新要求
典型应用场景:
参考博文:https://zhuanlan.zhihu.com/p/631670359
List的场景:
Set应用场景
Hash应用场景:
常常用于用户信息,购物车等管理
以用户id为key,商品id为field,商品数量为value,恰好构成了购物车的3个要素,如下图所示。
Redis发布订阅:实现流程的解耦
口述:Redis发布订阅其实是为了实现流程间的解耦,它是用channel作为沟通的桥梁,发布者发送到对应的channel,而channel又和客户端来绑定,绑定了同一个channel的这些客户端可以接受到相应的消息,底层的结构是用到list来实现的,从而实现这种流程的解耦,也是充当MQ。
Redis延时队列:
延时队列核心是使用到了ZSet的数据结构,score设置为任务执行的时间戳,如果任务的score小于当前时间戳,就执行这个任务,为了保证消费的可靠性,用两阶段消费来保证,就是有两个队列,每次不是直接从zset集合pop出来,而是放入另一个队列,其实这个队列就充当一个保障吧,要根据消费的结果来进行后序操作,消费成功那就可以删除,消费不成功那就需要重新消费,那就从这个队列拿出来放入到原先队列中,等待下次消费。
参考链接:https://mp.weixin.qq.com/s/jJ0vxdeKXHiYZLrwDEBOcQ