本文是我们学院课程的一部分,标题为Redis NoSQL键值存储 。
这是Redis的速成班。 您将学习如何安装Redis并启动服务器。 此外,您将在Redis命令行中乱七八糟。 接下来是更高级的主题,例如复制,分片和集群,同时还介绍了Redis与Spring Data的集成。 在这里查看 !
目录
- 1.简介 2. Redis集群限制 3.分片(分区)方案
- 3.1键哈希标签
4.简而言之,Redis聚类 5.一致性,可用性和可伸缩性 - 5.1一致性 5.2可用性 5.3可扩展性
6.安装具有群集支持的Redis 7.配置Redis集群 - 7.1配置Redis Cluster主节点 7.2配置Redis Cluster从节点和复制 7.3验证Redis集群工作正常 7.4在正在运行的Redis集群中添加和删除节点
8. Redis集群命令 9. Redis前哨 10.下一步是什么
1.简介
本教程的最后部分专门介绍Redis的最新和最酷但仍处于试验阶段(尚未投入生产)的功能-群集。 本部分的内容主要基于Redis文档部分http://redis.io/topics/cluster-tutorial和http://redis.io/topics/cluster-spec 。 Redis集群(或简称为Redis集群)是一种分布式Redis部署,旨在解决以下主要目标:
- 自动在多个节点之间分割数据集的能力
- 提供高性能和线性可扩展性的能力
- 保留来自与大多数节点连接的客户端的所有写操作的能力( 写安全性 / 一致性 )
- 能够在大多数主节点都可访问且每个不再可用的主节点上至少有一个可访问的从节点的网络分区中生存的能力( 可用性 )
Redis Cluster是数据分片(分区)的替代(但更高级)解决方案,我们已经在本教程的第4部分“ Redis Sharding”中看到过(但不是使用第三方工具,所有功能均由Redis本身提供)附加配置)。 为了实现高可用性,Redis Cluster还高度依赖于主从复制,这在本教程的第3部分“ Redis复制”中已经看到。
2. Redis集群限制
首先,与Redis Cluster相关的所有功能都处于实验模式,尚未准备好用于生产。
构建任何高度可用的分布式系统非常困难,但是Redis试图使其成为可能。 有一些局限性需要注意和权衡,我们已经提到了其中一些,但在这里也有必要重复一下。
首先,处理多个按键的命令不被Redis的集群支持( SINTER
, SUNION
,...)。 这种功能需要在Redis节点之间移动数据,这将使Redis Cluster无法在负载下提供可接受的性能和可预测的行为。 通常,在Redis节点中处理命令的键不可用的所有操作都不会实现。
其次,Redis Cluster不支持像独立版本的Redis一样的多个数据库。 只有一个数据库0,并且不允许SELECT
。
第三,Redis集群中的节点不将命令代理到存储给定密钥的正确节点,而是将客户端重定向到服务给定范围的密钥空间的正确节点(所谓的query routing
的混合形式)。 最终,客户端获得群集拓扑的最新表示,并且知道哪个节点提供密钥的哪个子集,可以直接联系正确的节点以发送给定命令(有效地回退到client side partitioning
)。
3.分片(分区)方案
正如我们从第4部分 Redis Sharding中已经知道的那样,有两种数据分片(分区)方案用于拆分数据,而一致性哈希是最先进和广泛使用的方案。 Redis Cluster不使用一致的哈希,而是使用不同形式的数据拆分,每个键都是所谓的hash slot
。
Redis群集中有16384个hash slots
,要计算给定密钥的hash slot
,将计算该密钥的CRC16函数( http://en.wikipedia.org/wiki/Cyclic_redundancy_check ),然后将其模将16384的值应用于其结果。
Redis群集中的每个节点都负责hash slots
的子集。 例如,让我们考虑一个具有四个Redis节点# 1 ,# 2 ,# 3和# 4的集群。 这可能会给我们以下hash slots
分布:
- Redis节点1包含从0到4096的
hash slots
- Redis节点2包含从4097到8192的
hash slots
- Redis节点3包含从8193到12288的
hash slots
- Redis节点4包含从12289到16383的
hash slots
这种分片(分区)方案可以轻松更改群集的拓扑(添加和删除节点)。 例如,如果需要添加新节点#5,则应将来自节点# 1 ,# 2 ,# 3和# 4的一些hash slots
移至节点# 5 。 同样,如果需要从群集中删除节点# 3 ,则应将节点# 3服务的hash slots
移至节点# 1和# 2 。 当节点#3变空时,可以将其从群集中永久删除。
现在最好的部分是:因为将hash slots
从一个节点移动到另一个节点不需要停止正在进行的操作,所以添加和删除节点(或更改节点持有的hash slots
的百分比)不需要停机。
在本教程的后面,我们将回到本示例,并使用三个Redis主节点(每个节点由一个从属节点支持)构建实际的集群。 在Redis Cluster运行期间,我们将添加和删除一些节点,以了解如何实时hash slots
。
3.1键哈希标签
Redis分片(分区)方案支持的非常有趣的功能就是所谓的密钥hash tags
。 Hash tags
是一种确保在同一hash slot
分配两个(或多个)密钥的技术。
为了支持hash tags
, hash slot
以不同的方式计算。 如果键包含“ {…} ”模式,则仅对“ { ”和“ } ”之间的子字符串进行哈希处理,以获得hash slot
(如果出现多次“ { ”或“ } ”密钥名称,会制定一些规则,并在http://redis.io/topics/cluster-spec中进行了描述。
我们在第4部分的 Redis Sharding中玩过的Twemproxy
( nutcracker
)还允许遵循相同的规则集来配置用于hash tags
。
4.简而言之,Redis聚类
在Redis群集中,所有节点都持有全局密钥集的某些部分(碎片或分区)。 此外,每个节点都保持群集的状态(包括hash slots
映射),以便将客户端重定向到给定密钥的正确节点。 Redis群集中的所有节点还能够自动发现其他节点,检测不可达或无法按预期工作的节点,并在需要时执行从属节点以进行主选举。
至于http://redis.io/topics/cluster-spec上描述的实现细节,则集群中的所有节点都使用带有二进制协议的TCP( cluster bus
)进行连接,以便每个节点都连接到该节点中的每个其他节点。使用cluster bus
的cluster bus
(这意味着在N个节点的Redis群集中,每个节点具有N – 1个传出TCP连接和N – 1个传入TCP连接)。 这些TCP连接始终保持活动状态。 节点使用八卦协议( http://en.wikipedia.org/wiki/Gossip_protocol )分散群集状态,发现新节点,确保所有节点均正常工作以及在群集中传播发布/订阅消息。
Redis群集中的每个节点都有唯一的ID(名称)。 节点ID(名称)是160位随机数的十六进制表示,是在节点第一次启动时获得的。 节点会将其ID(名称)保存在节点配置文件中(默认情况下为nodes.conf
),并将永久使用相同的ID(名称)(或至少在不删除节点配置文件的情况下)。
节点ID(名称)用于标识整个Redis群集中的每个节点。 给定节点可以更改其IP地址,而无需也更改其ID(名称)。 群集还能够检测IP或/和端口的更改,并使用在cluster bus
运行的八卦协议广播此信息。 此外,每个节点还具有与之相关的其他信息,Redis群集中的所有其他节点都应知道以下信息:
- 节点所在的IP地址和TCP端口
- 一组标志(主,从,…)
- 节点服务的一组
hash slots
(请参阅分片(分区)方案 ) - 上次使用群集总线发送ping数据包
- 上次收到pong数据包的答复
- 节点被标记为失败的时间
- 该节点的从站数量
- 主节点ID(名称)(如果此节点是从节点)(如果为主节点,则为零)
使用CLUSTER NODES
命令可以使用某些信息(请参阅Redis Cluster Commands部分)。
5.一致性,可用性和可伸缩性
Redis Cluster是一个分布式系统。 好的分布式系统是可扩展的,并且能够大规模提供更好的性能。 但是,在任何分布式系统中,任何组件都可能随时发生故障,并且系统应该提供某些保证,以防发生此类故障(尤其是在它是数据存储的情况下)。 在本节中,我们将简要介绍Redis在一致性,可用性和可伸缩性方面进行的一些高级权衡。 可以在http://redis.io/topics/cluster-spec和http://redis.io/topics/cluster-tutorial中找到更深入的见解和详细信息。 请注意,Redis Cluster的发展非常Swift,本节中讨论的某些保证可能不再成立。
5.1一致性
Redis Cluster无法保证强大的一致性,但是会努力保留客户端执行的所有写入操作。 不幸的是,这并不总是可能的。 由于Redis Cluster在主节点和从节点之间使用异步复制,因此在网络分区期间可能丢失写操作时,总是会有时间窗口。 如果主节点在没有到达从节点的写入的情况下死亡,则写入将永远丢失(以防万一主节点长时间无法访问并且其从节点之一被提升为主节点)。
5.2可用性
Redis群集在网络分区的少数部分不可用。 在网络分区的多数端中,假设每个不可达的主机至少有多数主机和一个从机,Redis群集仍然可用。 这意味着Redis群集可以承受群集中几个节点的故障,但不能承受大型网络分区。 对于示例,让我们考虑具有N个主节点( M1
, M2
, M3
)和N个从属节点( S1
, S2
, S3
,每个主节点都有一个从节点)的Redis集群。 如果由于网络分区而导致任何单个主节点无法访问(假设我们为M2
),则群集的大部分仍将保持可用状态(并且S2
将被提升为主节点)。 以后,如果其他任何主节点或从节点变得不可访问( S2
除外),则群集仍然可用。 但是请注意,如果节点S2
由于某种原因发生故障,则Redis Cluster将无法继续运行(因为主M2
和从属S2
都不可用)。
5.3可扩展性
从分片(分区)方案部分我们已经知道,Redis群集节点不会将命令转发给给定密钥的正确节点,而是重定向客户端。 客户端最终获得完整的映射,其中哪些节点服务于哪个键子集,并且可以直接与正确的节点联系。 因此,Redis Cluster能够线性扩展(添加更多节点可带来更好的性能),因为所有支持的操作的处理方式与单个Redis实例完全相同,而没有额外的开销。
6.安装具有群集支持的Redis
Redis Cluster当前仅在不稳定版本中可用。 撰写本文时,最新的不稳定版本是3.0.0-beta1
,可以从http://redis.io/download下载。 请注意,仅提供Linux发行版,Windows端口尚不可用。
使用集群安装Redis发行版与本教程的第1部分“ Redis安装”中描述的常规Redis安装没有什么不同,并且遵循相同的步骤:
wget https://github.com/antirez/redis/archive/3.0.0-beta1.tar.gz
tar xf 3.0.0-beta1.tar.gz
cd redis-3.0.0-beta1/
make
make test
sudo make install
最后一步之后,通常的Redis可执行文件将安装在/usr/local/bin
文件夹中。
7.配置Redis集群
无法使用常规Redis实例和常规配置创建Redis群集。 相反,应该在特殊的群集模式下运行几个空的Redis实例。 为此,应使用特定于群集的配置来运行实例(应在配置文件中将cluster-enabled
指令设置为“ yes ”),以便启用特定于群集的功能和命令。
运行某些具有群集模式支持的Redis实例所需的最少设置包括以下设置。
-
cluster-enabled
是 (默认: 否 )
为该实例启用Redis集群模式 -
cluster-config-file nodes.conf
(默认值: nodes.conf )
存储此实例的配置的文件的路径。 该文件绝不应该被触碰,它只是由Redis Cluster实例在启动时生成,并在每次需要时进行更新(请参阅Nutshell中的Redis Clustering一节)。 -
cluster-node-timeout
5000
故障检测算法将超时(以毫秒为单位)之后无响应的实例视为发生故障。 正如我们在分片(分区)方案部分中提到的那样,我们将配置和运行一个实时Redis集群,其中包含三个Redis主节点(master1
,master2
,master3
),每个主节点由Redis从属节点(slave1
,slave2
,slave3
)支持,如图所示。下面的图片。
在此过程中,我们将探索大多数Redis集群功能,但在此之前,让我们从配置主服务器和从服务器开始。 为了使配置足够简单,我们将从群集正常运行所需的最低限度的设置开始。
7.1配置Redis Cluster主节点
Redis主节点的最小配置如下所示:
- Redis节点
master1
(redis-master1.conf
)port 6379cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
- Redis节点
master2
(redis-master2.conf
)port 6380cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
- Redis节点
master3
(redis-master3.conf
)port 6381cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
准备好配置文件后,我们可以将配置作为命令行参数,一一启动Redis主节点。
- redis服务器redis-master1.conf
- redis服务器redis-master2.conf
- redis服务器redis-master3.conf
与独立Redis实例的控制台输出相比,有两个值得注意的区别:
- 开始时,每个节点都会生成其
unique ID
( 名称 ),如我们在《 Nutshell中的Redis群集》中所讨论的那样,请注意,此值仅在第一次运行时生成,然后再使用 - 每个实例都以
cluster mode
运行 - 此外,对于每个正在运行的实例,都有一个使用当前
node ID
( name )和一些其他信息创建的nodes.conf
文件。
目前,我们有三个Redis主节点以集群模式运行,但实际上尚未形成集群(每个Redis主节点仅看到自身,而其他节点则看不到)。 为了验证这一点,我们可以在每个实例上单独运行CLUSTER NODES
命令(请参阅Redis Cluster Commands部分),并观察确实如此。
为了形成集群,应使用CLUSTER MEET
命令将Redis节点(以集群模式运行)连接在一起(请参阅Redis集群命令部分)。 不幸的是,该命令仅接受IP地址,但不接受主机名。 在我们的拓扑master1
具有IP地址192.168.1.105, master2
拥有192.168.2.105和master3
具有192.168.3.105。 具有IP地址,让我们对master1
节点发出命令。
现在,如果我们重新运行CLUSTER NODES
命令,结果应该会完全不同。
CLUSTER NODES
命令的输出看起来有点晦涩难懂,需要一些解释,每列的含义。
在输出中未设置最后一列Hash Slots
,这是有原因的:我们尚未将hash slot
分配给主节点,这就是我们现在要做的。 可以通过在特定群集节点上使用CLUSTER ADDSLOTS
命令 (请参阅Redis群集命令 )将Hash slots
分配给节点(分别使用CLUSTER DELSLOTS
分配)。 不幸的是,不可能分配hash slot
范围(如0-5400),而应单独分配每个hash slot
(总数16384中 )。 克服此限制的最简单方法之一是使用一些Shell脚本。 由于集群中只有三个Redis主节点,因此可以这样划分16384个hash slots
的范围:
- Redis节点
master1
包含hash slots
0 – 5400for slot in {0..5400}; do redis-cli -h master1 -p 6379 CLUSTER ADDSLOTS $slot; done;
- Redis节点
master2
包含hash slots
5401 – 10800for slot in {5400..10800}; do redis-cli -h master2 -p 6380 CLUSTER ADDSLOTS $slot; done;
- Redis节点
master3
包含hash slots
10801 – 16383for slot in {10801..16383}; do redis-cli -h master3 -p 6381 CLUSTER ADDSLOTS $slot; done;
如果再次运行CLUSTER NODES
命令,则最后一列将填充每个主节点服务的适当hash slots
(与我们之前分配给节点的hash slot
范围完全匹配)。
7.2配置Redis Cluster从节点和复制
为了使我们的Redis集群完整,我们需要向每个运行的Redis主节点中恰好添加一个从节点。 尽管本教程的第3部分“ Redis复制”足够好地介绍了复制配置,但是Redis集群的做法有所不同。 从一开始,运行和配置从站的过程与主站没有什么不同(唯一的区别是端口号)。
- Redis节点
slave1
(redis- slave1.conf
)port 7379cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
- Redis节点
slave2
(redis-slave2.conf
)port 7380cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
- Redis节点
slave3
(redis-slave3.conf
)port 7381cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
让我们先启动所有三个从属实例,再启动CLUSTER MEET
命令,以便每个节点都将加入我们正在运行的Redis集群。
redis-server redis-slave1.conf
redis-server redis-slave2.conf
redis-server redis-slave3.conf
作为CLUSTER MEET
需要IP地址,我们slave1
具有IP地址192.168.4.105, slave2
拥有192.168.5.105和slave3
有192.168.6.105。
redis-cli -h master1 -p 6379 CLUSTER MEET 192.168.4.105 7379
redis-cli -h master1 -p 6379 CLUSTER MEET 192.168.5.105 7380
redis-cli -h master1 -p 6379 CLUSTER MEET 192.168.6.105 7381
和往常一样,使用CLUSTER NODES
命令,我们可以看到Redis集群中的当前节点(共有六个)。 输出显示所有节点均为主节点。
要配置复制,应通过提供主Node ID
(名称)在每个Redis从属服务器上执行新的CLUSTER REPLICATE
命令。 下表总结了所有一起复制所需的部分(通过查询CLUSTER NODES
命令输出的结果)。
至此,我们的Redis集群已正确配置,并具有我们要创建的拓扑。 CLUSTER NODES
命令显示所有连接到主站的从站。
如我们所见,所有节点都处于健康状态,相互连接并且分配了正确的角色(主节点和从节点)。
7.3验证Redis集群工作正常
与Redis一样,确保Redis集群按预期工作的最佳方法是使用redis-cli
发出一些命令。 请注意,因为集群中的节点不代理命令,而是重定向客户端(请参阅分片(分区)方案 ),所以客户端必须支持这样的协议,这就是为什么redis-cli
应该与-c
命令行选项一起运行(有集群支持):
redis-cli -h master1 -p 6379 -c
让我们尝试设置存储的键(使用SET
命令),然后再查询它们(使用GET
命令)。 因为我们在三个节点之间分配了hash slots
,所以密钥也将分布在所有这些节点上。 名称为some-key
的第一个密钥存储在我们连接到的master1
节点本身上。
但是,如果我们尝试存储名称为some-another-key
,那么将会发生有趣的事情: redis-cli
告诉我们该值将存储在IP地址为192.168.3.105 ( master3
)的节点上保留此键所属的hash slot
。
请注意,命令执行后, redis-cli
将自动重定向到节点192.168.3.105 ( master3
)。 一旦我们在群集节点192.168.3.105 ( master3
)上,我们可以通过发出CLUSTER GETKEYSINSLOT
命令来验证hash slot
确实包含密钥some-another-key。
我们也可以验证的Redis从节点slave3已复制的关键some-another-key
从主( master3
),并返回其值。
7.4在正在运行的Redis集群中添加和删除节点
我们在分片(分区)方案部分中已经提到,Redis集群可以在不停机的情况下进行重新配置,并且通常涉及hash slots
迁移。 让我们向集群添加另一个主节点master4
(IP地址为192.168.7.105 )并将插槽15929从节点master3
到master4
(这是包含密钥some-another-key
的hash slot
)。 她是Redis节点master4
( redis- master4.conf
)配置:
port 6384cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
redis-server redis-master4.conf
redis-cli -h master1 -p 6379 CLUSTER MEET 192.168.7.105 6384
hash slots
迁移过程包括以下阶段:
- 在拥有特定
hash slot
(master3
)的群集节点上,应执行命令CLUSTER SETSLOT slot MIGRATING
,其中是新节点master4
的Node ID
(即d8095be33a2b9d06affcb5583f7150b1341f4c96)。redis-cli -h master3 -p 6381 CLUSTER SETSLOT 15929 MIGRATINGd8095be33a2b9d06affcb5583f7150b1341f4c96
当某个插槽标记为
MIGRATING
,该节点将接受所有有关此hash slot
查询请求,但前提是给定键存在,否则该查询将转发到作为迁移目标的节点。 - 在应成为特定
hash slot
(master4
)的新所有者的群集节点上,命令CLUSTER SETSLOT slot IMPORTING
,其中是当前所有者master3
的Node ID
(即d8a2ae6221624212b76d9cf6c1483452e3c26117)。redis-cli -h master4 -p 6384 CLUSTER SETSLOT 15929 IMPORTINGd8a2ae6221624212b76d9cf6c1483452e3c26117
- 此时,应使用
MIGRATE
命令(请参阅http://redis.io/commands/migrate )将hash slot
所有密钥从当前所有者master3
到新所有者master4
。 因为只有一把钥匙,所以很容易。redis-cli -h master3 -p 6381 MIGRATE master4 6384 some-another-key 0 0
- 最后,当
hash slot
变为空时(可以通过发出CLUSTER GETKEYSINSLOT
命令进行验证),可以将其分配给新节点(master4
)。redis-cli -h master3 -p 6381 CLUSTER SETSLOT 15929 NODEd8095be33a2b9d06affcb5583f7150b1341f4c96
虽然了解详细情况非常有用,但是手动执行这样的过程非常困难且容易出错。 但是Redis Cluster软件包提供了一个方便的实用程序,称为redis-trib
,位于Redis发行版的src
文件夹中。 它是用Ruby编写的,通过简化Redis集群的管理可能会很有帮助(有关更多详细信息,请参见http://redis.io/topics/cluster-tutorial )。
8. Redis集群命令
Redis Cluster添加了另外一组专用于集群管理,监视和配置的命令。 在本教程的第2部分“ Redis命令”中没有涉及这些命令 ,因为它们在稳定版本中尚不可用。 另外,Redis网站上没有足够的文档,但是至少我们可以简要描述每个命令(您已经在实际操作中看到了许多命令)。
9. Redis前哨
Redis的另一个伟大但仍具有实验性的功能是Redis Sentinel
。 该系统旨在帮助管理实时Redis实例,并牢记以下目标:
- 监视 :Sentinel不断检查您的主实例和从实例是否按预期工作
- 通知 :Sentinel能够通知受监视的Redis实例之一是否有问题
- 自动故障转移 :如果某些主节点未按预期工作,则Sentinel可以启动故障转移过程,将其中一个从属节点升级为主节点
Redis Sentinel
是一个非常有前途的功能,但目前正在Redis源代码的不稳定分支中进行开发。 它不是Redis发行版的一部分。
有关更多详细信息,请参见http://redis.io/topics/sentinel 。
10.下一步是什么
在本节中,我们介绍了Redis集群的一个非常吸引人且要求很高的功能。 即使仍在开发中,该功能也足够稳定,可以开始使用它。 在本教程的下一部分中,我们将介绍用于在不同部署方案中访问Redis的编程Java API。
翻译自: https://www.javacodegeeks.com/2015/09/redis-clustering.html