Redis
集群是一个可以在多个Redis
节点之间进行数据共享的设施( installation
)。
Redis
集群不支持那些需要同时处理多个键的Redis
命令,因为执行这些命令需要在多个Redis
节点之间移动数据,并且在高负载的情况下,这些命令将降低Redis
集群的性能,并导致不可预测的行为。
Redis
集群通过分区( partition
)来提供一定程度的可用性( availability
) : 即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
将数据自动切分( split
) 到多个节点的能力。
当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力。
为什么要用redis-cluster
解决并发 redis
官方生成可以达到 10万/每秒,每秒执行10万条命令 假如业务需要每秒100万的命令执行呢?
数据量太大 一台服务器内存正常是16~256G
,假如你的业务需要500G
内存,
新浪微博作为世界上最大的redis
存储,就超过1TB
的数据,去哪买这么大的内存条?各大公司有自己的解决方案,推出各自的集群功能,核心思想都是将数据分片(sharding
)存储在多个redis
实例中,每一片就是一个redis
实例。
解决方案 配置一个超级牛逼的计算机,超大内存,超强cpu
,但是问题是。。。。
正确的应该是考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力,一堆机器做一件事
客户端分片 redis3.0
集群采用P2P
模式,完全去中心化,将redis
所有的key
分成了16384
个槽位,每个redis
实例负责一部分slot
,集群中的所有信息通过节点数据交换而更新。
redis
实例集群主要思想是将redis
数据的key
进行散列,通过hash
函数特定的key
会映射到指定的redis
节点上
数据分布理论
分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。
常见的分区规则有哈希分区和顺序分区。Redis Cluster
采用哈希分区规则,因此接下来会讨论哈希分区规则。
节点取余分区 一致性哈希分区 虚拟槽分区(redis-cluster
采用的方式) 顺序分区
哈希分区 节点取余
例如按照节点取余的方式,分三个节点
1~100的数据对3取余,可以分为三类
那么同样的分4个节点就是hash(key)%4
节点取余的优点是简单,客户端分片直接是哈希+取余
一致性哈希 客户端进行分片,哈希+顺时针取余
虚拟槽分区 Redis Cluster
采用虚拟槽分区
虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot
)。
Redis Cluster
槽的范围是0 ~ 16383
。
槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,
每个节点负责一定数量的槽。
搭建redis cluster
搭建集群分为几部
准备节点(几匹马儿) 节点通信(几匹马儿分配主从) 分配槽位给节点(slot
分配给马儿) redis-cluster
集群架构
多个服务端,负责读写,彼此通信,redis
指定了16384
个槽。
多匹马儿,负责运输数据,马儿分配16384
个槽位,管理数据。
ruby
的脚本自动就把分配槽位这事做了
环境准备 ruby安装 安装ruby gem
包管理工具 1 2 3 4 gem install -l redis gem list -- check redis gem
安装redis-trib.rb
命令 安装好gem redis
包会生成redis-trib.rb
命令,如果你执行提示没有该命令说明不在环境变量中,使用find
查找该命令位置
1 2 3 4 5 root@Tony-PC :/tmp/cluster /usr/share/doc/redis-tools /examples/redis-trib .rb root@Tony-PC :/tmp/cluster
准备redis-server
配置文件 1 2 3 4 5 6 cluster-8001 .conf 127.0 .0.1 :8001 cluster-8002 .conf 127.0 .0.1 :8002 cluster-8003 .conf 127.0 .0.1 :8003 cluster-8004 .conf 127.0 .0.1 :8004 cluster-8005 .conf 127.0 .0.1 :8005 cluster-8006 .conf 127.0 .0.1 :8006
编辑配置文件 1 2 3 4 5 6 7 8 9 10 11 12 root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster port 8001 daemonize yes dir /tmp/clusterlogfile 8001 .log dbfilename 8001 .rdb cluster-enabled yes cluster-config-file nodes-8001 .conf cluster-require-full-coverage no
编辑其他配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 root@Tony-PC :/tmp/cluster port 8002 daemonize yes dir /tmp/clusterlogfile 8002 .log dbfilename 8002 .rdb cluster-enabled yes cluster-config-file nodes-8002 .conf cluster-require-full-coverage no ----------------------------------------------------------------------------- root@Tony-PC :/tmp/cluster port 8003 daemonize yes dir /tmp/clusterlogfile 8003 .log dbfilename 8003 .rdb cluster-enabled yes cluster-config-file nodes-8003 .conf cluster-require-full-coverage no ----------------------------------------------------------------------------- root@Tony-PC :/tmp/cluster port 8004 daemonize yes dir /tmp/clusterlogfile 8004 .log dbfilename 8004 .rdb cluster-enabled yes cluster-config-file nodes-8004 .conf cluster-require-full-coverage no ----------------------------------------------------------------------------- root@Tony-PC :/tmp/cluster port 8005 daemonize yes dir /tmp/clusterlogfile 8005 .log dbfilename 8005 .rdb cluster-enabled yes cluster-config-file nodes-8005 .conf cluster-require-full-coverage no ----------------------------------------------------------------------------- root@Tony-PC :/tmp/cluster port 8006 daemonize yes dir /tmp/clusterlogfile 8006 .log dbfilename 8006 .rdb cluster-enabled yes cluster-config-file nodes-8006 .conf cluster-require-full-coverage no
运行redis-server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root@Tony-PC :/tmp/cluster root 8131 1 0 10 :22 ? 00 :00 :00 redis-server *:8001 [cluster ] root 8140 1 0 10 :22 ? 00 :00 :00 redis-server *:8002 [cluster ] root 8148 1 0 10 :22 ? 00 :00 :00 redis-server *:8003 [cluster ] root 8156 1 0 10 :22 ? 00 :00 :00 redis-server *:8004 [cluster ] root 8164 1 0 10 :22 ? 00 :00 :00 redis-server *:8005 [cluster ] root 8171 1 0 10 :22 ? 00 :00 :00 redis-server *:8006 [cluster ] root 8179 5341 0 10 :23 pts/1 00 :00 :00 grep redis
此时启动redis-cli
,集群还不能用,未提供hsah
槽
1 2 3 4 5 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8001 > keys *(empty list or set ) 127.0 .0.1 :8001 > set name tony(error) CLUSTERDOWN Hash slot not served
开启redis-cluster
集群 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 root@Tony-PC :/tmp/cluster >>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters:127.0 .0.1 :8001 127.0 .0.1 :8002 127.0 .0.1 :8003 Adding replica 127.0 .0.1 :8005 to 127.0 .0.1 :8001 Adding replica 127.0 .0.1 :8006 to 127.0 .0.1 :8002 Adding replica 127.0 .0.1 :8004 to 127.0 .0.1 :8003 >>> Trying to optimize slaves allocation for anti-affinity [WARNING ] Some slaves are in the same host as their master M: e1654cae78b3c314deeb8c9741d7fbcc4606469c 127.0 .0.1 :8001 slots:0 -5460 (5461 slots) master M: 0 fdb6c8423c25ffd8841cf67d25ed6ff5934ebb6 127.0 .0.1 :8002 slots:5461 -10922 (5462 slots) master M: 07239385 ba365d456cc9d7d7c60274eb894f4ebc 127.0 .0.1 :8003 slots:10923 -16383 (5461 slots) master S: 98 ab1b39b41a3588ab0102098915a92bb2b67203 127.0 .0.1 :8004 replicates 0 fdb6c8423c25ffd8841cf67d25ed6ff5934ebb6 S: dd8b553ce03137892578e59629f7b6ec483135a4 127.0 .0.1 :8005 replicates 07239385 ba365d456cc9d7d7c60274eb894f4ebc S: 6 df2f0ecbff311dd3289764ff9d9d789ad1cef6e 127.0 .0.1 :8006 replicates e1654cae78b3c314deeb8c9741d7fbcc4606469c 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 127.0.0.1:8001) M: e1654cae78b3c314deeb8c9741d7fbcc4606469c 127.0 .0.1 :8001 slots:0 -5460 (5461 slots) master 1 additional replica(s) S: dd8b553ce03137892578e59629f7b6ec483135a4 127.0 .0.1 :8005 slots: (0 slots) slave replicates 07239385 ba365d456cc9d7d7c60274eb894f4ebc S: 98 ab1b39b41a3588ab0102098915a92bb2b67203 127.0 .0.1 :8004 slots: (0 slots) slave replicates 0 fdb6c8423c25ffd8841cf67d25ed6ff5934ebb6 S: 6 df2f0ecbff311dd3289764ff9d9d789ad1cef6e 127.0 .0.1 :8006 slots: (0 slots) slave replicates e1654cae78b3c314deeb8c9741d7fbcc4606469c M: 07239385 ba365d456cc9d7d7c60274eb894f4ebc 127.0 .0.1 :8003 slots:10923 -16383 (5461 slots) master 1 additional replica(s) M: 0 fdb6c8423c25ffd8841cf67d25ed6ff5934ebb6 127.0 .0.1 :8002 slots:5461 -10922 (5462 slots) master 1 additional replica(s) [OK ] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK ] All 16384 slots covered.
开启成功,集群自动分配主从关系 8001、8006、8003为 8004、8005、8006 主动关系
新版开启集群方式 新版本开启集群的方式已经不需要redis-trib.tb命令了,官方给我们的警告是:WARNING: redis-trib.rb is not longer available!
,也就是说这个命令不再可用了,官方给的完整提示如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 WARNING: redis-trib.rb is not longer available! You should use redis-cli instead. All commands and features belonging to redis-trib.rb have been moved to redis-cli. In order to use them you should call redis-cli with the --cluster option followed by the subcommand name, arguments and options. Use the following syntax: redis-cli --cluster SUBCOMMAND [ARGUMENTS] [OPTIONS] Example: redis-cli --cluster create 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006 --cluster-replicas 1 To get help about all subcommands, type: redis-cli --cluster help
也就是说以后我们使用redis-cli --cluster create
命令就可以开启集群了。
查看集群状态 1 2 3 4 5 6 7 8 redis-cli -p 7000 cluster info redis-cli -p 7000 cluster nodes 集群主节点状态 redis-cli -p 7000 cluster nodes | grep master 集群从节点状态 redis-cli -p 7000 cluster nodes | grep slave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8001 > info replicationrole:master connected_slaves:1 slave0:ip=127.0 .0.1 ,port=8006 ,state=online,offset=1134 ,lag=1 master_replid:6914 abc6a11f70134a2d1e2446a21665539babcd master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1134 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1134 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8002 > info replicationrole:master connected_slaves:1 slave0:ip=127.0 .0.1 ,port=8004 ,state=online,offset=1134 ,lag=0 master_replid:8497 b92f1b109a90dda607f0b629e031edde9842 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1134 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1134 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8003 > info replicationrole:master connected_slaves:1 slave0:ip=127.0 .0.1 ,port=8005 ,state=online,offset=1162 ,lag=0 master_replid:5 e35aa5d820ccb34dfabbd2868bbe62379c44da8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1162 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1162 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8004 > info replicationrole:slave master_host:127.0 .0.1 master_port:8002 master_link_status:up master_last_io_seconds_ago:2 master_sync_in_progress:0 slave_repl_offset:1162 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:8497 b92f1b109a90dda607f0b629e031edde9842 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1162 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1162 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8005 > info replicationrole:slave master_host:127.0 .0.1 master_port:8003 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_repl_offset:1176 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:5 e35aa5d820ccb34dfabbd2868bbe62379c44da8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1176 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1176 root@Tony-PC :/tmp/cluster 127.0 .0.1 :8006 > info replicationrole:slave master_host:127.0 .0.1 master_port:8001 master_link_status:up master_last_io_seconds_ago:10 master_sync_in_progress:0 slave_repl_offset:1176 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:6914 abc6a11f70134a2d1e2446a21665539babcd master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1176 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1176
测试写入数据 测试写入集群数据,登录集群必须使用redis-cli -c -p 8001
必须加上-c
参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 127.0 .0.1 :8001 > set a 1 -> Redirected to slot [15495 ] located at 127.0 .0.1 :8003 OK 127.0 .0.1 :8003 > set b 2 -> Redirected to slot [3300 ] located at 127.0 .0.1 :8001 OK 127.0 .0.1 :8001 > set c 3 -> Redirected to slot [7365 ] located at 127.0 .0.1 :8002 OK 127.0 .0.1 :8002 > set d 4 -> Redirected to slot [11298 ] located at 127.0 .0.1 :8003 OK 127.0 .0.1 :8003 > set e 5 OK 127.0 .0.1 :8003 > set f 6 -> Redirected to slot [3168 ] located at 127.0 .0.1 :8001 OK 127.0 .0.1 :8001 > get a-> Redirected to slot [15495 ] located at 127.0 .0.1 :8003 "1" 127.0 .0.1 :8003 > get b-> Redirected to slot [3300 ] located at 127.0 .0.1 :8001 "2" 127.0 .0.1 :8001 > get c-> Redirected to slot [7365 ] located at 127.0 .0.1 :8002 "3" 127.0 .0.1 :8002 > get d-> Redirected to slot [11298 ] located at 127.0 .0.1 :8003 "4" 127.0 .0.1 :8003 > get e"5" 127.0 .0.1 :8003 > get f-> Redirected to slot [3168 ] located at 127.0 .0.1 :8001 "6" 127.0 .0.1 :8001 > keys *1 ) "b" 2 ) "f" 127.0 .0.1 :8002 > keys *1 ) "c" 127.0 .0.1 :8003 > keys *1 ) "d" 2 ) "e" 3 ) "a" 127.0 .0.1 :8004 > keys *1 ) "c" 127.0 .0.1 :8005 > keys *1 ) "e" 2 ) "a" 3 ) "d" 127.0 .0.1 :8006 > keys *1 ) "b" 2 ) "f"
集群ok
工作原理:
redis
客户端任意访问一个redis
实例,如果数据不在该实例中,通过重定向引导客户端访问所需要的redis
实例