集中式缓存

这篇文章我们继续聊聊《深入分布式缓存:从原理到实践》中关于集中式缓存的部分。

集中式缓存的基本概念,我在前面的文章 本地缓存 中已经有过介绍,相对于本地缓存,集中式缓存主要有以下几个优点:

  • 保证缓存数据的一致性。集中式缓存的数据是集中管理的,这样就能保证所有应用服务器取到的数据时一致的。
  • 更方便的数据扩容。当缓存数据过多需要扩容时,可以对缓存服务器进行水平扩展。
  • 应对单点故障。如果采用分布式的方式部署缓存服务器,当某一台缓存服务器出现故障时,其它缓存服务器仍然可用。

集中式缓存的使用场景

下面是集中式缓存的典型使用场景。

应用服务器第一次访问时,缓存数据未命中,则从数据库中获取数据并保存到缓存服务器,第二次访问则直接从缓存服务器中获取数据。

20180214001

如果数据有更新,则应用服务器先更新数据库中的数据,再刷新缓存。

20180214002

除了这两中场景,集中式缓存还有很多其它的应用,甚至可以拿来替代一部分数据库的功能,也就是将本来保存在数据库中的数据保存在缓存服务器中。

比如,在缓存中记录登录用户的信息,统计当前登录人数等等,限于篇幅原因在这里就不做展开了,如果大家有兴趣,推荐去看看《Redis IN ACTION》这边书。

常用的集中式缓存系统

目前企业中最常用的集中式缓存系统分别是Memcached和Redis,作者在书中也花费了大量的篇幅对这两个系统进行介绍,下面是它们的简要说明和主要区别。

Memcached是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用。这是一套开放源代码软件,以BSD license授权发布。

Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。

–以上摘选自维基百科

一、基本架构

Memcached采用客户端-服务器的架构,客户端和服务器端之间使用基于文本协议或者二进制协议协议标准。

Memcached服务器维护了一个key-Value关系的数据表,服务器之间相互独立,互相之间不共享数据也不做任何通讯操作,因此客户端需要知道所有的服务器,并自行负责管理数据在各个服务器间的分配。

Redis的基本结构与Memcached类似,但是存在两个重要区别。

  • Redis虽然也是使用key-Value形式保存数据,但是Value的数据结构比Memcached更加丰富,Redis支持String、List,Set, Hashes,Sorted Set五种结构,可以支持更加丰富的应用场景。
  • Redis服务器之间是可以互相通信,共享数据的。客户端只需要知道主服务器就可以了,不用关心数据时如何在各个服务器间分配的。

二、客户端与服务器的交互

Memcached支持同步/异步从服务器端获取数据,部分客户端也支持批量操作。

Redis在Memcached的基础上,还支持事务模式和发布/订阅模式。

  • 事务模式。通过Multi / Watch /Exec等命令可以支持事务的概念,原子性的执行一批命令。
  • 发布/订阅模式。由一个客户端触发,多个客户端被动接收,通过服务器中转,如下图所示: 20180214004

三、数据持久化/备份

Memcached不支持数据持久化,所有数据都是保存在内存中的。没有持久化,好处是数据存储性能消耗更小,坏处是一旦服务器遇到宕机/重启等突发情况,内存中的数据就消失了。

Memcached无法进行数据备份。Memcached各服务器之间是互相独立的,数据没有在各服务器间互相备份,因此很一旦遇到单点故障,故障服务器上所有的数据就都无法访问了。

Redis支持数据持久化,将数据从内存持久化到硬盘中,Redis提供了两种持久化方案。

  • 基于snapshot快照的全量模式。每间隔一段时间就将服务器完整的数据Dump下来存储在本地磁盘文件中。
  • 基于AOF(append-onlu file)的增量模式。记录对数据的修改操作,每间隔一段时间将新增的操作在磁盘文件执行一次。

Redis支持数据备份。通过master-slave模式,将Master节点中的数据定期备份到数台Slave节点上,一旦Master节点出现故障,可以迅速将请求切换到Slave节点,保证系统的可用性。

从数据持久化和备份的角度看,Redis的功能更加丰富,不过很多基于Memcached的项目也做了扩展,在Memcached的基础上封装了持久化和备份的功能。

四、分布式

对于一个集中式的缓存系统,在实际应用中会面临下面的几个挑战:

  • 数据量伸缩。缓存数据的存储量受限于节点实例的内存和磁盘容量,在长期运行的环境中,随着缓存数据的不断增加,节点的存储容量会达到瓶颈。
  • 访问量伸缩。节点能够承担的访问量是有上限的,当业务数据面临超过节点处理能力的高吞吐量需求时,如何提升能力成为难点。
  • 单点故障。如果节点上的数据没有备份,当遇到宕机/重启等情况时,如何保证数据不丢失也是一个重要的挑战。

对于数据量伸缩和访问量伸缩,Memcached可以采用集群的方式解决,通过动态增加/减少服务器的方式来降低压力。单点故障则需要自己进行扩展,Memcached本身并不能很好的解决这个问题。

Redis则是使用基于分布式的解决方案。

  • 水平拆分。与Memcached类似,Redis各节点分为不同的分组,每个分组处理业务数据的一个子集,分组之间的数据无交集。因此可以通过扩充节点方式解决数据量伸缩和访问量伸缩的问题。
  • 主备复制。同一份业务数据存在多个副本,当一个副本出现问题时,还可以对其它副本进行访问操作。
  • 故障转移。当业务数据所在的节点故障时,对这部分业务数据的操作会转移到其它节点上,使得故障节点在恢复期间,对应的业务数据仍然可用。

总结

从上面的对比中,我们可以看出来,Redis与Memcached相比有三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

因此,Redis的使用场景更加丰富,在系统容灾方面也表现更好。但是Memcached也有自己的优势,那就是系统结构更加简单,维护和使用成本比Redis更低。

上篇兩步验证的原理
下篇本地缓存