缓存的使用场景
- 高性能
如果一个mysql查询要600ms、并且查询结果变动不频繁,那么放在缓存比较合适2ms搞定查询。 - 高并发
mysql2000qps是极限了,redis的qps可以到10w的量级。
缓存使用不当可能带来的问题
- 穿透
什么是缓存穿透
有人恶意请求缓存中存在的key,或者key集体过期,导致大量流量直接打到数据库,数据库肯定扛不住
解决方案:
用布隆过滤器
- 雪崩
什么是缓存雪崩
缓存挂了,导致大量流量直接打到数据库,数据库肯定扛不住
解决方案
事前:redis主从+哨兵+集群部署
事中:mysql做限速和降级处理,超过处理能力的请求直接返回空数据。
事后:redis备份,用于快读恢复缓存
- 缓存与数据库双写不一致
把数据库的读写串行化到一个内存队列中,可以做到一致性,但是系统的吞吐能力下降
经典的缓存+数据库读写模式是:cache aside pattern
读的时候先读缓存,没有再度数据库,读到结果先刷新缓存再返回
写的时候先写数据库,再删除缓存/更新缓存
写完了数据库,然后到底是删除缓存还是更新缓存?
这要看你的业务,接下来是不是马上要访问刚才的写入值,删除缓存其本质是缓存lazy加载。
- 并发竞争
Redis为什么单线程还这么快
redis内部使用文件事件处理器、这个处理其实单线程的,所以说redis是单线程的。
为什么单线程还这么快?
- IO多路复用
- 纯内存操作
- 单线程没有现成切换开销
文件事件 处理器包含4部分:
多个socket
io多路复用程序
文件事件分派器
事件处理器
Redis过期策略
redis过期策略:定时删除+惰性删除+内存淘汰机制
定期删除:redis100ms随即抽查一些设置了过期时间的key,如果过期了就直接删除。
惰性删除:访问设置了过期时间的key的时候先检查该key是否已经过去,如果已经过期则删除该key不返回任何值
内存淘汰机制:
noeviction:写入报错
allkeys-lru(最常用)
allkeys-random
volatile-lru
volatile-random
volatile-ttl:最早过期
手写lru?
用hashMap+双向链表
Redis高可用
- 备份
- 主从
- 集群