redis
- 如何保证缓存与数据库的双写一致性
- 严格要求一致性:采用读请求和写请求串行化,串到一个内存队列去,会导致内存吞吐量降低
- 不严格要求
- cache aside pattern
- 读的时候先读缓存,缓存没有,读取数据库,放入缓存,返回相应
- 更新先更新数据库(锁表),再删除缓存,缓存设置过期时间
- 为什么删除,缓存不仅仅是数据库数据,
- 更新缓存代价比较好,不频繁数据不需要更新,两个并发写导致脏数据
- 有可能存在写多读少情况,有懒加载思想
- 问题:删除缓存失败,缓存中老数据,数据库中新数据
- 先删除缓存,在更新数据库,并发高也有问题,加锁,
- 设置过期时间,允许短时不一致
- 复杂数据不一致,上亿流量并发,每秒1万读请求,只要1s有写数据请求,就会出现问题
- read /write through pattern
- read through
- 读取数据,缓存中存在返回,缓存不存在,由缓存组件自己加载缓存,返回
- write through
- 写数据,如果,缓存失效,更新数据库,返回,如果缓存不失效,更新缓存,又缓存组件自己同步更新数据库
- read through
- write behind cache pattern
- write
- 写数据,直接更新缓存由缓存组件异步更新数据库,这样数据io操作非常快,而且可以合并多个更新请求
- 缺点:服务器宕机,数据丢失,逻辑复杂
- write
- 为什么需要分布式缓存(redis)
- 本地缓存占用内存空间大
- 一个service多个机器集群部署,负载均衡器发个同一个请求到不同实例,每个实例会建立缓存,浪费
- 分布式系统需要有一个外部缓存,要求内存足够大,io密集型
- 内存大,可以利用数据分片技术,把缓存分不到不同机器,可以无限扩内存
- 命中率,80%算是高
- 缓存牺牲了强一致性
- 缓存过期时间也要设计好,太长浪费内存,太短热点数据频繁更新内存,采用lru
- 爬虫保护机制
- 为什么需要外部缓存,数据库不是有缓存吗?
- 我对mysql比较熟悉,这里说一下
- cache aside pattern
1、 mysql第一种缓存叫sql语句结果缓存,但条件比较苛刻,程序员不可控,
我们的dba线上都关闭这个功能,具体实现可以查一下
2、mysql第二种缓存是innodb buffer pool,缓存的是磁盘上的分页数据,不是sql的查询结果,
sql的执行过程省不了。而mc,redis这些实际上都是缓存sql的结果,两种缓存方式,性能差很远。
因此,可控性,性能是数据库缓存和独立缓存的主要区别