Redis的应用场景
Redis数据丢失 ap
持久化,RDB就会有个时间区的丢失,aof默认会有1s
淘汰策略(用户已知的)
主从切换(主从同步是异步的)
sentinel脑裂:当因为网络问题发生分区容错的时候,会有2个master,2个master都可以写数据,并且2个master之间不会同步数据,那么当网络恢复后,有一个master就会变成slave,那么里面写入的数据就会丢失。
所以Redis尽量不要用来做业务逻辑处理,数据是不可靠的。
尽可能避免产生数据一致性问题,min-replicas-to-write至少多少个从节点
Redis与DB的数据一致性问题
并发场景下,可能出现redis与DB的数据不一致问题
假如mysql数据发生变更,需要做缓存依赖(删除redis的key)
redis与DB数据一致性怎么产生?并发情况下原子性问题(db的操作与redis操作不是原子的)
双删
不可取的强一致性方案
延时双删:核心思想是删除的时候等待其他线程执行完毕,性能差了,延时多久?
加锁:不存在原子性问题,但是牺牲了性能
最终一致性方案
每个缓存设置过期时间而不是永久key(缓存时间的不一致)
canal,通过mysql的binlog拿到变更的数据,同步给相关的redis缓存
如果要保证敏感数据的可靠,数据必须从DB拿
缓存雪崩、穿透、击穿
缓存雪崩
redis挂了或者redis大量的数据同时过期或失效,并发很高,全部call向DB
解决办法:
保证redis高可用,尽量防止redis挂掉:集群cluster、哨兵
设置不同的过期时间,随机过期,避免大量数据同时过期
缓存穿透
恶意攻击
查询的key,redis里没有,db里也没有,导致每次请求都会走DB
解决办法:
找运维,针对恶意攻击,封IP
通过布隆过滤器存储db数据的标识,hash + bitmap实现,最小的空间
布隆过滤器缺陷:能判断一个数据一定不存在,但是不能保证一定存在(因为可能hash冲突),最坏的情况是没有数据,查一次DB
解决办法:
增加hash次数,减少误判率
增加bitmap位图大小
缓存击穿
单个key过期的时候,大量并发请求这个key
解决办法:互斥锁,DCL,但是不建议,因为redis的初衷就是性能
慢查询
多慢才是慢?是可配置的
slowlog-log-slower-than 10000 //单位是微妙,默认10毫秒,正数代表界限,负数代表禁用,0表示每个指令都会记录
slowlog-max-len 128 //记录的最大长度,最多存储多少慢查日志
指令慢:比如hgetall keys *
大对象:建议拆分成多个子对象,不要超过10K,具体根据业务量而定
Redis阻塞
业务日志记好,降级,报警系统
外部原因:网络阻塞,CPU
内存原因:指令查询耗时长,如keys *
数据结构不合理,导致指令耗时过大
fork子进程阻塞:aof同步刷盘