redis集群实现方案:node
关于redis的集群化方案 目前有三种 redis
(1)Twitter开发的twemproxy 算法
(2)豌豆荚开发的codis 后端
(3)redis官方的redis-clusterruby
简介:twemproxy架构简单 就是用proxy对后端redis server进行代理 可是因为代理层的消耗性能很低 并且一般涉及多个key的操做都是不支持的 并且自己不支持动态扩容和透明的数据迁移 并且也失去维护 Twitter内部已经不使用了。服务器
redis-cluster是三个里性能最强大的 由于他使用去中心化的思想 使用hash slot方式 将16348个hash slot 覆盖到全部节点上 对于存储的每一个key值 使用CRC16(KEY)&16348=slot 获得他对应的hash slot 并在访问key时就去找他的hash slot在哪个节点上 而后由当前访问节点从实际被分配了这个hash slot的节点去取数据 节点之间使用轻量协议通讯 减小带宽占用 性能很高 自动实现负载均衡与高可用 自动实现failover 而且支持动态扩展 官方已经玩到能够1000个节点 实现的复杂度低 总之我的比较喜欢这个架构 由于他的去中心化思想免去了proxy的消耗 是全新的思路。架构
可是它也有一些不足 例如官方没有提供图形化管理工具 运维体验差 全手工数据迁移 而且本身对本身自己的redis命令支持也不彻底等 可是这些问题 我以为不能掩盖他关键的新思想所带来的的优点 随着官方的推动 这些问题应该都能在必定时间内获得解决 那么这时候去中心化思想带来的高性能就会表现出他巨大的优点。app
Codis使用的也是proxy思路 可是作的比较好 是这两种之间的一个中间级 并且支持redis命令是最多的 有图形化GUI管理和监控工具 运维友好 这个过段时间会详细另外写出来原理 工做机制和搭建实现。负载均衡
基本介绍:运维
Redis 集群是一个能够在多个 Redis 节点之间进行数据共享的设施installation。
Redis 集群不支持那些须要同时处理多个键的 Redis 命令, 由于执行这些命令须要在多个 Redis 节点之间移动数据, 而且在高负载的状况下, 这些命令将下降Redis集群的性能, 并致使不可预测的行为。
Redis 集群经过分区partition来提供必定程度的可用性availability: 即便集群中有一部分节点失效或者没法进行通信, 集群也能够继续处理命令请求。
Redis集群提供了如下两个好处:
集群原理:
redis-cluster架构图:
Redis集群中内置了 16384 个哈希槽,当须要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,而后把结果对 16384 求余数,这样每一个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大体均等的将哈希槽映射到不一样的节点。
redis-cluster投票:容错
1. 投票过程是集群中全部master参与,若是半数以上master节点与master节点通讯超时(cluster-node-timeout),认为当前master节点挂掉。
2. 何时整个集群不可用(cluster_state:fail)?
① 若是集群任意master挂掉,且当前master没有slave,集群进入fail状态,也能够理解成集群的slot映射[0-16383]不完整时进入fail状态。
redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败。
② 若是集群超过半数以上master挂掉,不管是否有slave,集群进入fail状态。
redis集群的搭建
彻底分布式:redis集群的节点个数是奇数个,最少有三个节点,为了保证集群的高可用性,对每台redis节点须要进行备份,所以redis集群须要6台服务器。
伪分布式:能够再一台服务器上面同时运行6个redis实例,模拟彻底分布式集群。须要修改每一个redis实例中的端口号,同时设置cluster-enabled的值为yes。
硬件环境
本文适用的硬件环境以下:
Linux版本:CentOS release 6.7 (Final) Redis版本:3.2.1
Redis已经成功安装,安装路径为/home/idata/axing/local/redis-3.2.1。
咱们要在单台机器上搭建Redis集群,方式是经过不一样的TCP端口启动多个实例,而后组成集群。
一、启动Redis多个实例
咱们在Redis安装目录下建立目录cluster,并编写7000.conf~7005.conf 6个配置文件,这6个配置文件用来启动6个实例,后面将使用这6个实例组成集群。
以7000.conf为例,配置文件须要填写以下几项:
port 7000 //端口7000,7002,7003 bind 10.93.84.53 //默认ip为127.0.0.1 须要改成其余节点机器可访问的ip 不然建立集群时没法访问对应的端口,没法建立集群 daemonize yes //redis后台运行 pidfile ./redis_7000.pid //pidfile文件对应7000,7001,7002 cluster-enabled yes //开启集群 把注释#去掉 cluster-config-file nodes_7000.conf //集群的配置 配置文件首次启动自动生成 7000,7001,7002 cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置 appendonly yes //aof日志开启 有须要就开启,它会每次写操做都记录一条日志
分别启动6个实例:
./bin/redis-server cluster/conf/7000.conf ./bin/redis-server cluster/conf/7001.conf ./bin/redis-server cluster/conf/7002.conf ./bin/redis-server cluster/conf/7003.conf ./bin/redis-server cluster/conf/7004.conf ./bin/redis-server cluster/conf/7005.conf
启动成功后,看一下进程:
# ps -ef | grep redis | grep cluster idata 15711 22329 0 18:40 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7000 [cluster] idata 15740 22329 0 18:40 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7001 [cluster] idata 15810 22329 0 18:40 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7002 [cluster] idata 17023 22329 0 18:42 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7003 [cluster] idata 17030 22329 0 18:42 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7004 [cluster] idata 17035 22329 0 18:42 pts/10 00:00:00 ./bin/redis-server 10.93.84.53:7005 [cluster]
至此,ip=10.93.84.53机器上建立了6个实例,端口号为port=7000~7005。
Redis 3.0以上的集群方式是经过Redis安装目录下的bin/redis-trib.rb脚本搭建。
这个脚本是用Ruby编写的,尝试运行,若是打印以下,你能够跳过本文的第二部分。
idata@qa-f1502-xg01.xg01:~/yangfan/local/redis-3.2.1/bin$ ruby redis-trib.rb Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN --replicas <arg> check host:port info host:port fix host:port --timeout <arg> reshard host:port --from <arg> --to <arg> --slots <arg> --yes --timeout <arg> --pipeline <arg> rebalance host:port --weight <arg> --auto-weights --use-empty-masters --timeout <arg> --simulate --pipeline <arg> --threshold <arg> 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> --copy --replace help (show this help) For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
二、安装ruby
下面的过程都是在root权限下完成的。
1)yum安装ruby和依赖的包。
2)使用gem这个命令来安装redis接口
3)升级Ruby的版本
4)安装gem redis接口
5)安装rubygems
至此,咱们的Ruby和运行redis-trib.rb须要的环境安装完成了。
三、Redis集群搭建
有了Ruby执行环境,能够开始将以前的6个实例组建成集群了。
命令方式:
ruby ./bin/redis-trib.rb create --replicas 1 10.93.84.53:7000 10.93.84.53:7001 10.93.84.53:7002 10.93.84.53:7003 10.93.84.53:7004 10.93.84.53:7005
--replicas 1表示为集群的master节点建立1个副本。那么6个实例里,有三个master,有三个是slave。
后面跟上6个实例就行了,形式就是ip:port
执行状况:
# ruby ./bin/redis-trib.rb create --replicas 1 10.93.84.53:7000 10.93.84.53:7001 10.93.84.53:7002 10.93.84.53:7003 10.93.84.53:7004 10.93.84.53:7005 >>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 10.93.84.53:7000 10.93.84.53:7001 10.93.84.53:7002 Adding replica 10.93.84.53:7003 to 10.93.84.53:7000 Adding replica 10.93.84.53:7004 to 10.93.84.53:7001 Adding replica 10.93.84.53:7005 to 10.93.84.53:7002 M: 6346ae8c7af7949658619fcf4021cc7aca454819 10.93.84.53:7000 slots:0-5460 (5461 slots) master M: 5ac973bceab0d486c497345fe884ff54d1bb225a 10.93.84.53:7001 slots:5461-10922 (5462 slots) master M: cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 10.93.84.53:7002 slots:10923-16383 (5461 slots) master S: 92f62ec93a0550d962f81213ca7e9b3c9c996afd 10.93.84.53:7003 replicates 6346ae8c7af7949658619fcf4021cc7aca454819 S: 942c9f97dc68198c39f425d13df0d8e3c40c5a58 10.93.84.53:7004 replicates 5ac973bceab0d486c497345fe884ff54d1bb225a S: a92a81532b63652bbd862be6f19a9bd8832e5e05 10.93.84.53:7005 replicates cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 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 10.93.84.53:7000) M: 6346ae8c7af7949658619fcf4021cc7aca454819 10.93.84.53:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) S: a92a81532b63652bbd862be6f19a9bd8832e5e05 10.93.84.53:7005 slots: (0 slots) slave replicates cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 M: 5ac973bceab0d486c497345fe884ff54d1bb225a 10.93.84.53:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 942c9f97dc68198c39f425d13df0d8e3c40c5a58 10.93.84.53:7004 slots: (0 slots) slave replicates 5ac973bceab0d486c497345fe884ff54d1bb225a S: 92f62ec93a0550d962f81213ca7e9b3c9c996afd 10.93.84.53:7003 slots: (0 slots) slave replicates 6346ae8c7af7949658619fcf4021cc7aca454819 M: cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 10.93.84.53:7002 slots:10923-16383 (5461 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.
能够看到16384个slot都已经建立完成,而且创建了3个master和对应的replica:
Using 3 masters: 10.93.84.53:7000 10.93.84.53:7001 10.93.84.53:7002 Adding replica 10.93.84.53:7003 to 10.93.84.53:7000 Adding replica 10.93.84.53:7004 to 10.93.84.53:7001 Adding replica 10.93.84.53:7005 to 10.93.84.53:7002 。。。 [OK] All 16384 slots covered.
四、验证集群状态
登陆集群客户端,-c标识以集群方式登陆:
./bin/redis-cli -h 10.93.84.53 -p 7000 -c
查看集群状态:
10.93.84.53:7000> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:8 cluster_my_epoch:8 cluster_stats_messages_sent:215 cluster_stats_messages_received:215 10.93.84.53:7000> cluster nodes 942c9f97dc68198c39f425d13df0d8e3c40c5a58 10.93.84.53:7004 slave 5ac973bceab0d486c497345fe884ff54d1bb225a 0 1507806791940 5 connected 5ac973bceab0d486c497345fe884ff54d1bb225a 10.93.84.53:7001 master - 0 1507806788937 2 connected 5461-10922 a92a81532b63652bbd862be6f19a9bd8832e5e05 10.93.84.53:7005 slave cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 0 1507806790939 6 connected cc46a4a1c0ec3f621b6b5405c6c10b7cffe73932 10.93.84.53:7002 master - 0 1507806789937 3 connected 10923-16383 6346ae8c7af7949658619fcf4021cc7aca454819 10.93.84.53:7000 myself,slave 92f62ec93a0550d962f81213ca7e9b3c9c996afd 0 0 1 connected 92f62ec93a0550d962f81213ca7e9b3c9c996afd 10.93.84.53:7003 master - 0 1507806792941 8 connected 0-5460
原理总结:
redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每一个节点都是平等的关系,都是对等的,每一个节点都保存各自的数据和整个集群的状态。每一个节点都和其余全部节点链接,并且这些链接保持活跃,这样就保证了咱们只须要链接集群中的任意一个节点,就能够获取到其余节点的数据。
Redis集群没有并使用传统的一致性哈希来分配数据,而是采用另一种叫作哈希槽(hash slot)的方式来分配的,一致性哈希对向集群中新增和删除实例的支持很好,可是哈希槽对向集群新增实例或者删除实例的话,须要额外的操做,须要手动的将slot从新平均的分配到新集群的实例中。
redis cluster 默认分配了 16384 个slot,当咱们set一个key时,会用CRC16算法来取模获得所属的slot,而后将这个key分到哈希槽区间的节点上,具体算法就是:CRC16(key)%16384。 Redis 集群会把数据存在一个master节点,而后在这个master和其对应的salve之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的master节点获取数据。只有当一个master 挂掉以后,才会启动一个对应的salve节点,充当master。
须要注意的是:必需要3个或以上的主节点,不然在建立集群时会失败,而且当存活的主节点数小于总节点数的一半时,整个集群就没法提供服务了。