Redis 集群搭建和测试教程

来源:互联网 发布:淄博网站排名优化 编辑:程序博客网 时间:2024/06/06 03:19


请注意,本教程使用于Redis3.0(包括3.0)以上版本

Redis集群介绍

Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.Redis 集群的优势:

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群的数据分片

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

  • 节点 A 包含 0 到 5500号哈希槽.
  • 节点 B 包含5501 到 11000 号哈希槽.
  • 节点 C 包含11001 到 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我像移除节点A,需要将A中得槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

Redis 集群的主从复制模型

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.

然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了

不过当B和B1 都失败后,集群是不可用的.

Redis 一致性保证

Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作.

第一个原因是因为集群是用了异步复制. 写操作过程:

  • 客户端向主节点B写入一条命令.
  • 主节点B向客户端回复命令状态.
  • 主节点将写操作复制给他得从节点 B1, B2 和 B3.

主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。注意:Redis 集群可能会在将来提供同步写的方法。Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。

举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .

Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.

注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项:

搭建并使用Redis集群

搭建集群的第一件事情我们需要一些运行在 集群模式的Redis实例. 这意味这集群并不是由一些普通的Redis实例组成的,集群模式需要通过配置启用,开启集群模式后的Redis实例便可以使用集群特有的命令和特性了.

下面是一个最少选项的集群的配置文件:

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

文件中的 cluster-enabled 选项用于开实例的集群模式, 而 cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为 nodes.conf.节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。

要让集群正常运作至少需要三个主节点,不过在刚开始试用集群功能时, 强烈建议使用六个节点: 其中三个为主节点, 而其余三个则是各个主节点的从节点。

首先, 让我们进入一个新目录, 并创建六个以端口号为名字的子目录, 稍后我们在将每个目录中运行一个 Redis 实例:命令如下:

mkdir cluster-testcd cluster-testmkdir 7000 7001 7002 7003 7004 7005

在文件夹 7000 至 7005 中, 各创建一个 redis.conf 文件, 文件的内容可以使用上面的示例配置文件, 但记得将配置中的端口号从 7000 改为与文件夹名字相同的号码。

从 Redis Github 页面 的 unstable 分支中取出最新的 Redis 源码, 编译出可执行文件 redis-server , 并将文件复制到 cluster-test 文件夹, 然后使用类似以下命令, 在每个标签页中打开一个实例:

cd 7000../redis-server ./redis.conf

实例打印的日志显示, 因为 nodes.conf 文件不存在, 所以每个节点都为它自身指定了一个新的 ID :

[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1

实例会一直使用同一个 ID , 从而在集群中保持一个独一无二(unique)的名字。


以上是参考 http://www.redis.cn/topics/cluster-tutorial.html 这里的说明,


下面是我自己的搭建集群环境:

我电脑本来是Centos7系统就直接在这个上面搭建了,就没有去弄虚拟机;

这里用到了我的电脑,在这上面搭建6个节点,创建出3个主节点(master)和3个从节点(slave)

Redis 采用的版本是 redis-3.2.8 版本


安装过程:

1. 下载 Reis 并解压

下载地址:https://redis.io/download

tar -zxvf redis-3.2.8.tar.gz


2. 编译安装

cd redis-3.2.8

make && make install


3. 创建 Redis 节点

首先在安装目录(redis-3.2.8) 下面创建一个 redis-cluster 目录

mkdir redis-cluster

再在 redis-cluster 目录下新建 6 个目录,分别为: 7000 - 7005

mkdir 7000 7001 7002 7003 7004 7005

再将 redis-3.2.8/redis.conf 配置文件 分别拷贝到 7000-7005目录下

cp redis.conf redis-cluster/7000

cp redis.conf redis-cluster/7001

cp redis.conf redis-cluster/7002

cp redis.conf redis-cluster/7003

cp redis.conf redis-cluster/7004

cp redis.conf redis-cluster/7005

再分别修改这些配置文件,修改内容格式如下:

port  7000       //端口7000,7001,7002,7003,7004,7005       bind 本机ip      //默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群,我这里没有配置daemonize    yes                          //redis后台运行pidfile  /var/run/redis_7000.pid          //pidfile文件对应7000,7001,7002,7003,7004,7005  cluster-enabled  yes                      //开启集群  把注释#去掉cluster-config-file  nodes_7000.conf      //集群的配置  配置文件首次启动自动生成 7000,7001,7002,7003,7004,7005cluster-node-timeout  15000               //请求超时  默认15秒,可自行设置appendonly  yes                           //aof日志开启  有需要就开启,它会每次写操作都记录一条日志

4. 将 redis-trib.rb 复制到 /usr/local/bin 目录下

redis-trib.rg 在 src 目录下面

cp redis-trib.rg /usr/local/bin


5. 启动各个节点,如果是分别放在6个电脑上面的话,就可以直接设置成自动启动,不需要我们去启动了。

[root@localhost redis-3.2.8]# redis-server redis-cluster/7002/redis.conf
[root@localhost redis-3.2.8]# redis-server redis-cluster/7003/redis.conf
[root@localhost redis-3.2.8]# redis-server redis-cluster/7004/redis.conf
[root@localhost redis-3.2.8]# redis-server redis-cluster/7005/redis.conf
[root@localhost redis-3.2.8]# redis-server redis-cluster/7006/redis.conf
[root@localhost redis-3.2.8]# redis-server redis-cluster/7001/redis.conf


6. 检查 redis 的启动情况, 可以发现后面有 cluster 标识。

[root@localhost redis-3.2.8]# ps -ef | grep redis

root      1364     1  0 08:51 ?        00:00:02 /usr/local/bin/redis-server 127.0.0.1:6379
root      5916     1  0 09:22 ?        00:00:00 redis-server 127.0.0.1:7000 [cluster]
root      5931     1  0 09:22 ?        00:00:00 redis-server 127.0.0.1:7001 [cluster]
root      6006     1  0 09:24 ?        00:00:00 redis-server 127.0.0.1:7002 [cluster]
root      6013     1  0 09:24 ?        00:00:00 redis-server 127.0.0.1:7003 [cluster]
root      6020     1  0 09:24 ?        00:00:00 redis-server 127.0.0.1:7004 [cluster]
root      6027     1  0 09:24 ?        00:00:00 redis-server 127.0.0.1:7005 [cluster]

7. 搭建集群

现在我们已经有了六个正在运行中的 Redis 实例, 接下来我们需要使用这些实例来创建集群, 并为每个节点编写配置文件。

通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中,

它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。

因为这个工具是个 Ruby 程序,所以需要有 Ruby 的环境,而系统里面没有 Ruby 环境。

  • 安装 Ruby 环境:

安装命令如下:

yum -y install ruby ruby-devel rubygems rpm-build

gem install redis

上面在执行命令:gem install redis 的时候会卡在那里不动,或者报错:ERROR:  While executing gem ... (OpenSSL::SSL::SSLError)
    hostname "upyun.gems.ruby-china.org" does not match the server certificate

于是我在网上就找了下资料,卡在那里不动是由于无法访问网站导致,

所以就使用了淘宝的一个镜像来安装 redis 了,命令如下

[root@localhost bin]# gem sources -a https://ruby.taobao.org/
https://ruby.taobao.org/ added to sources
[root@localhost bin]# gem install redis
ERROR:  While executing gem ... (OpenSSL::SSL::SSLError)
    hostname "upyun.gems.ruby-china.org" does not match the server certificate
[root@localhost bin]# sudo gem install redis

Fetching: redis-3.3.3.gem (100%)

Successfully installed redis-3.3.3
Parsing documentation for redis-3.3.3
Installing ri documentation for redis-3.3.3
1 gem installed

注意:要加 sudo 否在就会报错

ERROR:  While executing gem ... (OpenSSL::SSL::SSLError)
    hostname "upyun.gems.ruby-china.org" does not match the server certificate

原因
是由于openssl的版本过低或者缺少openssl,需要安装openssl包

可以通过命令 openssl -version 来查看是否有 openssl。

我的系统版本如下,应该是版本过低

[root@localhost ~]# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013

可以参考这里的贴文: http://ruby-china.org/topics/3324

如果是要安装 openssl 可以参考:http://blog.csdn.net/huang930528/article/details/51027915

  • 利用工具 redis-trib 创建集群:

输入如下命令: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 就可以了。

[root@localhost redis-3.2.8]# 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
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
M: 3965df7013f41eb1215e4fd9610f6900bbf911a1 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: c30c50d1bdc3112120f638411f8f03bcfad657e8 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 987a19e035237473936819f80d5e2080ce4f5d3c 127.0.0.1:7003
   replicates 3965df7013f41eb1215e4fd9610f6900bbf911a1
S: 10b11408aa6d735b7d6dd3cddad6f9bf3725ff69 127.0.0.1:7004
   replicates fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2
S: 565025fc12f7d731eddf15b49f56d083cc3690ce 127.0.0.1:7005
   replicates c30c50d1bdc3112120f638411f8f03bcfad657e8
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.....
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 3965df7013f41eb1215e4fd9610f6900bbf911a1 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: 10b11408aa6d735b7d6dd3cddad6f9bf3725ff69 127.0.0.1:7004
   slots: (0 slots) slave
   replicates fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2
S: 565025fc12f7d731eddf15b49f56d083cc3690ce 127.0.0.1:7005
   slots: (0 slots) slave
   replicates c30c50d1bdc3112120f638411f8f03bcfad657e8
M: fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 987a19e035237473936819f80d5e2080ce4f5d3c 127.0.0.1:7003
   slots: (0 slots) slave
   replicates 3965df7013f41eb1215e4fd9610f6900bbf911a1
M: c30c50d1bdc3112120f638411f8f03bcfad657e8 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

可以看到自动进行了分配3个master和3个slaver


8. 使用集群

打开一个终端Terminal,连接端口为 7000 节点,因为是在一个系统上,所以可以不用写参数  -h 127.0.0.1

连接方式:redis-cli -h 连接节点绑定的ip -c -p port

参数说明:-h 是配置文件中配置的 bind 后面的IP地址

                    -c 意思是连接到集群

                    -p port 端口

[root@localhost redis-3.2.8]# redis-cli -h 127.0.0.1 -c -p 7000
127.0.0.1:7000> set zero "7000"
-> Redirected to slot [10551] located at 127.0.0.1:7001
OK
127.0.0.1:7001> keys *
1) "zero"
127.0.0.1:7001>



然后再打开一个新的终端 Terminal , 连接端口为7005节点。查看在7000节点上面设置的key的值。

[root@localhost ~]# cd /home/software/redis/redis-3.2.8/
[root@localhost redis-3.2.8]# redis-cli -h 127.0.0.1 -c -p 7005
127.0.0.1:7005> get zero
-> Redirected to slot [10551] located at 127.0.0.1:7001
"7000"
127.0.0.1:7001>

redis-cli 对集群的支持是非常基本的, 所以它总是依靠 Redis 集群节点来将它转向(redirect)至正确的节点。

9. 简单说一下原理

redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。

Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。所以我们在测试的时候看到set 和 get 的时候,直接跳转到了7001端口的节点。我们可以在创建集群的时候擦看分配给主节点的槽的范围,我的是:

M: 3965df7013f41eb1215e4fd9610f6900bbf911a1 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: c30c50d1bdc3112120f638411f8f03bcfad657e8 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 987a19e035237473936819f80d5e2080ce4f5d3c 127.0.0.1:7003
   replicates 3965df7013f41eb1215e4fd9610f6900bbf911a1
S: 10b11408aa6d735b7d6dd3cddad6f9bf3725ff69 127.0.0.1:7004
   replicates fe4601cbb9237b5d6c56c0d1582c15c1cc1144e2
S: 565025fc12f7d731eddf15b49f56d083cc3690ce 127.0.0.1:7005
   replicates c30c50d1bdc3112120f638411f8f03bcfad657e8

Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。

需要注意的是:必须要3个或以上的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了。


好了,至此 Redis 集群的搭建就成功了,测试也OK了。


参考文档:

http://www.redis.cn/topics/cluster-tutorial.html

http://www.cnblogs.com/wuxl360/p/5920330.html

http://blog.csdn.net/liu2012huan/article/details/49909939

http://blog.csdn.net/huang930528/article/details/51027915

http://blog.csdn.net/shuai825644975/article/details/53446621



0 0
原创粉丝点击