缓存常规套路:
读:读缓存—— 没有就读数据库——然后返回结果,并写入Cache(因为有人来读以后就还可能被读到,不至于是冷数据)
写:删除缓存—— 更新 DB (可能失败)—— 没有必要更新缓存,因为不一定会有人读这个数据
高并发场景下这种方案可能会出问题:
读非常频繁—— cache已经删除—— 更新DB还没有提交事务—— 其他线程来读缓存—— 没有数据穿透到DB—— 事务还没提交—— 读到旧数据 —— 讲旧数据返回并更新到缓存—— 事务提交成功—— 不一致了。
缓存穿透:
DB里根本就没有这个key的数据,攻击
缓存击穿:(针对一个key)
在平常高并发的系统中,大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。这种现象我们称为缓存击穿。
对策:查询数据库的操作加锁—— 查完DB把数据更新进缓存—— 后续请求进来的时候——查缓存没有——就尝试获取锁——等待直到缓存里有数据。
作者:石杉的架构笔记
链接:https://www.imooc.com/article/283986?from=timeline
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作
缓存雪崩:(多个key)
同一时间多个key失效。大规模缓存失效(也可能是某台缓存服务器挂了导致的)——还好分布式缓存本身就有一些机制来避免这种一台机器挂了导致的大规模缓存失效问题
对策:
(1)设置失效时间为随机值
(2)解决方案分事前+事中+事后
1)事前:采用分布式缓存集群部署一致性hash算法等
避免缓存服务器挂了导致大量缓存失效
Redis分布式缓存的一致性Hash算法:能够保证机器增加或者减少的时候,影响的缓存数据范围最小(只影响挂了这台机器——到下一个节点的机器之间的缓存数据)—— 尤其是后来有了虚拟节点,可以解决热点数据都打到一台机器的问题。
2)事中:开启限流降级预案,使用本地缓存
3)事后:开启Redis持久化机制
参考:https://baijiahao.baidu.com/s?id=1654694618189745916&wfr=spider&for=pc
两种持久化机制:
1- RDB:
优点:以快照的形式把数据全量备份,适合数据恢复,而且比 AOF的恢复速度快
缺点:分主进程和子进程。专门开子进程来进行快照的持久化,但是在子进程持久化期间,父进程修改内存数据,子进程不会感知到,从而可能会丢失数据
2- AOF:
redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
可以设置同步数据的时间间隔:
(1)每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
(2)每秒同步everysec:异步操作,每秒记录 如果一秒内宕机,有数据丢失
优点:
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据
缺点:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。
参考文章:
https://www.imooc.com/article/283986?from=timeline