Redis架构演变与redis-cluster群集读写方案

导言

redis-cluster是近年来redis架构不断改进中的相对较好的redis高可用方案。本文涉及到近年来redis多实例架构的演变过程,包括普通主从架构(Master、slave可进行写读分离)、哨兵模式下的主从架构、redis-cluster高可用架构(redis官方默认cluster下不进行读写分离)的简介。同时还介绍使用Java的两大redis客户端:Jedis与Lettuce用于读写redis-cluster的数据的通常方法。再经过官方文档以及互联网的相关技术文档,给出redis-cluster架构下的读写能力的优化方案,包括官方的推荐的扩展redis-cluster下的Master数量以及非官方默认的redis-cluster的读写分离方案,案例中使用Lettuce的特定方法进行redis-cluster架构下的数据读写分离。java

近年来redis多实例用架构的演变过程

redis是基于内存的高性能key-value数据库,若要让redis的数据更稳定安全,须要引入多实例以及相关的高可用架构。而近年来redis的高可用架构亦不断改进,前后出现了本地持久化、主从备份、哨兵模式、redis-cluster群集高可用架构等等方案。node

一、redis普通主从模式

经过持久化功能,Redis保证了即便在服务器重启的状况下也不会损失(或少许损失)数据,由于持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据。 。可是因为数据是存储在一台服务器上的,若是这台服务器出现硬盘故障等问题,也会致使数据丢失。为了不单点故障,一般的作法是将数据库复制多个副本以部署在不一样的服务器上,这样即便有一台服务器出现故障,其余服务器依然能够继续提供服务。为此, Redis 提供了复制(replication)功能,能够实现当一台数据库中的数据更新后,自动将更新的数据同步到其余数据库上。redis

在复制的概念中,数据库分为两类,一类是主数据库(master),另外一类是从数据库(slave)。主数据库能够进行读写操做,当写操做致使数据变化时会自动将数据同步给从数据库。而从数据库通常是只读的,并接受主数据库同步过来的数据。一个主数据库能够拥有多个从数据库,而一个从数据库只能拥有一个主数据库。
算法

 

主从模式的配置,通常只须要再做为slave的redis节点的conf文件上加入“slaveof masterip masterport”, 或者做为slave的redis节点启动时使用以下参考命令:数据库

redis-server --port 6380 --slaveof masterIp masterPort   

redis的普通主从模式,能较好地避免单独故障问题,以及提出了读写分离,下降了Master节点的压力。互联网上大多数的对redis读写分离的教程,都是基于这一模式或架构下进行的。但实际上这一架构并不是是目前最好的redis高可用架构。缓存

 主从复制过程见下图安全

 

  1. 当一个从数据库启动时,会向主数据库发送sync命令,
  2. 主数据库接收到sync命令后会开始在后台保存快照(执行rdb操做),并将保存期间接收到的命令缓存起来
  3. 当快照完成后,redis会将快照文件和全部缓存的命令发送给从数据库。
  4. 从数据库收到后,会载入快照文件并执行收到的缓存的命令。

 

二、哨兵(Sentinel)模式高可用架构

 

Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案。实际上这意味着你可使用Sentinel模式建立一个能够不用人为干预而应对各类故障的Redis部署。
 
Redis提供的sentinel(哨兵)机制,经过sentinel模式启动redis后,自动监控master/slave的运行状态,基本原理是:心跳机制+投票裁决
  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运做正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 能够经过 API 向管理员或者其余应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工做时, Sentinel 会开始一次自动故障迁移操做, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其余从服务器改成复制新的主服务器; 当客户端试图链接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可使用新主服务器代替失效服务器。

Redis Sentinel 是一个分布式系统, 你能够在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪一个从服务器做为新的主服务器。服务器

能够用info replication查看主从状况 例子: 1主2从 1哨兵,能够用命令起也能够用配置文件里 可使用双哨兵,更安全,参考命令以下:架构

redis-server --port 6379 
redis-server --port 6380 --slaveof 192.168.0.167 6379 
redis-server --port 6381 --slaveof 192.168.0.167 6379
redis-sentinel sentinel.conf 

  

其中,哨兵配置文件sentinel.conf参考以下:app

sentinel monitor mymaster 192.168.0.167 6379 1  

  

其中mymaster表示要监控的主数据库的名字。配置哨兵监控一个系统时,只须要配置其监控主数据库便可,哨兵会自动发现全部复制该主数据库的从数据库。
Master与slave的切换过程:

  1. slave leader升级为master
  2. 其余slave修改成新master的slave
  3. 客户端修改链接
  4. 老的master若是重启成功,变为新master的slave

这里写图片描述 
这里写图片描述 
这里写图片描述 
这里写图片描述 

三、redis-cluster群集高可用架构

即便使用哨兵,redis每一个实例也是全量存储,每一个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,能够采用cluster群集,就是分布式存储。即每台redis存储不一样的内容。
采用redis-cluster架构正是知足这种分布式存储要求的集群的一种体现。redis-cluster架构中,被设计成共有16384个hash slot。每一个master分得一部分slot,其算法为:hash_slot = crc16(key) mod 16384 ,这就找到对应slot。采用hash slot的算法,其实是解决了redis-cluster架构下,有多个master节点的时候,数据如何分布到这些节点上去。key是可用key,若是有{}则取{}内的做为可用key,不然整个能够是可用key。群集至少须要3主3从,且每一个实例使用不一样的配置文件。

 

 

在redis-cluster架构中,redis-master节点通常用于接收读写,而redis-slave节点则通常只用于备份,其与对应的master拥有相同的slot集合,若某个redis-master意外失效,则再将其对应的slave进行升级为临时redis-master。
在redis的官方文档中,对redis-cluster架构上,有这样的说明:在cluster架构下,默认的,通常redis-master用于接收读写,而redis-slave则用于备份,当有请求是在向slave发起时,会直接重定向到对应key所在的master来处理。但若是不介意读取的是redis-cluster中有可能过时的数据而且对写请求不感兴趣时,则亦可经过readonly命令,将slave设置成可读,而后经过slave获取相关的key,达到读写分离。

具体能够参阅redis官方文档(https://redis.io/commands/readonly)等相关内容:

Enables read queries for a connection to a Redis Cluster slave node. Normally slave nodes will redirect clients to the authoritative master for the hash slot involved in a given command, however clients can use slaves in order to scale reads using the READONLY command. READONLY tells a Redis Cluster slave node that the client is willing to read possibly stale data and is not interested in running write queries. When the connection is in readonly mode, the cluster will send a redirection to the client only if the operation involves keys not served by the slave's master node. This may happen because: The client sent a command about hash slots never served by the master of this slave. The cluster was reconfigured (for example resharded) and the slave is no longer able to serve commands for a given hash slot.

 

例如,咱们假设已经创建了一个三主三从的redis-cluster架构,其中A、B、C节点都是redis-master节点,A一、B一、C1节点都是对应的redis-slave节点。在咱们只有master节点A,B,C的状况下,对应redis-cluster若是节点B失败,则群集没法继续,由于咱们没有办法再在节点B的所具备的约三分之一的hash slot集合范围内提供相对应的slot。然而,若是咱们为每一个主服务器节点添加一个从服务器节点,以便最终集群由做为主服务器节点的A,B,C以及做为从服务器节点的A1,B1,C1组成,那么若是节点B发生故障,系统可以继续运行。节点B1复制B,而且B失效时,则redis-cluster将促使B的从节点B1做为新的主服务器节点而且将继续正确地操做。但请注意,若是节点B和B1在同一时间发生故障,则Redis群集没法继续运行。

Redis群集配置参数:在继续以前,让咱们介绍一下Redis Cluster在redis.conf文件中引入的配置参数。有些命令的意思是显而易见的,有些命令在你阅读下面的解释后才会更加清晰。

  1. cluster-enabled :若是想在特定的Redis实例中启用Redis群集支持就设置为yes。 不然,实例一般做为独立实例启动。
  2. cluster-config-file :请注意,尽管有此选项的名称,但这不是用户可编辑的配置文件,而是Redis群集节点每次发生更改时自动保留群集配置(基本上为状态)的文件。
  3. cluster-node-timeout :Redis群集节点能够不可用的最长时间,而不会将其视为失败。 若是主节点超过指定的时间不可达,它将由其从属设备进行故障切换。
  4. cluster-slave-validity-factor :若是设置为0,不管主设备和从设备之间的链路保持断开链接的时间长短,从设备都将尝试故障切换主设备。 若是该值为正值,则计算最大断开时间做为节点超时值乘以此选项提供的系数,若是该节点是从节点,则在主链路断开链接的时间超过指定的超时值时,它不会尝试启动故障切换。
  5. cluster-migration-barrier :主设备将保持链接的最小从设备数量,以便另外一个从设备迁移到不受任何从设备覆盖的主设备。有关更多信息,请参阅本教程中有关副本迁移的相应部分。
  6. cluster-require-full-coverage :若是将其设置为yes,则默认状况下,若是key的空间的某个百分比未被任何节点覆盖,则集群中止接受写入。 若是该选项设置为no,则即便只处理关于keys子集的请求,群集仍将提供查询。

如下是最小的Redis集群配置文件:

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

  

注意:

  1. redis-cluster最小配置为三主三从,当1个主故障,你们会给对应的从投票,把从立为主,若没有从数据库能够恢复则redis群集就down了。
  2. 在这个redis cluster中,若是你要在slave读取数据,那么须要带上readonly指令。redis cluster的核心的理念,主要是用slave作高可用的,每一个master挂一两个slave,主要是作数据的热备,当master故障时的做为主备切换,实现高可用的。redis cluster默认是不支持slave节点读或者写的,跟咱们手动基于replication搭建的主从架构不同的。slave node要设置readonly,而后再get,这个时候才能在slave node进行读取。对于redis -cluster主从架构,若要进行读写分离,官方实际上是不建议的,但也能作,只是会复杂一些。具体见下面的章节。
  3. redis-cluster的架构下,实际上自己master就是能够任意扩展的,你若是要支撑更大的读吞吐量,或者写吞吐量,或者数据量,均可以直接对master进行横向扩展就能够了。也扩容master,跟以前扩容slave进行读写分离,效果是同样的或者说更好。
  4. 可使用自带客户端链接:使用redis-cli -c -p cluster中任意一个端口,进行数据获取测试。
相关文章
相关标签/搜索