Ubuntu 16.04下Redis Cluster集群搭建(官方原始方案)
前提:先安装好Redis,参考:http://www.cnblogs.com/EasonJim/p/7599941.html
说明:Redis Cluster集群模式可以做到动态增加节点和下线节点,使用起来非常的方便。
下面教程主要是通过官方提供的文档进行搭建测试:
https://redis.io/topics/cluster-tutorial
http://www.redis.cn/topics/cluster-tutorial.html
http://ifeve.com/redis-cluster-tutorial/
http://ifeve.com/redis-cluster-spec/(翻译自官方高级使用教程)
上面中文教程都可以在官方提供的文档中找到。
原理应该如下图所示:
注意:以下的搭建教程比较简单,基于伪集群的模式,如果是生产环境可以每台机部署一个实例。操作基本一致。
这篇教程是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
http://blog.csdn.net/xu470438000/article/details/42971091
http://www.cnblogs.com/gomysql/p/4395504.html
Ubuntu 16.04下Redis Cluster集群搭建(官方原始方案)的更多相关文章
- Ubuntu 16.04 下Redis Cluster集群搭建
实际操作如下: 准备工作 版本:4.0.2 下载地址:https://redis.io/download 离线版本:(链接: https://pan.baidu.com/s/1bpwDtOr 密码: ...
- centos6下redis cluster集群部署过程
一般来说,redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口,比如:slaveof 192.168.10.10 6379,然后启动主从,主从 ...
- Redis Cluster集群搭建与应用
1.redis-cluster设计 Redis集群搭建的方式有多种,例如使用zookeeper,但从redis 3.0之后版本支持redis-cluster集群,redis-cluster采用无中心结 ...
- Redis Cluster集群搭建与配置
Redis Cluster是一种服务器sharding分片技术,关于Redis的集群方案应该怎么做,请参考我的另一篇博客http://www.cnblogs.com/xckk/p/6134655.ht ...
- Redis Cluster集群搭建<原>
一.环境配置 一台window 7上安装虚拟机,虚拟机中安装的是centos系统. 二.目标 Redis集群搭建的方式有多种,根据集群逻辑的位置,大致可以分为三大类:基于客户端分片的Redis ...
- ubuntu 16.04快速安装ceph集群
准备工作 假设集群: 选一台作管理机 注意: ceph集群引用hostname,而非ip. 172.17.4.16 test16 #hostname必须是test16 172.17.4.17 test ...
- Redis Cluster 集群搭建与扩容、缩容
说明:仍然是伪集群,所有的Redis节点,都在一个服务器上,采用不同配置文件,不同端口的形式实现 前提:已经安装好了Redis,本文的redis的版本是redis-6.2.3 Redis的下载.安装参 ...
- 【Redis】Redis cluster集群搭建
Redis集群基本介绍 Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施installation. Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行 ...
- Redis Cluster集群搭建后,客户端的连接研究(Spring/Jedis)(待实践)
说明:无论是否已经搭建好集群,还是使用什么样的客户端去连接,都是必须把全部IP列表集成进去,然后随机往其中一个IP写. 这样做的好处: 1.随机IP写入之后,Redis Cluster代理层会自动根据 ...
随机推荐
- 一个简单的Java代码生成工具—根据数据源自动生成bean、dao、mapper.xml、service、serviceImpl
目录结构 核心思想 通过properties文件获取数据源—>获取数据表的字段名称.字段类型等—>生成相应的bean实体类(po.model).dao接口(基本的增删改查).mapper. ...
- 【Python】第一个爬虫
import urllib.request import re class DownPic: def __init__(self,url,re_str): self.url = url self.re ...
- 套接字、UDP通信、TCP通信、TCP/IP协议簇
一.套接字(socket) 1.英语单词socket:n.插座:穴:v.插入插座 2.套接字就是源IP地址和目的IP地址.源端口号和目的端口号的组合,是通过传输层进行通信的.IP指定电脑,端口指定某一 ...
- zabbix基础安装
环境依赖:LNMP或者LAMP 简介参考:http://blog.51cto.com/zhang789/1868880 一.准备 我安装的环境及其版本如下: 系统版本 CentOS Linux rel ...
- json 存 window.localStorage.setItem('hideColums',hideArr);
onColumnSwitch:function(row, $element){ //JSON.parse() var showColumns=$('#table').bootstrapTable('g ...
- Django 外键ForeignKey中的on_delete
当你在Django中删除了一个有着外键关联的数据时,比如一个作者和他名下的所有的书的信息,书的外键是作者(一个作者可有好多本书),当你把作者的信息从数据库中删除时,Django提供了一下几个参数来对作 ...
- mysql创建中文编码库
[2013/5/27 16:06:08] LuoXingchen: Create MySQL Database with Chinese supported: mysql> cre ...
- Day 14A 网络编程入门
---恢复内容开始--- 计算机网络基础 计算机网络是独立自主的计算机互联而成的系统的总称,组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享.今天计算机网络中的设备和计算机网络的用户已经 ...
- 记录一次通过命令行方式来使用svn碰到的一系列问题
由于使用Xcode自带的svn管理碰到很多问题,搞得头昏脑胀,找资料时看到小码哥这方面的视频,看完就开始折腾了. 准备:1.远程仓库地址及授权账号(用户名和密码) 2.一份项目代码,之所以要有这份代码 ...
- [Luogu] P3846 [TJOI2007]可爱的质数
题目描述 给定一个质数P(2<=P<2312^{31}231),以及一个整数B(2<=B<P),一个整数N(2<=N<P). 现在要求你计算一个最小的L,满足BL≡ ...