Redis集群

理论

简介

  1. 能够自动分割数据到不同节点上,扩展存储空间
  2. 能保证一定程度的可用性,当某些节点挂掉或网络不可达时,集群能继续对外提供服务。但当主节点和对应所有从节点都挂掉时,集群不可用

2个端口号

注意:redis集群需要开通2个端口,一个是对外暴露的执行redis命令的端口6379,另一个是节点间通信的内部端口,用来交换数据的,在生产环境要注意开通这2个端口的防火墙,不然集群不能正常工作。

hash槽

redis用了hash槽来实现数据分片,一共有16384个hash槽(0~16383),每个master节点分到其中一部分插槽,通过对key求CRC64校验和,然后对16384求模来得到应该存到哪个插槽。hash槽的好处是方便数据迁移,只要把hash槽对应的数据分给其他节点即可,而且迁移过程不需要停机。另外一个要注意的是,批量操作命令的key要在同一节点中,可以在存储时用大括号指定分组,k1{g1},k2{g2}

数据一致性

redis集群不保证数据的强一致性,主节点和从节点数据复制是异步的,有以下2种场景:

  1. 客户端写入节点A后,还没来得及同步到从节点A1,主节点A挂了,从节点切换成主节点,这时写入的数据丢失
  2. 发生网络分区,客户端和A在同一分区,写入A的数据会丢失。可以配置一个节点超时时间cluster-node-timeout,当某个节点网络不可达超过这个时间时,停止对外提供数据读写,避免大量数据不一致的情况

集群配置

  • cluster-enabled <yes/no>:是否启用集群模式
  • cluster-config-file <filename>:集群配置文件,自动生成的
  • cluster-node-timeout <milliseconds>: 节点超时时间,某个节点和集群其他节点,网络不可达超过这个时间时,会被认为失败,停止对外提供数据读写
  • cluster-slave-validity-factor <factor>:从节点的配置,可以为0或正数,为0 时表示主节点挂掉时,从节点可以取而代之,为正数表示不会取代
  • cluster-allow-reads-when-down <yes/no>:节点失败时,是否仍然能读数据,默认no
  • cluster-migration-barrier :从节点迁移有关的配置(从节点迁移),

操作流程

redis集群的部署只需要2步:

  1. 以集群模式启动各个redis实例
  2. 创建集群

集群模式启动

因为我想创建6个节点,3主3从,依次创建6个目录,如果是生产环境,主节点和从节点不能放在同一机器

drwxr-xr-x. 2 root root 42 Mar 25 14:22 7001
drwxr-xr-x. 2 root root 42 Mar 25 14:22 7002
drwxr-xr-x. 2 root root 42 Mar 25 16:10 7003
drwxr-xr-x. 2 root root 42 Mar 25 16:10 7004
drwxr-xr-x. 2 root root 42 Mar 25 16:10 7005
drwxr-xr-x. 2 root root 42 Mar 25 16:10 7006

每个目录复制配置文件,需要修改的有:端口号、pid文件、日志文件、后台启动、持久化文件路径,另外在REDIS CLUSTER部分增加如下配置:

cluster-enabled yes
cluster-config-file /opt/redis-cluster/7001/nodes.conf
cluster-node-timeout 5000

创建集群

redis 5.0以后可以直接通过redis-cli命令创建集群,redis3、4要通过一个ruby脚本

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

之前已经创建过,不需要重新创建

[ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

cluster nodes查看集群节点,会显示各个节点的node ID、IP、端口号、ping/pong的时间戳、主还是从、连接状态,插槽范围,slave节点还有对应master的nodeID

[root@localhost redis-cluster]# redis-cli -c -p 7001 cluster nodes
db05a3906426f4f18f3e91095268319aadd9cf54 127.0.0.1:7003@17003 master - 0 1616676667000 3 connected 10923-16383
1a6eb06cda839396668b351b2a21bf35a9252877 127.0.0.1:7004@17004 slave 2783fb20f0c7f4894716af706c1438dc104482cf 0 1616676667545 4 connected
08095926ce60ad74e6a47252ed85f8c63af32c1f 127.0.0.1:7002@17002 master - 0 1616676665505 2 connected 5461-10922
ae6e7e4389de5c119a4e86043652233066a5878f 127.0.0.1:7005@17005 slave 08095926ce60ad74e6a47252ed85f8c63af32c1f 0 1616676666000 5 connected
2783fb20f0c7f4894716af706c1438dc104482cf 127.0.0.1:7001@17001 myself,master - 0 1616676666000 1 connected 0-5460
79e13c5bf81b4c344fa9f5ae654e753ecad2de53 127.0.0.1:7006@17006 slave db05a3906426f4f18f3e91095268319aadd9cf54 0 1616676667034 6 connected

访问集群

-c表示集群方式访问,这样读写key时会自动重定向到对应插槽的节点

[root@localhost redis-cluster]# redis-cli -c -p 7001
127.0.0.1:7001> set k1 v1
-> Redirected to slot [12706] located at 127.0.0.1:7003
OK
127.0.0.1:7003> 

集群模式下,跨slot时,批量操作key、同一事务的操作key、lua脚本不支持

127.0.0.1:7003> mset k1 v1 k2 v2 k3 v3
(error) CROSSSLOT Keys in request don't hash to the same slot

如果要批量操作,可以通过大括号指定分组,注意读写都要指定。大括号位置无所谓,比如{group1}.k1、k2{group1}、{group1}.k2,这3个key会分到相同的插槽,可以批量操作

127.0.0.1:7003> mset k1{g1} v1 k2{g1} v2 k3{g1} v3
OK
127.0.0.1:7003> MGET k1 k2 k3
(error) CROSSSLOT Keys in request don't hash to the same slot
127.0.0.1:7003> MGET k1{g1} k2{g1} k3{g1}
1) "v1"
2) "v2"
3) "v3"

集群管理命令

有2类,cluster子命令和–cluster子命令

127.0.0.1:7003> cluster help
 1) CLUSTER <subcommand> arg arg ... arg. Subcommands are:
 2) ADDSLOTS <slot> [slot ...] -- Assign slots to current node.
 3) BUMPEPOCH -- Advance the cluster config epoch.
 4) COUNT-failure-reports <node-id> -- Return number of failure reports for <node-id>.
 5) COUNTKEYSINSLOT <slot> - Return the number of keys in <slot>.
 6) DELSLOTS <slot> [slot ...] -- Delete slots information from current node.
 7) FAILOVER [force|takeover] -- Promote current replica node to being a master.
 8) FORGET <node-id> -- Remove a node from the cluster.
 9) GETKEYSINSLOT <slot> <count> -- Return key names stored by current node in a slot.
10) FLUSHSLOTS -- Delete current node own slots information.
11) INFO - Return onformation about the cluster.
12) KEYSLOT <key> -- Return the hash slot for <key>.
13) MEET <ip> <port> [bus-port] -- Connect nodes into a working cluster.
14) MYID -- Return the node id.
15) NODES -- Return cluster configuration seen by node. Output format:
16)     <id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ... <slot>
17) REPLICATE <node-id> -- Configure current node as replica to <node-id>.
18) RESET [hard|soft] -- Reset current node (default: soft).
19) SET-config-epoch <epoch> - Set config epoch of current node.
20) SETSLOT <slot> (importing|migrating|stable|node <node-id>) -- Set slot state.
21) REPLICAS <node-id> -- Return <node-id> replicas.
22) SLOTS -- Return information about slots range mappings. Each range is made of:
23)     start, end, master and replicas IP addresses, ports and ids

计算key的插槽

127.0.0.1:7003> CLUSTER KEYSLOT k1
(integer) 12706

统计插槽对应多少个key

127.0.0.1:7003> CLUSTER COUNTKEYSINSLOT 12706
(integer) 1

获取插槽中的key

127.0.0.1:7003> CLUSTER GETKEYSINSLOT 12706 5
1) "k1"
[root@localhost ~]# redis-cli --cluster help
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN
                 --cluster-replicas <arg>
  check          host:port
                 --cluster-search-multiple-owners
  info           host:port
  fix            host:port
                 --cluster-search-multiple-owners
  reshard        host:port
                 --cluster-from <arg>
                 --cluster-to <arg>
                 --cluster-slots <arg>
                 --cluster-yes
                 --cluster-timeout <arg>
                 --cluster-pipeline <arg>
                 --cluster-replace
  rebalance      host:port
                 --cluster-weight <node1=w1...nodeN=wN>
                 --cluster-use-empty-masters
                 --cluster-timeout <arg>
                 --cluster-simulate
                 --cluster-pipeline <arg>
                 --cluster-threshold <arg>
                 --cluster-replace
  add-node       new_host:new_port existing_host:existing_port
                 --cluster-slave
                 --cluster-master-id <arg>
  del-node       host:port node_id
  call           host:port command arg arg .. arg
  set-timeout    host:port milliseconds
  import         host:port
                 --cluster-from <arg>
                 --cluster-copy
                 --cluster-replace
  help           

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

reshard的意思是重新分片,把其他主节点的插槽重新分一部分到某个节点,其他节点可以是其他所有节点,也可以部分

redis-cli --cluster reshard <host>:<port> --cluster-from <node-id> --cluster-to <node-id> --cluster-slots <number of slots> --cluster-yes

故障转移

当某个主节点挂掉,对应从节点会成为主节点。如下7002是7005的从节点

ae6e7e4389de5c119a4e86043652233066a5878f 127.0.0.1:7005@17005 myself,master - 0 1616744708000 9 connected 0-499 5461-11422
08095926ce60ad74e6a47252ed85f8c63af32c1f 127.0.0.1:7002@17002 slave ae6e7e4389de5c119a4e86043652233066a5878f 0 1616744708783 9 connected

测试7005挂掉,直接kill也可以

127.0.0.1:7005> DEBUG SEGFAULT
Could not connect to Redis at 127.0.0.1:7005: Connection refused

7002成为主节点,插槽是原先对应主节点插槽

08095926ce60ad74e6a47252ed85f8c63af32c1f 127.0.0.1:7002@17002 master - 0 1616744732009 10 connected 0-499 5461-11422

主节点恢复后,成为新主节点的从节点。大哥东山再起,也只能当小弟了

ae6e7e4389de5c119a4e86043652233066a5878f 127.0.0.1:7005@17005 slave 08095926ce60ad74e6a47252ed85f8c63af32c1f 0 1616744870000 10 connected

节点添加和删除

添加和删除注意都要指定集群任意一个节点的IP和端口号,因为要知道是哪个集群

节点添加分为2种情况:

  1. 添加master,redis-cli --cluster add-node <要加的ip port> <集群任意ip port>
  2. 添加slave,redis-cli --cluster add-node <要加的ip port> <集群任意ip port> --cluster-slave

从节点自动迁移

当redis集群出现孤立主节点时是很脆弱的,一旦它挂了,整个集群就挂了。好消息是从节点支持自动迁移,意思是当出现孤立主节点时,其他从节点可以自动迁移给孤立节点。具体迁移哪一个可以通过cluster-migration-barrier参数配置,默认是1 ,只有数量大于1的从节点才会迁移。这意味着部署集群时,最好让一些主节点的从节点数大于1,从而使得出现孤立节点时,这些大于1的从节点可以自动迁移过来。

先试试孤立节点挂掉,整个集群是否可用。我把7002,7005干掉,在尝试获取数据:

(error) CLUSTERDOWN The cluster is down

集群添加新slave节点7007,作为7002的从节点:

redis-server 7007/redis.conf
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7003 --cluster-slave --cluster-master-id 08095926ce60ad74e6a47252ed85f8c63af32c1f

kill掉7006,此时7003成为孤立节点,过一会后,发现:

6f46d30854e1a64b8d29d478348687c25b6ef03b 127.0.0.1:7007@17007 slave db05a3906426f4f18f3e91095268319aadd9cf54 0 1616914659659 17 connected
db05a3906426f4f18f3e91095268319aadd9cf54 127.0.0.1:7003@17003 master - 0 1616914659558 17 connected 11423-16383

观察到7007自动迁移过去了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值