架构词典:缓存

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这篇想讨论的缓存不是[[redis]]的全部功能,而仅仅是其缓存部分。redis在架构上其实承担着两个角色,一个是缓存,另一个是内存计算服务。比如实现 HyperLogLog 算法的 PFADD 等指令就属于典型的内存计算服务。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"共享的缓存(而不是直接在业务代码中缓存)其实出现得比较早,广泛使用的 [[memcached]] 诞生于 2003年,是 [[LiveJournal]] 公司为了解决自己的业务问题发明的。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缓存以及后面出现的[[ES]]等全文搜索引擎很大程度缓解了[[数据库]]的压力,甚至改变了数据库在架构中的一些使用方式。比如之前对数据库使用推崇读写分离,但缓存引入之后,数据库的读写量差异已经不大,所以不少设计又回归到在线业务全部使用主库的设计,这个设计更加简单,还能规避掉很多因为数据库主从不一致导致的幻读等问题。ES则大幅度解放了对数据库索引的需求,引入ES后,数据索引一般只用于必要的主键、外键、唯一性约束等场景。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缓存的使用其实需要比较谨慎,因为","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"每引入一处缓存就需要解决一处同步问题","attrs":{}},{"type":"text","text":"。我个人比较喜欢在两端加缓存:API出口以及紧邻数据库的区域,这两种之外一般还会有第三方调用缓存、计算缓存等场景。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对于API出口,一般情况下会设计成对於单个实体的缓存周期略长,但在使用缓存时会先校验关键元素(实体本身以及被引用的其他身体)版本是否变更;对于列表则会设计成较低缓存周期(比如1-5分钟),但查询时不做任何检查。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对于紧邻数据库的场景,则需要严肃考虑缓存淘汰机制。一般我缓存的目标会是一个领域对象,而不是简单的数据库的一行。更新领域对象时,会先更新数据库,然后清理缓存。但这种处理方式仍然没法严格保证最终一致性,一般解决方式有三种,a. 设置缓存有效期 b. 用一个延时队列再清理一次缓存 c. 使用分布式事务锁。考虑到 b/c 两种方式成本高,普通场景下用a的比较多。这种方式对多中心的设计也比较友好,当多中心数据库同步时,只需要对同步的每一个Entity都清理对应的缓存的即可。对于紧邻数据库的列表型缓存,一般也有两种处理手法,一种是短缓存周期存储全部内容;另一种是中缓存周期,但只保存ID。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章