前提:先安装好Redis,参考:http://www.cnblogs.com/EasonJim/p/7599941.htmlhtml
说明:Redis Cluster集群模式能够作到动态增长节点和下线节点,使用起来很是的方便。node
下面教程主要是经过官方提供的文档进行搭建测试:mysql
https://redis.io/topics/cluster-tutorialredis
http://www.redis.cn/topics/cluster-tutorial.html算法
http://ifeve.com/redis-cluster-tutorial/sql
http://ifeve.com/redis-cluster-spec/(翻译自官方高级使用教程)数据库
上面中文教程均可以在官方提供的文档中找到。vim
原理应该以下图所示:ruby
注意:如下的搭建教程比较简单,基于伪集群的模式,若是是生产环境能够每台机部署一个实例。操做基本一致。bash
这篇教程是Redis集群的简要介绍,而非讲解分布式系统的复杂概念。它主要从一个使用者的角度介绍如何搭建、测试和使用Redis集群,至于Redis集群的详细设计将在“Redis集群规范”中进行描述。
本教程以redis使用者的角度,用简单易懂的方式介绍Redis集群的可用性和一致性。
注意: 本教程要求Redis3.0或以上的版本。
若是你打算部署Redis集群,你能够读一些关于集群的详细设计,固然,这不是必须的。由这篇教程入门,先大概使用一下Redis的集群,而后再读Redis集群的详细设计,也是不错的选择。
Redis集群 101
Redis集群在启动的时候就自动在多个节点间分好片。同时提供了分片之间的可用性:当一部分redis节点故障或网络中断,集群也能继续工做。可是,当大面积的节点故障或网络中断(好比大部分的主节点都不可用了),集群就不能使用。
因此,从实用性的角度,Redis集群提供如下功能:
- 自动把数据切分到多个Redis节点中
- 当一部分节点挂了或不可达,集群依然能继续工做
Redis集群的TCP端口
Redis集群中的每一个节点都须要创建2个TCP链接,监听这2个端口:一个端口称之为“客户端端口”,用于接受客户端指令,与客户端交互,好比6379;另外一个端口称之为“集群总线端口”,是在客户端端口号上加10000,好比16379,用于节点之间经过二进制协议通信。各节点经过集群总线检测宕机节点、更新配置、故障转移验证等。客户端只能使用客户端端口,不能使用集群总线端口。请确保你的防火墙容许打开这两个端口,不然Redis集群无法工做。客户端端口和集群总线端口之间的差值是固定的,集群总线端口比客户端端口高10000。
注意,关于集群的2个端口:
- 客户端端口(通常是6379)须要对全部客户端和集群节点开放,由于集群节点须要经过该端口转移数据。
- 集群总线端口(通常是16379)只需对集群中的全部节点开放
这2个端口必须打开,不然集群无法正常工做。
集群节点之间经过集群总线端口交互数据,使用的协议不一样于客户端的协议,是二进制协议,这能够减小带宽和处理时间。
Redis集群数据的分片
Redis集群不是使用一致性哈希,而是使用哈希槽。整个Redis集群有16384个哈希槽,决定一个key应该分配到那个槽的算法是:计算该key的CRC16结果再模16834。
集群中的每一个节点负责一部分哈希槽,好比集群中有3个节点,则:
- 节点A存储的哈希槽范围是:0 – 5500
- 节点B存储的哈希槽范围是:5501 – 11000
- 节点C存储的哈希槽范围是:11001 – 16384
这样的分布方式方便节点的添加和删除。好比,须要新增一个节点D,只须要把A、B、C中的部分哈希槽数据移到D节点。一样,若是但愿在集群中删除A节点,只须要把A节点的哈希槽的数据移到B和C节点,当A节点的数据所有被移走后,A节点就能够彻底从集群中删除。
由于把哈希槽从一个节点移到另外一个节点是不须要停机的,因此,增长或删除节点,或更改节点上的哈希槽,也是不须要停机的。
若是多个key都属于一个哈希槽,集群支持经过一个命令(或事务, 或lua脚本)同时操做这些key。经过“哈希标签”的概念,用户可让多个key分配到同一个哈希槽。哈希标签在集群详细文档中有描述,这里作个简单介绍:若是key含有大括号”{}”,则只有大括号中的字符串会参与哈希,好比”this{foo}”和”another{foo}”这2个key会分配到同一个哈希槽,因此能够在一个命令中同时操做他们。
Redis集群的主从模式
为了保证在部分节点故障或网络不通时集群依然能正常工做,集群使用了主从模型,每一个哈希槽有一(主节点)到N个副本(N-1个从节点)。在咱们刚才的集群例子中,有A,B,C三个节点,若是B节点故障集群就不能正常工做了,由于B节点中的哈希槽数据无法操做。可是,若是咱们给每个节点都增长一个从节点,就变成了:A,B,C三个节点是主节点,A1, B1, C1 分别是他们的从节点,当B节点宕机时,咱们的集群也能正常运做。B1节点是B节点的副本,若是B节点故障,集群会提高B1为主节点,从而让集群继续正常工做。可是,若是B和B1同时故障,集群就不能继续工做了。
Redis集群的一致性保证
Redis集群不能保证强一致性。一些已经向客户端确认写成功的操做,会在某些不肯定的状况下丢失。
产生写操做丢失的第一个缘由,是由于主从节点之间使用了异步的方式来同步数据。
一个写操做是这样一个流程:
1)客户端向主节点B发起写的操做
2)主节点B回应客户端写操做成功
3)主节点B向它的从节点B1,B2,B3同步该写操做
从上面的流程能够看出来,主节点B并无等从节点B1,B2,B3写完以后再回复客户端此次操做的结果。因此,若是主节点B在通知客户端写操做成功以后,但同步给从节点以前,主节点B故障了,其中一个没有收到该写操做的从节点会晋升成主节点,该写操做就这样永远丢失了。
就像传统的数据库,在不涉及到分布式的状况下,它每秒写回磁盘。为了提升一致性,能够在写盘完成以后再回复客户端,但这样就要损失性能。这种方式就等于Redis集群使用同步复制的方式。
基本上,在性能和一致性之间,须要一个权衡。
若是真的须要,Redis集群支持同步复制的方式,经过WAIT指令来实现,这可让丢失写操做的可能性降到很低。但就算使用了同步复制的方式,Redis集群依然不是强一致性的,在某些复杂的状况下,好比从节点在与主节点失去链接以后被选为主节点,不一致性仍是会发生。
这种不一致性发生的状况是这样的,当客户端与少数的节点(至少含有一个主节点)网络联通,但他们与其余大多数节点网络不通。好比6个节点,A,B,C是主节点,A1,B1,C1分别是他们的从节点,一个客户端称之为Z1。
当网络出问题时,他们被分红2组网络,组内网络联通,但2组之间的网络不通,假设A,C,A1,B1,C1彼此之间是联通的,另外一边,B和Z1的网络是联通的。Z1能够继续往B发起写操做,B也接受Z1的写操做。当网络恢复时,若是这个时间间隔足够短,集群仍然能继续正常工做。若是时间比较长,以至B1在大多数的这边被选为主节点,那刚才Z1发给B的写操做都将丢失。
注意,Z1给B发送写操做是有一个限制的,若是时间长度达到了大多数节点那边能够选出一个新的主节点时,少数这边的全部主节点都不接受写操做。
这个时间的配置,称之为节点超时(node timeout),对集群来讲很是重要,当达到了这个节点超时的时间以后,主节点被认为已经宕机,能够用它的一个从节点来代替。一样,在节点超时时,若是主节点依然不能联系到其余主节点,它将进入错误状态,再也不接受写操做。
Redis集群参数配置
咱们后面会部署一个Redis集群做为例子,在那以前,先介绍一下集群在redis.conf中的参数。
- cluster-enabled
<yes/no>
: 若是配置”yes”则开启集群功能,此redis实例做为集群的一个节点,不然,它是一个普通的单一的redis实例。- cluster-config-file
<filename>
: 注意:虽然此配置的名字叫“集群配置文件”,可是此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。一般是在收到请求以后这个文件就会被更新。- cluster-node-timeout
<milliseconds>
: 这是集群中的节点可以失联的最大时间,超过这个时间,该节点就会被认为故障。若是主节点超过这个时间仍是不可达,则用它的从节点将启动故障迁移,升级成主节点。注意,任何一个节点在这个时间以内若是仍是没有连上大部分的主节点,则此节点将中止接收任何请求。- cluster-slave-validity-factor
<factor>
: 若是设置成0,则不管从节点与主节点失联多久,从节点都会尝试升级成主节点。若是设置成正数,则cluster-node-timeout乘以cluster-slave-validity-factor获得的时间,是从节点与主节点失联后,此从节点数据有效的最长时间,超过这个时间,从节点不会启动故障迁移。假设cluster-node-timeout=5,cluster-slave-validity-factor=10,则若是从节点跟主节点失联超过50秒,此从节点不能成为主节点。注意,若是此参数配置为非0,将可能出现因为某主节点失联却没有从节点能顶上的状况,从而致使集群不能正常工做,在这种状况下,只有等到原来的主节点从新回归到集群,集群才恢复运做。- cluster-migration-barrier
<count>
:主节点须要的最小从节点数,只有达到这个数,主节点失败时,它从节点才会进行迁移。更详细介绍能够看本教程后面关于副本迁移到部分。- cluster-require-full-coverage <yes/no>:在部分key所在的节点不可用时,若是此参数设置为”yes”(默认值), 则整个集群中止接受操做;若是此参数设置为”no”,则集群依然为可达节点上的key提供读操做。
建立和使用Redis集群
注意:手动部署Redis集群可以很好的了解它是如何运做的,但若是你但愿尽快的让集群运行起来,能够跳过本节和下一节,直接到”使用create-cluster脚本建立Redis集群”章节。
要建立集群,首先须要以集群模式运行的空redis实例。也就说,以普通模式启动的redis是不能做为集群的节点的,须要以集群模式启动的redis实例才能有集群节点的特性、支持集群的指令,成为集群的节点。
下面是最小的redis集群的配置文件(redis.conf):
port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes开启集群模式只需打开cluster-enabled配置项便可。每个redis实例都包含一个配置文件,默认是nodes.conf(启动时会自动生成),用于存储此节点的一些配置信息。这个配置文件由redis集群的节点自行建立和更新,不能由人手动地去修改。
一个最小的集群须要最少3个主节点。第一次测试,强烈建议你配置6个节点:3个主节点和3个从节点。
开始测试,步骤以下:先进入新的目录,以redis实例的端口为目录名,建立目录,咱们将在这些目录里运行咱们的实例。
相似这样:
mkdir cluster-test cd cluster-test mkdir 7000 7001 7002 7003 7004 7005在7000-7005的每一个目录中建立配置文件redis.conf,内容就用上面的最简配置作模板,注意修改端口号,改成跟目录一致的端口。
把你的Redis服务器(用GitHub中的不稳定分支的最新的代码编译来/或者稳定代码)拷贝到cluster-test目录,而后打开6个终端页准备测试。
第一台:
在每一个终端启动一个redis实例,指令相似这样:
cd 7000 ../redis-server ./redis.conf
在日志中咱们能够看到,因为没有nodes.conf文件不存在,每一个节点都给本身一个新的ID。
[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1这个ID将一直被此节点使用,做为此节点在整个集群中的惟一标识。节点区分其余节点也是经过此ID来标识,而非IP或端口。IP能够改,端口能够改,但此ID不能改,直到这个节点离开集群。这个ID称之为节点ID(Node ID)。
第二台:
第三台:
第四台:
第五台:
第六台:
重复第一台的操做。
建立集群
如今6个实例已经运行起来了,咱们须要给节点写一些有意义的配置来建立集群。redis集群的命令工具redis-trib可让咱们建立集群变得很是简单。redis-trib是一个用ruby写的脚本,用于给各节点发指令建立集群、检查集群状态或给集群从新分片等。redis-trib在Redis源码的src目录下,须要gem redis来运行redis-trib。
gem install redis建立集群只需输入指令:
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005这里用的命令是create,由于咱们须要建立一个新的集群。选项”–replicas 1”表示每一个主节点须要一个从节点。其余参数就是须要加入这个集群的Redis实例的地址。
咱们建立的集群有3个主节点和3个从节点。
redis-trib会给你一些配置建议,输入yes表示接受。集群会被配置并彼此链接好,意思是各节点实例被引导彼此通话并最终造成集群。最后,若是一切顺利,会看到相似下面的信息:
[OK] All 16384 slots covered这表示,16384个哈希槽都被主节点正常服务着。
使用create-cluster脚本建立redis集群
若是你不想像上面那样,单独的手工配置各节点的方式来建立集群,还有一个更简单的系统(固然也无法了解到集群运做的一些细节)。
在utils/create-cluster目录下,有一个名为create-cluster的bash脚本。若是须要启动一个有3个主节点和3个从节点的集群,只须要输入如下指令
#1
create-cluster start #2
create-cluster create在步骤2,当redis-trib要你接受集群的布局时,输入”yes”。
如今你能够跟集群交互,第一个节点的起始端口默认是30001。当你完成后,中止集群用以下指令:
create-cluster stop请查看目录下的README,它有详细的介绍如何使用此脚本。
实际操做以下:
版本:4.0.2
下载地址:https://redis.io/download
离线版本:(连接: https://pan.baidu.com/s/1bpwDtOr 密码: 4cxk)
源码编译:
wget http://download.redis.io/releases/redis-4.0.2.tar.gz tar xzf redis-4.0.2.tar.gz cd redis-4.0.2 make
若是不安装到指定位置,那么程序默认放在src文件夹下,
建立集群文件及文件夹:
mkdir cluster-test cd cluster-test mkdir 7000 7001 7002 7003 7004 7005
进入7000建立redis.conf,内容以下:
cd 7000 sudo vim redis.conf #内容 port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
进入7001建立redis.conf,内容以下:
cd 7001
sudo vim redis.conf #内容 port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
进入7002建立redis.conf,内容以下:
cd 7002
sudo vim redis.conf #内容 port 7002 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
进入7003建立redis.conf,内容以下:
cd 7003
sudo vim redis.conf #内容 port 7003 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
进入7004建立redis.conf,内容以下:
cd 7004
sudo vim redis.conf #内容 port 7004 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
进入7005建立redis.conf,内容以下:
cd 7005
sudo vim redis.conf #内容 port 7005 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
分别启动6台集群:
cd 7000
../redis-server ./redis.conf
cd 7001 ../redis-server ./redis.conf
cd 7002 ../redis-server ./redis.conf
cd 7003 ../redis-server ./redis.conf
cd 7004 ../redis-server ./redis.conf
cd 7005 ../redis-server ./redis.conf
建立集群:
先安装ruby
sudo apt-get ruby
进入src文件夹
再经过gem安装redis
cd src gem install redis
若是出现错误,参考:http://www.cnblogs.com/EasonJim/p/7629314.html
启动
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
期间会提示输入yes,而后基本完成。输出的信息上有提示哪些是主节点和从节点。
参考:
http://ifeve.com/redis-cluster-tutorial/(以上内容部分转自此篇文章)
http://blog.csdn.net/fengshizty/article/details/51368004 (节点操做的测试)
http://www.redis.cn/topics/cluster-tutorial.html
http://ifeve.com/redis-cluster-spec/
http://os.51cto.com/art/201512/499551.htm
http://blog.csdn.net/robertohuang/article/details/70766809
http://blog.csdn.net/robertohuang/article/details/70768922
http://blog.csdn.net/robertohuang/article/details/70833231
http://blog.chinaunix.net/uid-28396214-id-4981572.html
http://blog.51yip.com/nosql/1725.html
http://www.cnblogs.com/wuxl360/p/5920330.html
http://blog.csdn.net/men_wen/article/details/72853078