redis-cluster 官方文档


Redis cluster tutorial

Redis集群教程

这个文档是一个平和的介绍 Redis Cluster, 它不是要复杂的来理解分布式系统内容。

它提供了如何设置一个集群,测试和操作它 ,没有涉及redis cluster 特定的细节

然而 这个教材 试图提供信息关于 Redis Cluster 的可用性和一致性行.

注意:这个教材需要Redis 3.0或者以上版本:

如果你计划运行一个Redis Cluster  部署

Redis Cluster 101


Redis Cluster  提供一种方式来运行一个Redis 安装,数据是自动分片到多个Redis nodes.


Redis Cluster 也提供一些可用性 在分区之间,

实际上是 有能力在当一些节点失败 或者不能通讯时 仍旧能提供操作


然而 集群停止操作 ,万一大量的节点失败(比如 当master的大多数是不可用)

那么从实际意义上讲,Redis集群有什么好处呢?


在多个及诶单之间自动分片你的数据

当节点的一部分故障或者不能通讯,有能力即系提供服务

Redis Cluster TCP ports

每个Redis Cluster 节点需要2个TCP 连接打开,通常Redis TCP port 是用于服务clients,

例如 6379, 加上1000得到数据端口,因此 16379

第2个端口使用 Cluster bus,那是一个node-to-node 通讯通道使用一个2进制协议

Cluster 总线是用于节点间故障检测,配置升级 故障转移等

cliet 不能尝试和cluster bus port 通讯,总是和normal Redis command port 通讯

确保 你打开两个端口在你的防火墙,否则  Redis cluster nodes 不能通讯

命令端口和cluster bus 端口偏移量是固定的,始终是10000


请注意 一个Redis cluster 集群正常工作,你必须为每个节点:

正常的client 通讯端口(通常是6379) 用于和客户端通讯 打开用于所有的客户端 可以到达集群,

加上所有其他集群节点(使用客户端端口用于keys迁移)

集群节点(client port 加上10000)必须是从所有其他节点可达的

Redis 集群数据分片

Redis Cluster  不使用一致性hashing,但是一个不同的分片形式,每个key 是hash slot的一部分


这里有16384 个hash slots 在 Redis Cluster,为了计算一个给定key 是在哪个hash slot 






192.168.137.4:7004> CLUSTER nodes
bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 192.168.137.4:7005@17005 master - 0 1585427745845 24 connected 5461-10922
1b83e27acd5235726aea44702526a8ca0ede9a48 192.168.137.2:7000@17000 slave 9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 0 1585427744837 26 connected
3c6510bd29af80703ae7c0be5a5884caaa60cd4e 192.168.137.2:7001@17001 slave a7287834bc7db37249614d23e06ed8f9a6c7b3d3 0 1585427746348 14 connected
191d7306b81ffa85b5837898562eb6bf1479122c 192.168.137.3:7002@17002 slave,fail bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 1585427709565 1585427709532 24 connected
a7287834bc7db37249614d23e06ed8f9a6c7b3d3 192.168.137.4:7004@17004 myself,master - 0 1585427744000 14 connected 10923-16383
9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 192.168.137.3:7003@17003 master,fail - 1585427709565 1585427709532 26 connected 0-5460

0到16383



Redis cluster 的每个节点是负责hash slots的一部分,例如 我们可能有一个cluster 有3个节点:

Node A contains hash slots from 0 to 5500.
Node B contains hash slots from 5501 to 11000.
Node C contains hash slots from 11001 to 16383.



这个允许增加和删除节点很轻松,比如 你需要增加一个节点D  我么需要移动一些hash slots 从A,B,C 到D

类似的 如果我们需要移动节点A从集群 我们只需要移动hash slots 从A到B和C  

当节点A 是被请空 我们可以从集群中完全删除

因为移动hash slots 从一个节点到另外节点不需要停止操作,增加和删除节点,或者改变节点持有的hash slots的比例 不需要任何down机时间


Redis Cluster  支持多个key 操作只要所有的keys 是通过单个命令执行(或者整个事务,或者lua 脚本执行)
中涉及的所有密钥都属于同一个哈希槽。

Redis Cluster master-slave model Redis集群 主从模式

为了保持仍旧可用 当主节点的一部分是故障或者不能和大多数节点通讯,

Redis Cluster 使用一个 master-slave模式每个hash slot 有1到N个副本

在我们的例子中集群有节点A,B,C ,如果节点B故障 集群是不能继续,

因为我们没有办法继续提供服务 hash slots 在5501-11000之间的hash slots

然而 当集群被创建(或者稍后)  我们增加一个slave 节点到每个master,

这样 最后的集群是有A,B,C是master节点 A1,B1,C1 是slaves节点 系统可以继续如果节点B故障

节点B1复制到B,如果B故障 集群会选取节点B1 作为新的master 或继续正常操作

但是注意 如果节点B和B1同时故障 集群不能继续工作


Redis集群一致性保证

Redis Cluster 是不能保证强制一致性的。 实际上 这意味着某些情况下 它是可能丢失写的 


第一个原因 为什么Redis Cluster 能丢失写 是因为使用异步复制,这个意味着写的过程中发生如下情况:

1.你的客户端写到MASTER B

2.MASTER B 回复OK给你的客户端

3.MASTER B 传播写到slaves B1,B2和B3

如你所见,B 不能等待一个确认 从B1B2,B3 在回复给客户端之前

因为这个会是一个禁止性延迟惩罚 对于Redis

如果你的client 写一些东西, B 确认写,但是故障发生在你发送写到它的slave之前 

slaves中的一个(没有收到写)被选择成master,永久的丢失写



这是非常简单的 大多数数据库 配置成每秒刷新数据到磁盘

因此这是一个方案 你已经可以知道原因因为过去传统的数据库系统的经验没有涉及分布式系统

简单的 你可以改善一致性通过强制数据库刷新数据到磁盘 在回复给客户端之前 这个通常会导致性能低下

基本上,在性能和一致性之间需要权衡:

Redis Cluster 也支持同步写 当需要时,通过WAIT 命令,这个让丢失写可能性大大降低,但是注意 


Redis Cluster  不会实现强一致性 即使当同步复制被使用 在更复杂的故障情况下,一个slae 不能收到写被选举为master



另外一个值得注意的场景 Redis Cluster 会丢失写,这个发生在一个网络分区 当一个client 是和少数实例包含至少一个master 隔离


让我们以6个节点的集群为例,它有A,B,C ,A1,B1,C1 使用3个主节点和3个slaves节点。

有一个客户端,叫做Z1


在一个分区发生后,它是可能 在分区的一边 我们有A, C, A1, B1, C1,  在另外一段我们有B和Z1

Z1 仍旧能写给B ,能接收它的写。如果分区在很短的时间内恢复,集群能正常工作

然而如果分区持久足够的时间对于B1 来促使B1 成为master ,写Z1发送到B会丢失


注意 有一个最大窗口到写到Z1的总量可以发送到B  如果足够的事件已经被消耗对于分区的大多数 选组一个slave成为master

每个master节点 在少数端 停止接收写请求


这个时间是非常重要的配置指令,被称为node timeout



在节点超时已经发生,一个master 节点是被认为是故障的,可以被它的副本替换。

类似的在节点超时已经发生 不需要一个主节点是被感知 其他主节点的大多数 

Redis Cluster configuration parameters


我们将创建一个集群部署示例。在继续之前, 让我们介绍Redis Cluster 的配置参数在redis.conf file. 

有些是会很明显的,有些会随着你继续阅读而更加清晰

cluster-enabled  yes

cluster-enabled <yes/no>: 如果是yes,启用Redis Cluster 支持一个特定的Redis instance

否则  示例启动作为一个单独的实例

cluster-config-file nodes.conf

cluster-config-file <filename>: 注意尽管这个选项的名字, 但是不是用户编辑的配置文件,

但是这个文件 一个Redis Cluster 节点自动保存cluster 配置(状态,基本上的) 在每次改变时

以便在启动的时候重新读取它。

文件列出的事情像其他节点的信息在集群中,它们的状态,持久化变量 

通常 这个文件是重写和刷新 因为一些信息反映

cluster-node-timeout <milliseconds>:  毫秒

最大时间  一个Redis Cluster 节点可以是不可用的,没有被认为是故障

如果一个master 节点 不可达 大于指定的事件 它会通过slaves进行故障转移。

这个参数控制其他重要的事情 尤其,每个节点 不能达到大多数节点 ,会停止接收查询

cluster-slave-validity-factor <factor>: 

如果设置为0, 一个slave 会总是尝试古装转移一个master,

不管时间长短 连接在Master和slave之间保持断开状态。

如果值为正, 最大的断开时间是被计算作为节点超时时间乘以这个选项

如果节点是一个slave,它不会尝试 开始一个故障转移 如果 master 连接是断开 超时特定时间。


例如,如果节点超时是设置为5秒, 有效因子是设置为10

一个slave 断开master 超过50秒 不会尝试故障转移它的master 

请注意,任何值不等于0 会导致 Redis Cluster 变为不可达 在一个master 故障 

如果没有slave可以故障转移它  只有当原始主节点重新加入集群时,集群才会返回可用状态。



cluster-migration-barrier <count>: slaves的最小数量 一个master 必须保持连接状态

Creating and using a Redis Cluster


创建和使用一个Redis Cluster


注意:

要手动部署一个Redis Cluster这是非常重要的了解操作方面的东西

要创建集群, 第一件事我们需要有一些空的Redis instances 运行在cluster mode

这个基本意味着 clusters 不是使用普通的redis 实例来创建 因为需要配置特定的模式 

这样redis 实例会启用Cluster 特定的功能和命令

以下是最小的REDIS 集群配置文件:

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

node1:/root/cluster/7001#netstat -na | grep 700
tcp        0      0 192.168.137.2:7000          0.0.0.0:*                   LISTEN      
tcp        0      0 192.168.137.2:7001          0.0.0.0:*                   LISTEN      
tcp        0      0 192.168.137.2:17000         0.0.0.0:*                   LISTEN      
tcp        0      0 192.168.137.2:17001         0.0.0.0:*                   LISTEN   


正如你所看到的,启用集群模式的只是cluster-enabled 指令。

每个实例也可以包含 文件的路径 节点配置文件存放的位置 默认是nodes.conf

这个文件不是人为创建的, 它是在Redis Cluster instances 启动的时候创建的,


请注意 ,按预期工作的最小集群至少需要3个master节点。 对于你首先测试的 它是强烈推荐启动一个6个节点的集群 

使用 3个masters 和3个slaves

为此,请输入一个新目录,创建下面的目录 

mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005

在每个目录中创建一个redis.conf file,从7000 到 7005

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

node1:/opt/redis/data/7000#ls
appendonly.aof  dump.rdb  nodes.conf
node1:/opt/redis/data/7000#cat nodes.conf 
9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 192.168.137.3:7003@17003 master,fail - 1585496423812 1585496423812 26 connected 0-5460
3c6510bd29af80703ae7c0be5a5884caaa60cd4e 192.168.137.2:7001@17001 slave a7287834bc7db37249614d23e06ed8f9a6c7b3d3 0 1585496430857 14 connected
a7287834bc7db37249614d23e06ed8f9a6c7b3d3 192.168.137.4:7004@17004 master,fail? - 1585496423838 1585496423812 14 disconnected 10923-16383
1b83e27acd5235726aea44702526a8ca0ede9a48 192.168.137.2:7000@17000 myself,slave 9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 0 1585496430000 23 connected
bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 192.168.137.4:7005@17005 master,fail? - 1585496423838 1585496423812 24 disconnected 5461-10922
191d7306b81ffa85b5837898562eb6bf1479122c 192.168.137.3:7002@17002 slave,fail bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 1585496423812 1585496423812 24 connected
vars currentEpoch 27 lastVoteEpoch 24

Creating the cluster


现在 我们有很多运行的实例,我们需要创建我们的就请你通过写一些有用的配置到节点:

如果你使用Redis 5, 这是非常简单的完成 因为我们通过Redis Cluster command line utility

对于Redis 版本3或者4,有一个称为redis-trib.rb的工具,非常类似

你可以在scr目录下扎到,你需要安装redis gem 来运行 redis-trib.

gem install redis


第一个例子, 集群创建, 在redis 5 中使用redis-cli


redis-trib in Redis 3 and 4. 

然而接下来的所有示例 我们都使用 redis-cli,  因为你可以看到语法是类似的 

要使用Redis cli为Redis 5创建集群,只需键入:



redis-cli --cluster create 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 \
--cluster-replicas 1

Using redis-trib.rb for Redis 4 or 3 type:

./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



这个命令使用在这里是创建,因为我们需要创建一个新的集群。

这个选项  --cluster-replicas 1 意味着 我们需要一个slave对于每个创建的master

另外的参数是实例的地址列表 

显然 我么的要求是创建一个由3主3从的cluster

Redis-cli 会提议你一个配置,接收建议的配置通输入 yes

集群会被配置和加入,这意味着 实例会被引导大相互交流中


测试故障转移:

注意: 在这个测试期间,你应该打开一个tab open 使用一致性测试应用

为了触发故障转移,最简单的事情我们需要做(也就是分布式系统可能发生的 最简单的故障)是使单个进程崩溃,

在我们的例子中是单个主进程:




我们可以通过以下命令识别一个master 然后让他崩溃:

$ redis-cli -p 7000 cluster nodes | grep master
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0 connected 5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0 connected 11423-16383
97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422


node1:/root#redis-cli -h 192.168.137.2 -p 7000 cluster nodes | grep master
9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 192.168.137.3:7003@17003 master - 0 1585502413836 26 connected 0-5460
a7287834bc7db37249614d23e06ed8f9a6c7b3d3 192.168.137.4:7004@17004 master - 0 1585502412324 14 connected 10923-16383
bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 192.168.137.4:7005@17005 master - 0 1585502414342 24 connected 5461-10922



所以7000,7001和7002 是主节点,让我们crash 节点7002 使用 DEBUG SEGFAULT command:

node1:/root#redis-cli -h 192.168.137.2 -p 7000 cluster nodes | grep master
9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 192.168.137.3:7003@17003 master - 0 1585502413836 26 connected 0-5460
a7287834bc7db37249614d23e06ed8f9a6c7b3d3 192.168.137.4:7004@17004 master - 0 1585502412324 14 connected 10923-16383
bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 192.168.137.4:7005@17005 master - 0 1585502414342 24 connected 5461-10922
node1:/root#
node1:/root#
node1:/root#
node1:/root#redis-cli -h 192.168.137.2 -p 7000 cluster nodes | grep master
9809b72ec290d73d99a3e1b0d12c4c7bf8583c45 192.168.137.3:7003@17003 master,fail - 1585502528397 1585502525874 26 disconnected
a7287834bc7db37249614d23e06ed8f9a6c7b3d3 192.168.137.4:7004@17004 master - 0 1585502532945 14 connected 10923-16383
1b83e27acd5235726aea44702526a8ca0ede9a48 192.168.137.2:7000@17000 myself,master - 0 1585502530000 29 connected 0-5460
bf0edaba80c4f31e9b56101572d2a5ccc8aa145c 192.168.137.4:7005@17005 master - 0 1585502532541 24 connected 5461-10922



正如你在故障转移期间看到的,系统不能接收578次读和577次写,

然而 数据库中没有不一致被创建。

我们现在检查 故障转移后的集群设置(注意,同时我们重新启动了崩溃的实例这样它重新加入cluster 作为一个slave)

Manual failover

手动故障转移:

发布了3883 篇原创文章 · 获赞 120 · 访问量 360万+

猜你喜欢

转载自blog.csdn.net/zhaoyangjian724/article/details/105184944