分布式缓存

1. 缓存的读写模式和分类

1)缓存的读写模式

(1) 缓存有3种读写模式

  • Cache Aside(旁路缓存)
  • Read/Write(读写穿透)
  • Write Behind Caching(异步缓存写入)

分布式缓存

(2) Cache Aside

分布式缓存

  • 写过程:更新DB => 删除cache => DB驱动缓存数据更新(cache lazy更新,eg: 异步探测DB变更日志,重新计算后进行缓存更新);
  • 读过程:读cache => (cache未使中)读DB => DB数据更新cache(异步);
  • 特点:业务应用方关注cache与DB的读写全过程,写过程cache更新使用lazy机制由DB实时变更更新,高一致性;
  • 适合场景:高一致性需求,缓存数据更新比较复杂(需复杂计算)等;

(2) Read/Write Through

 分布式缓存

  • 写过程:Cache更新(Cache存在的情况先更新) => DB更新  (两者同步更新);
  • 读过程:读cache => (cache未使中)读DB => 回种cache(非异步,同步);
  • 特点:存储服务封装了所有的数据处理细节(cache + DB),业务应用端代码只用关注业务逻辑本身,系统的隔离性更佳, 另外 cache没有数据则不更新,有缓存才更新,内存效率高;
  • 适合场景:数据有明显冷热区分,并对实时性有一定要求。如weibo大V和僵尸的feed列表更新;

(3) Write Behind Caching

 分布式缓存

  • 写过程:Cache更新(Cache存在的情况先更新) => DB更新  (异步批量更新DB);
  • 读过程:读cache => (cache未使中)读DB => 回种cache(非异步,同步);
  • 特点:
    • 优势:1)存储服务封装了所有的数据处理细节(cache + DB),业务应用端代码只用关注业务逻辑本身,系统的隔离性更佳。2)数据存储的写性能高
    • 缺点:1)数据一致性差,极端场景会存在数据丢失问题(eg:比如系统 Crash、机器宕机时,如果有数据还没保存到 DB,则会存在丢失的风险);
  • 适合场景:1) 非常适合一些变更特别频繁的业务,特别是可以合并写请求的业务(eg:一些计数业务,一条 Feed 被点赞 1万 次,如果更新 1万 次 DB 代价很大,而合并成一次请求直接加 1万,则是一个非常轻量的操作)

总结:三种模式各有优劣,不存在最佳模式。实际上,我们也不可能设计出一个最佳的完美模式出来,如同前面讲到的空间换时间、访问延迟换低成本一样,高性能和强一致性从来都是有冲突的,系统设计从来就是取舍,随处需要 trade-off。

2)缓存的分类

(1) 按宿主层次分类

  • 本地Cache: 进程内Cache,读写性能高且无任何网络开销,但容易丢失(进程或应用重启);
    • Ehcache
    • Guava Cache
    • Self Build(自建缓存,如map, set, array等)
  • 进程间Cache: 本机Cache,读写性能较高,可以大幅度减少网络开销,但运维复杂肯与应用程序有资源竞争,也易造成数据丢失且适合无状态应用(机器重启);
    • Memcached
    • Redis
    • Fatcache
    • Pika
    • Others
  • 远程Cache:独立部署,容量大易扩展,但需网络跨机访问,带宽是瓶颈;
    • Memcached
    • Redis
    • Fatcache
    • Pika
    • Others

(2) 按储存介质分类

  • 内存型缓存:数据存储在内存,读写性能好,数据易丢失(但系统重启或是crash后);
    • Memcached
    • Redis
  • 持久化型缓存:数据存储在高速硬盘(SSD/Fusion-IO), 容量比内存型大1个数量级,但读写情能慢1~2个数量级,数据不易丢失(持久化到存储介质了)
    • Pika
    • 其他基于RocksDB开发的缓存组件

2)缓存的架构设计

 未完待续。。。