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