redis 集群
cluster 在设计的时候,就考虑到了去中心化,去中间件,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。
redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。所以我们在测试的时候看到set 和 get 的时候,直接跳转到了6379端口的节点。
Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。
只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。
需要注意的是:Redis 至少3+3,还延续着Master-Slave的设计理念;
1、设计集群测试实例端口 :
6001 6001 6002 6003 6004 6005 6006
# yum -y install gcc gcc-c++ tcl ruby ruby-devel rubygems rpm-build # yum install gcc tcl ruby -y # wget http://download.redis.io/releases/redis-3.2.4.tar.gz # tar xf redis-3.2.4.tar.gz # mv redis-3.2.4 /opt/redis # cd /opt/redis
# mkdir -p redis/{log,data} # make # make test 安装完Redis再执行: gem install redis
2、内核修改配置
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
/sbin/sysctl -p
3、iptables/selinux及内核设置:
# cat /etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 6379 -j ACCEPT
# redis.conf bind 192.168.100.9 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize yes // redis后台运行 cluster-enabled yes // 开启集群 cluster-config-file nodes_6379.conf //集群配置 首次启动生成 cluster-node-timeout 5000 // 请求超时 appendonly yes // aof 日志开启 supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile /opt/redis/logs/6379/redis.log databases 16 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /opt/redis/data/6379 slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes
启动 Redis 实例;
src/redis-server redis_cluster/6001/redis.conf src/redis-server redis_cluster/6002/redis.conf src/redis-server redis_cluster/6003/redis.conf src/redis-server redis_cluster/6004/redis.conf src/redis-server redis_cluster/6005/redis.conf src/redis-server redis_cluster/6006/redis.conf 6001 6001 6002 6003 6004 6005 6006 端口实例;
通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。
redis-trib.rb create --replicas 1 192.168.100.9:6001 192.168.100.9:6002 192.168.100.9:6003 192.168.100.9:6004 192.168.100.9:6005 192.168.100.9:6006 // 这个命令在这里用于创建一个新的集群, 选项–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
集群重新分片:
./redis-trib.rb reshard 192.168.100.9:6003 // 需要指定移动哈希槽数( 1 - 16383 )和目标节点 ID
redis-cli -h 192.168.100.9 -p 6003 cluster nodes | grep myself
root@redis: /opt/redis# redis-cli -h 192.168.100.9 -p 6003 cluster nodes | grep myself 739f446f69739eb7f95331eec7c74a4e57d2eeac 192.168.100.9:6003 myself,master - 0 0 3 connected 10923-16383
添加一个新节点
添加新的节点的基本过程就是添加一个空的节点然后移动一些数据给它;
有两种情况,添加一个主节点和添加一个从节点(添加从节点时需要将这个新的节点设置为集群中某个节点的复制)
针对这两种情况,本节都会介绍,先从添加主节点开始.
两种情况第一步都是要添加 一个空的节点.
使用redis-trib 来添加这个节点到现有的集群中去. ./redis-trib.rb add-node 192.168.100.9:6379 192.168.100.9:6003 // addnode命令来添加节点,第一个参数是新节点的地址,第二个参数是任意一个已经存在的节点的IP和端口. 我们可以看到新的节点已经添加到集群中:
root@redis: /opt/redis# src/redis-cli -c -h 192.168.100.9 -p 6379 192.168.100.9:6379> cluster nodes 0d9cb75cf92ce44dc3a4ad48bd95b48fc0d7a5ca 192.168.100.9:6379 myself,master - 0 0 0 connected 40d6721c15f32d732da89871b941788c3c57dcd3 192.168.100.9:6001 master - 0 1494413014845 1 connected 0-5460 041cb360dfcd8c1e8c77d8e7db03183da553953b 192.168.100.9:6004 slave 40d6721c15f32d732da89871b941788c3c57dcd3 0 1494413014344 1 connected c9d5f58cd5e74f2c5ebbf6213e4314f4e92fb389 192.168.100.9:6006 slave 739f446f69739eb7f95331eec7c74a4e57d2eeac 0 1494413014644 3 connected 5a606eef48bc1fd8be9ad4d7a1d2a9420d8b2552 192.168.100.9:6002 master - 0 1494413015845 2 connected 5461-10922 f539cc2330a19f31a8dd55360e184cda2dc81151 192.168.100.9:6005 slave 5a606eef48bc1fd8be9ad4d7a1d2a9420d8b2552 0 1494413015345 2 connected 739f446f69739eb7f95331eec7c74a4e57d2eeac 192.168.100.9:6003 master - 0 1494413016345 3 connected 10923-16383 192.168.100.9:6379>
新节点现在已经连接上了集群, 成为集群的一份子, 并且可以对客户端的命令请求进行转向了, 但是和其他主节点相比, 新节点还有两点区别:
新节点没有包含任何数据, 因为它没有包含任何哈希槽.
尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。
接下来, 只要使用 redis-trib 程序, 将集群中的某些哈希桶移动到新节点里面, 新节点就会成为真正的主节点了。
添加一个从节点
有两种方法添加从节点, 1、redis-trib 命令,也可以像下面的例子一样使用 --slave选项: ./redis-trib.rb add-node --slave 192.168.100.9:6379 192.168.100.9:6001 // 此处的命令和添加一个主节点命令类似,此处并没有指定添加的这个从节点的主节点,这种情况下系统会在其他的复制集中的主节点中随机选取一个作为这个从节点的主节点。 2/你可以通过下面的命令指定主节点: ./redis-trib.rb add-node --slave --master-id 739f446f69739eb7f95331eec7c74a4e57d2eeac 192.168.100.9:6379 192.168.100.9:6001 // 也可以使用CLUSTER REPLICATE 命令添加.这个命令也可以改变一个从节点的主节点。
例如,要给主节点 192.168.100.9:6003添加一个从节点,该节点哈希槽的范围1423-16383,
节点 ID 739f446f69739eb7f95331eec7c74a4e57d2eeac,我们需要链接新的节点(已经是空的主节点)并执行命令: redis 192.168.100.9:6379> cluster replicate 739f446f69739eb7f95331eec7c74a4e57d2eeac 我们新的从节点有了一些哈希槽,其他的节点也知道(过几秒后会更新他们自己的配置),可以使用如下命令确认: $ redis-cli -p 6001 cluster nodes | grep slave | grep 739f446f69739eb7f95331eec7c74a4e57d2eeac f093c80dde814da99c5cf72a7dd01590792b783b 192.168.100.9:6379 slave 739f446f69739eb7f95331eec7c74a4e57d2eeac 0 1385543617702 3 connected 041cb360dfcd8c1e8c77d8e7db03183da553953b 192.168.100.9:6004 slave 40d6721c15f32d732da89871b941788c3c57dcd3 0 1494413014344 1 connected
节点 739f446f69739eb7f95331eec7c74a4e57d2eeac 有两个从节点, 6004 (已经存在的) 和 6379 (新添加的).
移除一个节点:
1、只要使用 del-node 命令即可: ./redis-trib del-node 192.168.100.9:6001 `<node-id>` // 第一个参数是任意一个节点的地址,第二个节点是你想要移除的节点地址。 使用同样的方法移除主节点,不过在移除主节点前,需要确保这个主节点是空的. 如果不是空的,需要将这个节点的数据重新分片到其他主节点上. 替代移除主节点的方法是手动执行故障恢复,被移除的主节点会作为一个从节点存在,不过这种情况下不会减少集群节点的数量,也需要重新分片数据.
从节点的迁移:
在Redis集群中会存在改变一个从节点的主节点的情况,需要执行如下命令 :
CLUSTER REPLICATE <master-node-id>