CNET 2020-01-05
为每一个集群的节点准备一个配置文件:
# 7000.conf port 7000 bind 192.168.1.181 daemonize yes pidfile 7000.pid cluster-enabled yes cluster-config-file 7000_node.conf cluster-node-timeout 15000 appendonly yes
# 7001.conf port 7001 bind 192.168.1.181 daemonize yes pidfile 7001.pid cluster-enabled yes cluster-config-file 7001_node.conf cluster-node-timeout 15000 appendonly yes
# 7002.conf port 7002 bind 192.168.1.181 daemonize yes pidfile 7002.pid cluster-enabled yes cluster-config-file 7002_node.conf cluster-node-timeout 15000 appendonly yes
以上三个配置文件都在192.168.1.181机器上,三个集群节点分别绑定的端口为7000、7001、7002。相当于三台redis服务器。
在另外一台机器192.168.1.180上,同样也准备三个redis服务:
# 7003.conf port 7003 bind 192.168.1.180 daemonize yes pidfile 7003.pid cluster-enabled yes cluster-config-file 7003_node.conf cluster-node-timeout 15000 appendonly yes
# 7004.conf port 7004 bind 192.168.1.180 daemonize yes pidfile 7004.pid cluster-enabled yes cluster-config-file 7004_node.conf cluster-node-timeout 15000 appendonly yes
# 7005.conf port 7005 bind 192.168.1.180 daemonize yes pidfile 7005.pid cluster-enabled yes cluster-config-file 7005_node.conf cluster-node-timeout 15000 appendonly yes
这三个redis服务跑在192.168.1.180机器上,使用7003、7004、7005端口。
使用第一节中的6个配置文件,分别在两台机器上启动6个redis实例(服务)。
[ ~]# redis-server ./7000.conf 1855:C 05 Jan 2020 22:29:55.465 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1855:C 05 Jan 2020 22:29:55.465 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1855, just started 1855:C 05 Jan 2020 22:29:55.465 # Configuration loaded [-base ~]# redis-server ./7001.conf 1860:C 05 Jan 2020 22:30:01.587 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1860:C 05 Jan 2020 22:30:01.587 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1860, just started 1860:C 05 Jan 2020 22:30:01.587 # Configuration loaded [-base ~]# redis-server ./7002.conf 1865:C 05 Jan 2020 22:30:03.438 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1865:C 05 Jan 2020 22:30:03.438 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=1865, just started 1865:C 05 Jan 2020 22:30:03.438 # Configuration loaded
[ ~]# redis-server ./7003.conf 21201:C 05 Jan 2020 22:35:57.144 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21201:C 05 Jan 2020 22:35:57.144 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=21201, just started 21201:C 05 Jan 2020 22:35:57.144 # Configuration loaded [-base ~]# redis-server ./7004.conf 21206:C 05 Jan 2020 22:35:59.415 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21206:C 05 Jan 2020 22:35:59.415 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=21206, just started 21206:C 05 Jan 2020 22:35:59.415 # Configuration loaded [-base ~]# redis-server ./7005.conf 21211:C 05 Jan 2020 22:36:01.211 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21211:C 05 Jan 2020 22:36:01.211 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=21211, just started 21211:C 05 Jan 2020 22:36:01.211 # Configuration loaded
查看进程:
root 1856 1 0 22:29 ? 00:00:00 redis-server 192.168.1.181:7000 [cluster] root 1861 1 0 22:30 ? 00:00:00 redis-server 192.168.1.181:7001 [cluster] root 1866 1 0 22:30 ? 00:00:00 redis-server 192.168.1.181:7002 [cluster] root 1871 1403 0 22:30 pts/0 00:00:00 grep --color=auto redis
root 21202 1 0 22:35 ? 00:00:00 redis-server 192.168.1.180:7003 [cluster] root 21207 1 0 22:35 ? 00:00:00 redis-server 192.168.1.180:7004 [cluster] root 21212 1 0 22:36 ? 00:00:00 redis-server 192.168.1.180:7005 [cluster] root 21217 9126 0 22:36 pts/0 00:00:00 grep --color=auto redis
执行以下命令创建集群:
[ src]# redis-cli --cluster create --cluster-replicas 1 192.168.1.181:7000 192.168.1.181:7001 192.168.1.181:7002 192.168.1.180:7003 192.168.1.180:7004 192.168.1.180:7005 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.1.180:7005 to 192.168.1.181:7000 Adding replica 192.168.1.181:7002 to 192.168.1.180:7003 Adding replica 192.168.1.180:7004 to 192.168.1.181:7001 M: 0e8ad6ec3c1dbd9bc4aa7571717b98f2eddfae7f 192.168.1.181:7000 slots:[0-5460] (5461 slots) master M: b42102dab52497b36ed5b768b01463b09f7e7eab 192.168.1.181:7001 slots:[10923-16383] (5461 slots) master S: 75a547cdad955d5b77812fb7db7b276594cdcde2 192.168.1.181:7002 replicates 6fa4cbb6d52841c91a0e9f747e5b906a8b6f10b1 M: 6fa4cbb6d52841c91a0e9f747e5b906a8b6f10b1 192.168.1.180:7003 slots:[5461-10922] (5462 slots) master S: 00e3e7ed62c230ebbafb15ab5a7194ca28221112 192.168.1.180:7004 replicates b42102dab52497b36ed5b768b01463b09f7e7eab S: 240f6cc79a637db17d35d39edd42475484ca56ad 192.168.1.180:7005 replicates 0e8ad6ec3c1dbd9bc4aa7571717b98f2eddfae7f Can I set the above configuration? (type ‘yes‘ to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ....... >>> Performing Cluster Check (using node 192.168.1.181:7000) M: 0e8ad6ec3c1dbd9bc4aa7571717b98f2eddfae7f 192.168.1.181:7000 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: b42102dab52497b36ed5b768b01463b09f7e7eab 192.168.1.181:7001 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: 6fa4cbb6d52841c91a0e9f747e5b906a8b6f10b1 192.168.1.180:7003 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 240f6cc79a637db17d35d39edd42475484ca56ad 192.168.1.180:7005 slots: (0 slots) slave replicates 0e8ad6ec3c1dbd9bc4aa7571717b98f2eddfae7f S: 75a547cdad955d5b77812fb7db7b276594cdcde2 192.168.1.181:7002 slots: (0 slots) slave replicates 6fa4cbb6d52841c91a0e9f747e5b906a8b6f10b1 S: 00e3e7ed62c230ebbafb15ab5a7194ca28221112 192.168.1.180:7004 slots: (0 slots) slave replicates b42102dab52497b36ed5b768b01463b09f7e7eab [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
注意,在命令中,我们使用了 --cluster-replicas 1 ,这个表示每一个主节点配一个从节点。所以将6个redis实例,分成了3个主,3个从。
其中主节点为7000、7001、7003。他们的从节点分别是:7005、7004、7002。
注意,redis一共有16384个slots,用于存储数据。
当我们只有一个redis服务的时候,所有的数据都存放在这些槽里面。
而当我们使用集群的时候,例如上述的3个主节点,那么这16384个槽会分配到三台主节点中。(注意上述命令中标黄的部分)
当我们向集群中存储数据的时候,例如:
set name leo
Redis会通过CRC16算法来计算name对应的值,然后再除以16384,余数就是对应该存放的slot编号(公式:CRC16(key)%16384)。然后根据这个编号去连接对应的主节点,进行存储。
我们随便连接一个redis实例(在集群中,连接任何一个实例都相当于连接到了集群),并执行set name leo:
[ src]# redis-cli -h 192.168.1.181 -c -p 7002 192.168.1.181:7002> set name leo -> Redirected to slot [5798] located at 192.168.1.180:7003 OK 192.168.1.180:7003>
可以看到,我们连接的192.168.1.181:7002其实属于slave,使用-c表示连接到集群,否则会报错。当执行set name leo的时候,redis计算到name对应的slot编号为5798,对应的是192.168.1.180:7003主节点。
然后自动跳转连接了192.168.1.180:7003,并存储了数据。
当某个主节点宕机的时候,与他连接的从节点会自动变为主节点。
例如,我们杀掉192.168.1.181:7000的redis进程:
[ src]# kill -9 1856 [-base src]# ps -ef | grep redis root 1861 1 0 22:30 ? 00:00:04 redis-server 192.168.1.181:7001 [cluster] root 1866 1 0 22:30 ? 00:00:04 redis-server 192.168.1.181:7002 [cluster] root 1906 1403 0 22:56 pts/0 00:00:00 grep --color=auto redis
此时,我们查看7000对应slave节点192.168.1.180:7005的状态:
[ src]# redis-cli -h 192.168.1.180 -p 7005 info replication # Replication role:master connected_slaves:0 master_replid:43d5b373d03e9a1ef4853b60c0504e25a562a62a master_replid2:97def7c7993bcfbcbb6105aef2e86ae51190d236 master_repl_offset:1148 second_repl_offset:1149 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1148
可以看到7005已经变成了主节点。
如果此时,7000重新上线,则会作为7005的Slave节点存在:
[ ~]# redis-cli -h 192.168.1.181 -p 7000 info replication # Replication role:slave master_host:192.168.1.180 master_port:7005 master_link_status:up master_last_io_seconds_ago:5 master_sync_in_progress:0 slave_repl_offset:1176 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:43d5b373d03e9a1ef4853b60c0504e25a562a62a master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1176 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1149 repl_backlog_histlen:28
注意:集群必须存在3个以及3个以上的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总节点的一半时,整个集群就无法提供服务了。
安装redis-py-cluster:
pip install redis-py-cluster
使用python连接集群:
from rediscluster import RedisCluster if __name__ == ‘__main__‘: try: startup_nodes = [ # 这里可以将所有的主总节点都写上 {‘host‘: ‘192.168.1.181‘, ‘port‘: ‘7000‘}, {‘host‘: ‘192.168.1.181‘, ‘port‘: ‘7001‘}, {‘host‘: ‘192.168.1.181‘, ‘port‘: ‘7002‘}, {‘host‘: ‘192.168.1.180‘, ‘port‘: ‘7003‘}, {‘host‘: ‘192.168.1.180‘, ‘port‘: ‘7004‘}, {‘host‘: ‘192.168.1.180‘, ‘port‘: ‘7005‘}, ] src = RedisCluster(startup_nodes=startup_nodes, decode_responses=True) res = src.set(‘name‘, ‘leo‘) print(res) except Exception as e: print(e)
对集群的操作和对单个redis的操作是一样的。