Redis 集群原理与使用

Redis 在2014年11月3日release了3.0.0-RC1版本 其中含有万众期待的集群功能  

(补充 2015年1月13日发布了RC2版本)

在github上很多人都开始测试集群版本  目前尚不稳定 变更还是比较大  


Redis Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

节点之间使用gossip协议传播信息以及发现新节点。

这种结构和Cassandra很相似,Cassandra节点可以转发请求。

Redis集群中节点不作为client请求的代理,client根据node返回的错误信息重定向请求


Redis集群预分好16384个桶,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。

每个Redis物理结点负责一部分桶的管理,当发生Redis节点的增减时,调整桶的分布即可。

例如,假设Redis Cluster三个节点A/B/C,则 Node A 包含桶的编号可以为: 0 到 5500. Node B 包含桶的编号可以为: 5500 到 11000. Node C包含桶的编号可以为: 11001 到 16384. 当发生Redis节点的增减时,调整桶的分布即可。 

预分桶的方案介于“硬Hash”和“一致性Hash”之间,牺牲了一定的灵活性,但相比“一致性Hash“,数据的管理成本大大降低。


为了保证服务的可用性,Redis Cluster采取的方案是的Master-Slave 每个Redis Node可以有一个或者多个Slave。

当Master挂掉时,选举一个Slave形成新的Master 一个Redis Node包含一定量的桶,当这些桶对应的Master和Slave都挂掉时,这部分桶对应的数据不可用


Redis Cluster使用异步复制,一个完整的写操作步骤: 1.client写数据到master 2.master告诉client "ok" 3.master传播更新到slave 存在数据丢失的风险: 1. 上述写步骤1)和2)成功后,master crash,而此时数据还没有传播到slave 2. 由于分区导致同时存在两个master,client向旧的master写入了数据。 


Redis Cluster支持在线增/减节点。 

基于桶的数据分布方式大大降低了迁移成本,只需将数据桶从一个Redis Node迁移到另一个Redis Node即可完成迁移。

当桶从一个Node A向另一个Node B迁移时,Node A和Node B都会有这个桶,Node A上桶的状态设置为MIGRATING,Node B上桶的状态被设置为IMPORTING 当客户端请求时: 所有在Node A上的请求都将由A来处理,所有不在A上的key都由Node B来处理。同时,Node A上将不会创建新的key


我在本机上搭建了一个Redis集群  作为测试使用  其中学习过程纪录在此

配置文件差异:

Redis集群版本中比单机版本在配置文件上多出了一部分

577 ################################ REDIS CLUSTER  ###############################
578 #
579 # 单机版本Redis实例不能作为集群的一部分;
580 # 只有以cluster node启动的节点可以加入集群
581 # 为了以集群启动Redis实例需要开启下列参数
582 #
583 cluster-enabled yes
584 
585 # 集群中每个节点都有一个配置文件 
586 # 这个文件并不需要手动配置
587 # 这个配置文件有Redis生成并更新 
588 # 每个Redis集群节点需要一个单独的配置文件
589 # 请确保与实例运行的系统中配置文件名称不冲突
590 #
591 cluster-config-file nodes-6379.conf
592 
593 # 集群节点超时毫秒数Cluster node timeout is the amount of milliseconds a node must be unreachable
594 # for it to be considered in failure state.
595 # Most other internal time limits are multiple of the node timeout.
596 #
597 cluster-node-timeout 15000
598 
599 # 如果数据太老的话失败的master A slave of a failing master will avoid to start a failover if its data
600 # looks too old.
601 #
602 # slave有一个简单的方法用来度量其数据生命周期
603 # 以下的两个检测将被执行:
604 #
605 # 1) 如果失连节点关联了多个slave, slave之间会交换信息
606 #    用来确定slave之间的最佳复制位置(处理了master
607 #    发来的数据最多).
608 #    Slaves 之间会尝试根据偏移量进行排名, 用于启动and apply to the start
609 #    of the failover a delay proportional to their rank.
610 #
611 # 2) Every single slave computes the time of the last interaction with
612 #    its master. This can be the last ping or command received (if the master
613 #    is still in the "connected" state), or the time that elapsed since the
614 #    disconnection with the master (if the replication link is currently down).
615 #    If the last interaction is too old, the slave will not try to failover
616 #    at all.
617 #
618 # The point "2" can be tuned by user. Specifically a slave will not perform
619 # the failover if, since the last interaction with the master, the time
620 # elapsed is greater than:
621 #
622 #   (node-timeout * slave-validity-factor) + repl-ping-slave-period
623 #
624 # 举个例子 如果节点超时时间为三十秒, 并且slave-validity-factor为10,
625 # 假设默认的 repl-ping-slave-period 是十秒,
626 # 如果310秒slave 将不会尝试进行故障转移 if it was not able to talk with the master
627 # for longer than 310 seconds.
628 #
629 # A large slave-validity-factor may allow slaves with too old data to failover
630 # a master, while a too small value may prevent the cluster from being able to
631 # elect a slave at all.
632 #
633 # For maximum availability, it is possible to set the slave-validity-factor
634 # to a value of 0, which means, that slaves will always try to failover the
635 # master regardless of the last time they interacted with the master.
636 # (However they'll always try to apply a delay proportional to their
637 # offset rank).
638 #
639 # 当集群中所有分区恢复时,集群可以继续正常运行,
640 # 需要把这个值设为零.
641 #
642 cluster-slave-validity-factor 10
643 
644 # 集群中slave可以迁移成为孤立的masterCluster slaves are able to migrate to orphaned masters, that are masters
645 # that are left without working slaves. This improves the cluster ability
646 # to resist to failures as otherwise an orphaned master can't be failed over
647 # in case of failure if it has no working slaves.
648 #
649 # Slaves migrate to orphaned masters only if there are still at least a
650 # given number of other working slaves for their old master. This number
651 # is the "migration barrier". A migration barrier of 1 means that a slave
652 # will migrate only if there is at least 1 other working slave for its master
653 # and so forth. It usually reflects the number of slaves you want for every
654 # master in your cluster.
655 #
656 # 默认情况下是1(slaves 只有在master关联到至少一个slave时才会触发迁移过程).
657 # 设置一个很大的值可以禁止迁移触发.
658 # 在调试环境下可以设为0
659 # 在生产环境下这么做风险较大
660 #
661 cluster-migration-barrier 1
662 
663 # 默认情况下Redis集群各节点在检测到至少一个hash槽位遗漏的情况下会停止处理查询请求
664 # (不可达节点会处理这个遗漏的槽位)
665 # 在这种情况下如果集群部分节点宕机(例如部分hash槽位没有被分配)
666 # 会造成整个集群不可用.
667 # 集群直到所有槽位均被分配时才自动回复为可用状态.
668 #
669 # 但是有时我们希望集群的一个子集正常工作,
670 # 对active的部分keyspace继续接收并执行请求.
671 # 为达到这种效果, 请将cluster-require-full-coverage
672 # 设置为no.
673 #
674 cluster-require-full-coverage yes


在Redis src目录下 有一个redis-tribe.rb ruby脚本用于新建Redis集群

首先需要使用gem安装ruby redis client:

gem install redis

redis-tribe.rb脚本提供了集群的基本管理功能:

Usage: redis-trib <command> <options> <arguments ...>

  create          host1:port1 ... hostN:portN
                  --replicas <arg>
  check           host:port
  fix             host:port
  reshard         host:port
                  --from <arg>
                  --to <arg>
                  --slots <arg>
                  --yes
  add-node        new_host:new_port existing_host:existing_port
                  --slave
                  --master-id <arg>
  del-node        host:port node_id
  set-timeout     host:port milliseconds
  call            host:port command arg arg .. arg
  import          host:port
                  --from <arg>
  help            (show this help)


    

>>> Creating cluster
Connecting to node 127.0.0.1:4379: OK
Connecting to node 127.0.0.1:5379: OK
Connecting to node 127.0.0.1:6379: OK
Connecting to node 127.0.0.1:7379: OK
Connecting to node 127.0.0.1:8379: OK
Connecting to node 127.0.0.1:9379: OK

>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:4379
127.0.0.1:5379
127.0.0.1:6379

Adding replica 127.0.0.1:7379 to 127.0.0.1:4379
Adding replica 127.0.0.1:8379 to 127.0.0.1:5379
Adding replica 127.0.0.1:9379 to 127.0.0.1:6379

M: 317fd61eea7cecbc1d919a028657af955e654c0d 127.0.0.1:4379
   slots:0-5460 (5461 slots) master
M: 3f3e200b6fa6c73e72ad4caa73d53a611b126981 127.0.0.1:5379
   slots:5461-10922 (5462 slots) master
M: 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e 127.0.0.1:6379
   slots:10923-16383 (5461 slots) master
   
S: 699c827a885bcfe4833693f4ce37b22102bd9ee9 127.0.0.1:7379
   replicates 317fd61eea7cecbc1d919a028657af955e654c0d
S: d5dc58114b0840a81e5f2ff9402a92b0e12f7544 127.0.0.1:8379
   replicates 3f3e200b6fa6c73e72ad4caa73d53a611b126981
S: 22770332720330ec3b27b806edf8c8aaf1eccadc 127.0.0.1:9379
   replicates 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e
   
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:4379)

M: 317fd61eea7cecbc1d919a028657af955e654c0d 127.0.0.1:4379
   slots:0-5460 (5461 slots) master
M: 3f3e200b6fa6c73e72ad4caa73d53a611b126981 127.0.0.1:5379
   slots:5461-10922 (5462 slots) master
M: 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e 127.0.0.1:6379
   slots:10923-16383 (5461 slots) master
M: 699c827a885bcfe4833693f4ce37b22102bd9ee9 127.0.0.1:7379
   slots: (0 slots) master
   replicates 317fd61eea7cecbc1d919a028657af955e654c0d
M: d5dc58114b0840a81e5f2ff9402a92b0e12f7544 127.0.0.1:8379
   slots: (0 slots) master
   replicates 3f3e200b6fa6c73e72ad4caa73d53a611b126981
M: 22770332720330ec3b27b806edf8c8aaf1eccadc 127.0.0.1:9379
   slots: (0 slots) master
   replicates 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e
   
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.



Setting up a cluster involves a few different moving parts. Here are a few things to try so we can figure out where you're stuck:

  • make sure each redis-server is running in its own directory

  • make sure you can reach the Redis port and Redis port + 10000 (example: port 6379 and port 16379, or port 7000 and port 17000)

  • provide the command line and cluster-related configuration used to start Redis

  • provide the nodes.conf (or whatever you named cluster-config-file) for each server after the failure or timeout of redis-trib.

  • provide any output from your redis-server instances

    • if the output doesn't look useful, move to a different log level and try again

                                                                                                                        摘自 <Redis MailList>


CLUSTER SLOTS用于查看槽位与Redis实例之间的映射关系  其中返回的结构如下:

    起始槽位

    终止槽位

    master Host/Port

    各个slave Host/Port

1) 1) (integer) 5461
   2) (integer) 10922
   3) 1) "127.0.0.1"
      2) (integer) 8379
   4) 1) "127.0.0.1"
      2) (integer) 5379
      
2) 1) (integer) 0
   2) (integer) 5460
   3) 1) "127.0.0.1"
      2) (integer) 7379
   4) 1) "127.0.0.1"
      2) (integer) 4379
      
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 6379
   4) 1) "127.0.0.1"
      2) (integer) 9379


参考文献:

[1] Redis Cluster a pragmatic approach to distribution  

http://redis.io/presentation/Redis_Cluster.pdf

[2] How Twitter Uses Redis To Scale - 105TB RAM, 39MM QPS, 10,000+ Instances

http://highscalability.com/blog/2014/9/8/how-twitter-uses-redis-to-scale-105tb-ram-39mm-qps-10000-ins.html

[3] CLUSTER SLOTS

http://redis.io/commands/cluster-slots

[4] redis-benchmark cannot work on Redis Cluster

https://github.com/antirez/redis/issues/2191

[5] Redis Cluster(Redis 3.X)设计要点

http://blog.csdn.net/yfkiss/article/details/39996129







转载于:https://my.oschina.net/darionyaphet/blog/357276

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值