写点什么

架构词典:缓存

用户头像
lidaobing
关注
发布于: 2020 年 12 月 05 日
架构词典:缓存
  • 这篇想讨论的缓存不是[[redis]]的全部功能,而仅仅是其缓存部分。redis 在架构上其实承担着两个角色,一个是缓存,另一个是内存计算服务。比如实现 HyperLogLog 算法的 PFADD 等指令就属于典型的内存计算服务。

  • 共享的缓存(而不是直接在业务代码中缓存)其实出现得比较早,广泛使用的 [[memcached]] 诞生于 2003 年,是 [[LiveJournal]] 公司为了解决自己的业务问题发明的。

  • 缓存以及后面出现的[[ES]]等全文搜索引擎很大程度缓解了[[数据库]]的压力,甚至改变了数据库在架构中的一些使用方式。比如之前对数据库使用推崇读写分离,但缓存引入之后,数据库的读写量差异已经不大,所以不少设计又回归到在线业务全部使用主库的设计,这个设计更加简单,还能规避掉很多因为数据库主从不一致导致的幻读等问题。ES 则大幅度解放了对数据库索引的需求,引入 ES 后,数据索引一般只用于必要的主键、外键、唯一性约束等场景。

  • 缓存的使用其实需要比较谨慎,因为每引入一处缓存就需要解决一处同步问题。我个人比较喜欢在两端加缓存:API 出口以及紧邻数据库的区域,这两种之外一般还会有第三方调用缓存、计算缓存等场景。

  • 对于 API 出口,一般情况下会设计成对于单个实体的缓存周期略长,但在使用缓存时会先校验关键元素(实体本身以及被引用的其他身体)版本是否变更;对于列表则会设计成较低缓存周期(比如 1-5 分钟),但查询时不做任何检查。

  • 对于紧邻数据库的场景,则需要严肃考虑缓存淘汰机制。一般我缓存的目标会是一个领域对象,而不是简单的数据库的一行。更新领域对象时,会先更新数据库,然后清理缓存。但这种处理方式仍然没法严格保证最终一致性,一般解决方式有三种,a. 设置缓存有效期 b. 用一个延时队列再清理一次缓存 c. 使用分布式事务锁。考虑到 b/c 两种方式成本高,普通场景下用 a 的比较多。这种方式对多中心的设计也比较友好,当多中心数据库同步时,只需要对同步的每一个 Entity 都清理对应的缓存的即可。对于紧邻数据库的列表型缓存,一般也有两种处理手法,一种是短缓存周期存储全部内容;另一种是中缓存周期,但只保存 ID。


发布于: 2020 年 12 月 05 日阅读数: 980
用户头像

lidaobing

关注

还未添加个人签名 2017.10.18 加入

还未添加个人简介

评论

发布
用户头像
该评论已删除
2020 年 12 月 11 日 14:09
回复
OK
2020 年 12 月 11 日 22:00
回复
没有更多了
架构词典:缓存