博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis 集群原理与使用
阅读量:6972 次
发布时间:2019-06-27

本文共 9399 字,大约阅读时间需要 31 分钟。

hot3.png

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 yes584 585 # 集群中每个节点都有一个配置文件 586 # 这个文件并不需要手动配置587 # 这个配置文件有Redis生成并更新 588 # 每个Redis集群节点需要一个单独的配置文件589 # 请确保与实例运行的系统中配置文件名称不冲突590 #591 cluster-config-file nodes-6379.conf592 593 # 集群节点超时毫秒数Cluster node timeout is the amount of milliseconds a node must be unreachable594 # 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 15000598 599 # 如果数据太老的话失败的master A slave of a failing master will avoid to start a failover if its data600 # looks too old.601 #602 # slave有一个简单的方法用来度量其数据生命周期603 # 以下的两个检测将被执行:604 #605 # 1) 如果失连节点关联了多个slave, slave之间会交换信息606 #    用来确定slave之间的最佳复制位置(处理了master607 #    发来的数据最多).608 #    Slaves 之间会尝试根据偏移量进行排名, 用于启动and apply to the start609 #    of the failover a delay proportional to their rank.610 #611 # 2) Every single slave computes the time of the last interaction with612 #    its master. This can be the last ping or command received (if the master613 #    is still in the "connected" state), or the time that elapsed since the614 #    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 failover616 #    at all.617 #618 # The point "2" can be tuned by user. Specifically a slave will not perform619 # the failover if, since the last interaction with the master, the time620 # elapsed is greater than:621 #622 #   (node-timeout * slave-validity-factor) + repl-ping-slave-period623 #624 # 举个例子 如果节点超时时间为三十秒, 并且slave-validity-factor为10,625 # 假设默认的 repl-ping-slave-period 是十秒,626 # 如果310秒slave 将不会尝试进行故障转移 if it was not able to talk with the master627 # for longer than 310 seconds.628 #629 # A large slave-validity-factor may allow slaves with too old data to failover630 # a master, while a too small value may prevent the cluster from being able to631 # elect a slave at all.632 #633 # For maximum availability, it is possible to set the slave-validity-factor634 # to a value of 0, which means, that slaves will always try to failover the635 # master regardless of the last time they interacted with the master.636 # (However they'll always try to apply a delay proportional to their637 # offset rank).638 #639 # 当集群中所有分区恢复时,集群可以继续正常运行,640 # 需要把这个值设为零.641 #642 cluster-slave-validity-factor 10643 644 # 集群中slave可以迁移成为孤立的masterCluster slaves are able to migrate to orphaned masters, that are masters645 # that are left without working slaves. This improves the cluster ability646 # to resist to failures as otherwise an orphaned master can't be failed over647 # in case of failure if it has no working slaves.648 #649 # Slaves migrate to orphaned masters only if there are still at least a650 # given number of other working slaves for their old master. This number651 # is the "migration barrier". A migration barrier of 1 means that a slave652 # will migrate only if there is at least 1 other working slave for its master653 # and so forth. It usually reflects the number of slaves you want for every654 # master in your cluster.655 #656 # 默认情况下是1(slaves 只有在master关联到至少一个slave时才会触发迁移过程).657 # 设置一个很大的值可以禁止迁移触发.658 # 在调试环境下可以设为0659 # 在生产环境下这么做风险较大660 #661 cluster-migration-barrier 1662 663 # 默认情况下Redis集群各节点在检测到至少一个hash槽位遗漏的情况下会停止处理查询请求664 # (不可达节点会处理这个遗漏的槽位)665 # 在这种情况下如果集群部分节点宕机(例如部分hash槽位没有被分配)666 # 会造成整个集群不可用.667 # 集群直到所有槽位均被分配时才自动回复为可用状态.668 #669 # 但是有时我们希望集群的一个子集正常工作,670 # 对active的部分keyspace继续接收并执行请求.671 # 为达到这种效果, 请将cluster-require-full-coverage672 # 设置为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  
 
  create          host1:port1 ... hostN:portN                  --replicas 
  check           host:port  fix             host:port  reshard         host:port                  --from 
                  --to 
                  --slots 
                  --yes  add-node        new_host:new_port existing_host:existing_port                  --slave                  --master-id 
  del-node        host:port node_id  set-timeout     host:port milliseconds  call            host:port command arg arg .. arg  import          host:port                  --from 
  help            (show this help)

    

>>> Creating clusterConnecting to node 127.0.0.1:4379: OKConnecting to node 127.0.0.1:5379: OKConnecting to node 127.0.0.1:6379: OKConnecting to node 127.0.0.1:7379: OKConnecting to node 127.0.0.1:8379: OKConnecting to node 127.0.0.1:9379: OK>>> Performing hash slots allocation on 6 nodes...Using 3 masters:127.0.0.1:4379127.0.0.1:5379127.0.0.1:6379Adding replica 127.0.0.1:7379 to 127.0.0.1:4379Adding replica 127.0.0.1:8379 to 127.0.0.1:5379Adding replica 127.0.0.1:9379 to 127.0.0.1:6379M: 317fd61eea7cecbc1d919a028657af955e654c0d 127.0.0.1:4379   slots:0-5460 (5461 slots) masterM: 3f3e200b6fa6c73e72ad4caa73d53a611b126981 127.0.0.1:5379   slots:5461-10922 (5462 slots) masterM: 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e 127.0.0.1:6379   slots:10923-16383 (5461 slots) master   S: 699c827a885bcfe4833693f4ce37b22102bd9ee9 127.0.0.1:7379   replicates 317fd61eea7cecbc1d919a028657af955e654c0dS: d5dc58114b0840a81e5f2ff9402a92b0e12f7544 127.0.0.1:8379   replicates 3f3e200b6fa6c73e72ad4caa73d53a611b126981S: 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 clusterWaiting 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) masterM: 3f3e200b6fa6c73e72ad4caa73d53a611b126981 127.0.0.1:5379   slots:5461-10922 (5462 slots) masterM: 06bcc9edcb10b2fcc6d19f1e4a19ad9c3cd6082e 127.0.0.1:6379   slots:10923-16383 (5461 slots) masterM: 699c827a885bcfe4833693f4ce37b22102bd9ee9 127.0.0.1:7379   slots: (0 slots) master   replicates 317fd61eea7cecbc1d919a028657af955e654c0dM: d5dc58114b0840a81e5f2ff9402a92b0e12f7544 127.0.0.1:8379   slots: (0 slots) master   replicates 3f3e200b6fa6c73e72ad4caa73d53a611b126981M: 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  

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

[3] CLUSTER SLOTS

[4] redis-benchmark cannot work on Redis Cluster

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

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

你可能感兴趣的文章
登录时记住用户名和密码及cookie案例应用
查看>>
对于一个小白来说,遇到的前端问题(2)
查看>>
cocos2dx-新建工程时避免文件和文件夹的拷贝
查看>>
[bzoj 3622]已经没有什么好害怕的了
查看>>
【文文殿下】CF1175F The Number of Subpermutations
查看>>
Struts2配置文件_常量属性_独立测试分析
查看>>
c语言代写
查看>>
技巧:Vim 的纵向编辑模式【转】
查看>>
[转载]linux内存映射mmap原理分析【转】
查看>>
Linux之定时器与时间管理 【转】
查看>>
Linux的软中断处理实现 【转】
查看>>
深入理解Java中的反射机制
查看>>
C# 面向对象
查看>>
并发异步处理队列 .NET 4.5+
查看>>
Udp SocketAsyncEventArgs SocketAsyncDataHandler
查看>>
JVM入门
查看>>
selenium web自动化
查看>>
Python核心编程(2)—— 数字
查看>>
AI和企业管理
查看>>
使用Aspose.Cell控件实现Excel高难度报表的生成
查看>>