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 手动搭建集群

1
2
3
mkdir my-cluster
cd my-cluster
mkdir node1 node2 node3 node4 node5 node6

给每个节点的文件夹子添加名为redis.conf的配置文件并写入如下内容:

1
2
cluster-enabled yes
port 3000x 

其中x为1到6

然后将集群内的节点联通并分配槽:

1
redis-cli --cluster create 127.0.0.1:30001 127.0.0.1:30002 127.0.0.1:30003 127.0.0.1:30004 127.0.0.1:30005 127.0.0.1:30006 --cluster-replicas 1 

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 重分片

1
2
3
4
5
6
7
redis-cli --cluster reshart <ip:port> 
	--cluster-from <id> 
	--cluster-to <id> 
	--cluster-slots <num>       # 需要迁移的数量 
	--cluster-yes               # 直接确认
	--cluster-timeout <time>     
	--cluster-pipeline <yes/no> # 是否使用流水线 

例如: 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命令添加的新节点将作为主节点存在。如果想使得新节点是从节点,那么可以指定选项:

1
2
--cluster-slave
--cluster-master-id <id> 

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 导入数据

1
2
3
4
5
redis-cli --cluster import
	<host:ip>                # 集群入口节点的ip和port
	--cluster-from <ip:port> # 单机服务器的ip和port
	--cluster-copy           # 导入单机服务器的数据,不删除单机服务器的数据(默认删除)
	--cluster-replace        # 键冲突时,使用导入的键覆盖 

20.6 集群管理命令

除了集群管理程序外,redis还提供了一些以cluster开头的集群命令

redis-cli --cluster命令实际上是由cluster命令实现的

20.6.1 cluster meet 将节点添加至集群

cluster meet ip port

如果节点已经存在某个集群中,那么将会把这个集群全部加入到当前集群中

20.6.2 cluster nodes 查看集群内所有节点的相关信息

cluster nodes 输出行中各项信息的意义: cluster nodes输出行各项意义

节点的角色和状态 节点的角色和状态

槽的数字以及状态 槽的数字以及状态

作为例子,对于以下这个输出行:

1
2
9cd23534bf654a47a2d4d8a4b2717c495ee31b40 127.0.0.1:30001@40001 myself, master -
01541751161000 1 connected 0-5460
  • 这个节点的运行ID为9cd23534bf654a47a2d4d8a4b2717c495ee31b40
  • 它的IP地址为127.0.0.1,客户端端口号为30001,集群端口号为40001
  • 角色和状态部分的myself表示它是客户端正在连接的节点,而master则表示它是一个主节点。
  • 因为这个节点本身就是一个主节点,它没有正在复制的节点,所以它的主节点ID部分为-
  • 节点最近一次发送PING消息的时间戳为0,这表示该节点与其他节点连接正常,并且没有待发送的PING消息;该节点最后一次收到PONG消息的时间戳为1541751161000
  • 这个节点所处的配置纪元为1
  • connected表示这个节点的集群总线连接状态正常
  • 0-5460表示这个节点负责处理槽0至槽5460

再举个例子,如

1
db3a54cfe722264bd91caef4d4af9701bf02223f 127.0.0.1:30006@40006 slave 309871e77eaccc0a4e260cf393547bf51ba11983 0 1541751161694 6 connected
  • 这个节点的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执行时,将对节点执行以下操作:

  1. 遗忘该节点已知的其他节点
  2. 撤销指派给该节点的所有槽,并清空节点内部的槽-节点映射表
  3. 如果执行该命令的节点是从节点,那么将它转换为主节点
  4. 如果是硬重置,那将节点创建一个新的运行id,节点的纪元和配置纪元都设置为0
  5. 通过集群节点配置文件的方式,将新的配置持久化到硬盘上

此命令只能在数据库为空的节点上执行,否则返回错误

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