Redis Cluster原理

前言

原本最近打算学习Unix网络编程,可是项目中项目中用到了Redis Cluster,本身对Redis集群这方面并非很熟悉,因此打算花点时间来系统的学习一下Redis,Redis主要分四个部分;
1.数据结构与对象
2.单机数据库实现
3.多机数据库实现
4.独立功能的实现
本文先简单介绍下Redis 的集群实现,后续会针对上面的在进行详解;node

Redis 集群介绍

Redis由于具备丰富的数据结构和超高额性能以及简单的协议,使其可以很好的做用为数据库的上游。可是当数据量变大的时候(如数据达到千万级别时),会受限以多个地方,单机内存有限、单点问题、动态扩容问题等。
为了解决上面的问题,Redis的集群方案就显得比较重要了。使用Redis集群一般有三个途径;redis

  • 官方提供的 Redis Cluster
  • 经过Proxy分片
  • 客户端分片(Smart Client)

本文主要介绍一下官方提供的 Redis Cluster,Redis Cluster 是在Redis 3.0开始支持的,3.0主要是更新了多机方面的功能,在5.0以前Redis Cluster 主要是采用 Redis提供的 redis-trib.rb(Ruby实现的脚本,须要安装相应的依赖环境)这个管理工具。5.0版本开始支持 --cluster 参数来进行管理。数据库

Redis Cluster 数据分片

Redis Cluster 并无使用一致性hash,而是引用了一个叫哈希槽的概念。 Redis Cluster 中有16384个哈希槽,每一个key经过CRC16校验后对16384取模来决定放置哪一个槽。集群的每一个节点分配一部分的哈希槽,这样有一点很方便就是在增长和移除的时候,只须要分配相应的哈希槽就能够了。
在单命令执行下和单机Redis并没有区别,客户端写入命令,由Redis Cluster计算当前key属于哪一个槽点而后返回相应数据。可是多命令的状况下(如求集合的交集)有可能多个key不在同一个槽点里,能够采用{}来设置须要多命令执行的key。{key}:xxx它只对括号里面的进行hash操做,因此能够保证在同一个哈希槽中。编程

Redis Cluster 端口

Redis Cluster 的每一个节点都须要维护两个TCP端口,用于为Redis提供服务的普通端口,例如6370,加上经过向数据端口添加10000得到的端口,如16379。
第二个端口是用于集群总线,使用二进制节点到节点的通讯通道(gossip 协议)。总线端口的偏移量是固定的,始终为10000。节点使用的集群总线主要用来进行故障检测、数据更新、故障转移受权等 。为了保证集群的正常使用,客户端永不该该尝试与集群总线通信,始终使用正常的端口通信。防火墙要打开这两个端口,不然Redis节点将没法通信。服务器

Redis Cluster 故障恢复问题

为了提升可用性,Redis 采用了主从模型,其中每个节点拥有一个master N个slave,若是其中一个节点的 master出现问题,它的一个slave会被选举为master节点。若是某个节点的master和slave所有挂掉,那么这个Redis Cluster将没法服务。其中还有一点须要注意,选举的时候须要有其它一半以上的master节点参加。若是没有一半以上的master节点存活参与选举则slave不会被选举为master。如两个master服务,其中一个挂掉,挂掉服务的slave是不会被选举成为master的,由于存活的master不到一半以上。或者是master恰好分配在一台服务器上,这个服务器挂掉,即便他的slave存在,集群也是没办法将slave节点选举为master节点作到自动故障转移的。因此咱们在分配节点的时候必定要注意合理分配,最好本身分配(默认自动分配)。网络

Redis Cluster 强一致性

首先咱们要知道Redis Cluster 并不提供强一致性。这意味着在某种条件下,Redis 会形成数据丢失。主要缘由是由于Redis Cluster 采用了异步复制:数据结构

  1. 客户端向主机写入
  2. 主机向客户端回复确认
  3. 主机通知该节点的slave设备

基于这种状况,若是出现了上面的故障问题,主机在崩溃后没来得及通知其slave服务,而且这个slave被选为master,那么这个数据则会永久丢失。
Redis Cluster 也支持同步复制,经过WAIT命令实现,这样会大大的下降数据丢失的可能性。但即便是同步复制,也不可能保证强一致性。在更复杂的状况下老是能够实现失败场景,没法接收写入的slave被选为master。
还有另外一个值得注意的状况是,Redis Cluster将丢失写入,这种状况发生在网络分区中 。客户端向节点请求是有最大时间限制(cluster-node-timeout) 不推荐用redis事务机制,由于采用了分片处理。若是一个事物中涉及到多个key的操做的话,这么多个key不必定都存储在同一个节点上。
Redis 分布式锁
若是确实须要强一致性的话能够考虑采用分布式锁:并发

  • 实现逻辑
    在获取锁的时候,使用SETNX加锁,并使用EXPIRE命令为锁添加一个超时时间,超过该事件自动释放锁,锁的value值会随机生成一个UUID,释放锁的时候,经过UUID判断是否是该锁,如果该锁,则释放。若是在执行EXPIRE以前服务挂掉了那么这个锁就永远得不到释放了。能够用SET命令同时设置SETNX和EXPIRE
  • 并发竞争问题 若是不要求执行顺序则让你们去抢锁,抢到了就进行操做。若是须要顺序,能够考虑设置一个时间戳抢到的节点判断当前时间戳是否属于本身,若属于本身在进行操做。
相关文章
相关标签/搜索