redis3.0正式引入集群功能
20.1 基本特性
- 复制与高可用
- redis集群与单机版redis一样,也提供主从复制功能,同时也提供类似sentinel一样的功能
- redis集群中,主节点负责处理客户端发送的读写请求,从节点负责对主节点进行复制
- 分片与重分片
- 与单机版将整个数据库放在同一个数据库上不同,redis集群通过将数据库分散存储到多个节点上来平衡各个节点的负载压力
- redis集群会将整个数据库空间划分为16384个槽(slot),而集群中各个主节点则会分别负责处理其中一部分槽。
- 当用户尝试将一个键存储到集群中时,客户端会先计算出所有键所属的槽,然后根据槽-节点映射表找到对应节点
- 当用户想向集群中发送添加新节点的命令后,集群会将相应的槽以及槽中存储的数据迁移至新节点。当用户移除节点时,也会将该节点的数据转交给其他节点。整个重分片过程都可以在线进行,无需停机
- 高性能
- redis集群采用无代理模式,客户端发送的所有命令都会直接交由节点执行,并且对于经过优化的集群客户端来说,客户端发送的命令在绝大部分情况下都不需要实施转向,或者仅需一次转向,因此在redis集群中执行命令的性能与单机上执行非常接近
- 除了节点间互通信息带来的性能损耗外,单个redis集群节点处理命令请求的性能与单个redis服务器处理命令请求的性能几乎别无二致。
- 从理论上来讲,集群每增加一倍数量的主节点,集群对于命令请求的性能就会提高一倍
- 简单易用
20.2 搭建集群
两种方式搭建集群。一是使用源码附带的集群自动搭建程序create-cluster
,二是使用配置文件手动搭建集群
20.2.1 使用create-cluster
创建
./create-cluster start
创建6个节点
./create-cluster create
把6个节点组合成一个集群,包含3个主节点,3个从节点
./create-clust stop
关闭
连接集群时,需要指定参数redis-cli -c -p <port>
如果接收到命令请求的节点并目标节点,那么客户端将根据节点提示的转向信息再次向正确的节点发送命令请求(这个过程被称为转向redirect)。(类似于dns,告诉客户端目标地址,而不是转发请求)
20.2.2 手动搭建集群
|
|
给每个节点的文件夹子添加名为redis.conf
的配置文件并写入如下内容:
|
|
其中x为1到6
然后将集群内的节点联通并分配槽:
|
|
20.3 散列标签
redis提供散列标签(hash tag)功能,该功能会找出键中第一个被大括号{}
包围并且非空的子字符串用来计算该键所属的槽。例如{user}:123
可以使用命令cluster keyslot <key>
来查看key会被分配至哪个槽
20.4 打开/关闭从节点的读命令执行权限
集群的从节点在默认情况下只会对主节点进行复制,不会处理客户端的任何请求 如果从节点接收到请求命令,那么会将客户端重定向到主节点
但是,redis向用户提供了READONLY
用来将从节点设置为可读,用READWRITE
来关闭可读
命令只对执行了该命令的客户端有效
20.5 使用redis-cli管理集群
redis-cli --cluster help
查看命令列表
20.5.1 创建集群
redis-cli --cluster create <ip1:port1> ... <ipn:portn> --cluster-replicas <num>
20.5.2 查看集群信息
redis-cli --cluster info <ip:port>
20.5.3 检查集群
redis-cli --cluster check <ip:port>
检查集群配置是否正确,槽是否以及被全部分配
20.5.4 修复槽错误
当集群在重分片、负载均衡、槽迁移的过程中出现错误时,执行fix命令可以让设计的槽重新回到正常状态:redis-cli --cluster fix <ip:port>
fix命令会检查各个节点处于“导入中”和“迁移中”状态的槽,并根据情况将槽迁移至更合理的一方
20.5.5 重分片
|
|
例如:
redis-cli --cluster reshard <ip:port> --cluster-from <id1> --cluster-to <id2> --cluster-slots <num>
会先用check命令检查一次集群,确保集群和槽都处于正常状态,然后给出一个重分片计划,并询问我们的意见。
20.5.6 负载均衡
redis-cli --cluster rebalance <ip:port>
对各个节点的槽数量进行平衡
用户可以设置节点的权重,使得其被分配更多槽,默认情况下每个节点的默认权重为1.0,设置为0将导致它被撤销所有的槽指派从而成为一个空节点
如果想对为被指派槽的空节点进行分配,可以使用选项--cluster-use-empty-masters
rebalance命令会根据节点目前槽数量以及权重计算每个节点应该负责的槽数量的期望值。如果这个期望值与节点目前负责的槽数量的比率超过指定的阈值,将触发重分配操作。阈值默认为2.0。
用户可以指定选项--cluster-threshold <value>
来设置阈值
rebalance命令在执行负载均衡操作时会逐一对节点的槽数量进行调整,如果想同时进行可以指定选项--cluster-simulate
20.5.7 添加节点
redis-cli --cluster add-node <new_host:port> <existing_host:port>
在默认情况下,add-node命令添加的新节点将作为主节点存在。如果想使得新节点是从节点,那么可以指定选项:
|
|
20.5.8 移除节点
redis-cli --cluster del-node <ip:port> <node_id>
20.5.9 执行命令
通过call子命令,可以在整个集群的所有节点上执行给定命令:
redis-cli --cluster call host:port command arg1 ...
20.5.10 设置超时时间
通过set-timeout子命令可以为集群所有节点重新设置cluster-node-timeout
选项的值:
redis-cli --cluster set-timeout <host:port> <milliseconds>
20.5.11 导入数据
|
|
20.6 集群管理命令
除了集群管理程序外,redis还提供了一些以cluster开头的集群命令
redis-cli --cluster
命令实际上是由cluster
命令实现的
20.6.1 cluster meet
将节点添加至集群
cluster meet ip port
如果节点已经存在某个集群中,那么将会把这个集群全部加入到当前集群中
20.6.2 cluster nodes
查看集群内所有节点的相关信息
cluster nodes
输出行中各项信息的意义:
节点的角色和状态
槽的数字以及状态
作为例子,对于以下这个输出行:
|
|
- 这个节点的运行ID为9cd23534bf654a47a2d4d8a4b2717c495ee31b40
- 它的IP地址为127.0.0.1,客户端端口号为30001,集群端口号为40001
- 角色和状态部分的myself表示它是客户端正在连接的节点,而master则表示它是一个主节点。
- 因为这个节点本身就是一个主节点,它没有正在复制的节点,所以它的主节点ID部分为-
- 节点最近一次发送PING消息的时间戳为0,这表示该节点与其他节点连接正常,并且没有待发送的PING消息;该节点最后一次收到PONG消息的时间戳为1541751161000
- 这个节点所处的配置纪元为1
- connected表示这个节点的集群总线连接状态正常
- 0-5460表示这个节点负责处理槽0至槽5460
再举个例子,如
|
|
- 这个节点的ID为db3a54cfe722264bd91caef4d4af9701bf02223f,它是一个从节点,它的IP地址为127.0.0.1,客户端端口号为30006,集群端口号为40006
- 这个节点正在复制的主节点的运行ID为309871e77eaccc0a4e260cf393547bf51ba11983
- 这个节点最后一次发送PING消息的时间戳为0,这表示该节点与其他节点的连接正常,并且没有待发送的PING消息;而它最后一次接收到PONG消息的时间戳为1541751161694
- 这个节点所处的配置纪元为6
- connected表示这个节点的集群总线的连接状态正常
- 这个节点是一个从节点,它没有被指派任何槽,所以槽信息部分为空
20.6.3 cluster myid
查看当前节点的运行id
查看当前客户端连接的节点的id
20.6.4 cluster info
查看集群信息
20.6.5 cluster forget node-id
从集群中移除节点
cluster forget
命令引发的节点移除消息不会通过Gossip
协议传播至集群的其他节点:
- 当用户想一个节点发送
cluster forget
命令时,接收到命令的节点只是暂时屏蔽用户指定的节点,其他节点仍然可见 - 想让集群真正移除这个节点,需要在60s内向集群中所有节点都发送相同的
cluster forget
命令,否则被暂时屏蔽的节点会因为Gossip协议重新添加到集群中
20.6.6 cluster replicate
将节点变为从节点
cluster replicate master-id
将当前节点复制为master-id的从节点:
- 用户给定的主节点必须与当前节点位于相同的集群中
- 如果当前节点是一个主节点,那么它必须没有被指派任何槽,并且数据库不能有数据
- 如果当前节点已经是一个从节点,那么它将清空数据库,并开始复制用户给定的节点
20.6.7 cluster replicas
查看给定节点的所有从节点
cluster replicas node-id
接受一个节点id作为参数,然后返回该节点属下所有从节点相关信息
20.6.8 cluster failover
强制执行故障转移
用户可以通过向从节点发送cluster failover [force|takeover]
命令,让它发起一次对自身主节点的故障转移操作
接收到命令的从节点会先将自身数据库更新至与主节点完全一致,然后再执行后续的故障转移操作
如果用户尝试想主节点发送该命令,将返回一个错误
在给定force
选项时,从节点将不尝试与主节点进行握手,直接实施故障转移
即使给定force
选项,从节点对主节点的故障转移也需要经过集群中大多数主节点同意才能真正执行。但如果给定takeover
选项,那么从节点将不再询问,直接实施故障转移。
20.6.9 cluster reset [soft|hard]
重置节点
默认使用soft选项
cluster reset
执行时,将对节点执行以下操作:
- 遗忘该节点已知的其他节点
- 撤销指派给该节点的所有槽,并清空节点内部的槽-节点映射表
- 如果执行该命令的节点是从节点,那么将它转换为主节点
- 如果是硬重置,那将节点创建一个新的运行id,节点的纪元和配置纪元都设置为0
- 通过集群节点配置文件的方式,将新的配置持久化到硬盘上
此命令只能在数据库为空的节点上执行,否则返回错误
20.7 槽管理命令
20.7.1 cluster slots
查看槽与节点之间的关联信息
20.7.2 cluster addslots
把槽指派给节点
20.7.3 cluster delslots
撤销对节点的槽指派
20.7.4 cluster flushslots
撤销对节点的所有槽指派
20.7.5 cluster keyslot
查看键所属的槽
20.7.6 cluster countkeysinslot
查看槽包含的键的数量
20.7.7 cluster
getkeysinslot 获取槽包含的键
20.7.8 cluster setslot
改变槽的状态
没意思,TODO