Redis集群及管理讲解

一、为什么要弄redis集群

集群技术是构建高性能网站架构的重要手段,试想在网站承受高并发访问压力的同时,还需要从海量数据中查询出满足条件的数据,并快速响应,我们必然想到的是将数据进行切片,把数据根据某种规则放入多个不同的服务器节点,来降低单节点服务器的压力。上篇redis_主从我们讲到了 Redis 的主从复制技术,当实现了多节点的 master-slave 后,我们也可以把它叫做集群,但我们今天要讲的集群主要是利用切片技术来组建的集群。我们最后希望达到的是类似下图:

二、实现策略

因为从3.0开始以后官方已经支持了 redis cluster,http://redis.io/topics/cluster-tutorial

集群要实现的目的是要将不同的 key 分散放置到不同的 redis 节点,这里我们需要一个规则或者算法,通常的做法是获取 key 的哈希值,然后根据节点数来求模,但这种做法有其明显的弊端,当我们需要增加或减少一个节点时,会造成大量的 key 无法命中,这种比例是相当高的,所以就有人提出了一致性哈希的概念。

由于官方版本是基于哈希槽(hash slot)的概念来实现的,我们还是从其官方介绍中翻译解释一下:

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

使用哈希槽的好处就在于可以方便的添加或移除节点:

当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;

当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;

三、集群实现

对于我们来说,在新增或移除节点的能做到无缝(即不需要重启集群),这点它做到了。还是来看看具体的实现吧:

新建redis_cluster文件夹下面新建6000、6100、6200三个文件夹。

把src 目录下面的redis-server、redis.conf这两个文件分别拷贝到这三个目录里面,拷贝完之后就像这样子了:

[mysql@localhost 6000]$ ll -rw-rw-r--. 1 mysql mysql 116 Aug 21 05:37 redis.conf -rwxrwxr-x. 1 mysql mysql 7820101 Aug 21 05:29 redis-server

修改每个目录下面的redis.conf文件因为我们启动的端口是不一样的,vi redis.conf删除里面的所有添加如下的:

daemonize yes //指定以守护进程启动 port 6000 //启动端口 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes

依次启动每一个实例文件夹下面的./redis-server ./redis.conf,这样的话3个实例就启动了,但是如何将3个实例维护成一个集群呢,在src目录下面执行:

./redis-trib.rb create --replicas 0 127.0.0.1:6000 127.0.0.1:6100 127.0.0.1:6200

执行以后是不是会发现执行失败提示没有redis-trib.rb文件,好吧我们还忘了装一个,因为我们执行的是ruby命令,所以还需要安装ruby:

https://rubygems.org/gems/redis下载,然后离线安装。sudo gem install redis-3.3.1.gem --local

安装完成以后再src目录下面就有了redis-trib.rb文件。

执行上面的集群命令控制台输出如下:

来试试集群的效果吧:

在6000端口实例上测试

[mysql@localhost src]$ ./redis-cli -c -p 6000 127.0.0.1:6000> get name -> Redirected to slot [5798] located at 127.0.0.1:6100 //发现当没有指定的key的时候会重定向到集群的其它机器去找 127.0.0.1:6100> set aaa 111 OK 127.0.0.1:6100> get aaa "111" //如上索性在6100实例的机器上面set aaa的值,然后在6200的机器上面去查 [mysql@localhost src]$ ./redis-cli -c -p 6200 127.0.0.1:6200> get aaa -> Redirected to slot [10439] located at 127.0.0.1:6100 //发现重定向去6100的端口的实例上找到了结果 "111" //在6200的机器上面直接重置aaa为1234 127.0.0.1:6200> set aaa 1234 -> Redirected to slot [10439] located at 127.0.0.1:6100 //还是重定向去6100的端口的实例上更新结果 OK

从上面的结果可以看出,集群中的节点是会进行通讯的,从而能找到不同的key在不同实例上,在机器固定的情况下,key唯一时后续对其的所有更新以及查询都会映射到这一台机器上面。

当然我们的集群的节点是不会一成不变的,我们随时有可能扩容、缩容那该怎么来实现呢?下面来讲讲集群节点的变化吧。

四、集群变更

我们先在上面的基础上试试添加端口为6300的实例,重复操作如上:

[mysql@localhost redis_cluster]$ mkdir 6300 [mysql@localhost redis_cluster]$ ll total 16 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6000 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6100 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6200 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 06:27 6300 [mysql@localhost redis_cluster]$ cp ../redis/redis-3.2.3/src/redis-server ../redis/redis-3.2.3/redis.conf 6300/

不要忘了修改redis.conf,具体配置如上文提到的。

[mysql@localhost 6300]$ ./redis-server ./redis.conf [mysql@localhost 6300]$ netstat -an | grep 6300 tcp 0 0 0.0.0.0:16300 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:6300 0.0.0.0:* LISTEN tcp 0 0 :::16300 :::* LISTEN tcp 0 0 :::6300 :::* LISTEN

新的redis实例已经启动好了,然后需要把它加到已有的集群啦:

./redis-trib.rb add-node 127.0.0.1:6300 127.0.0.1:6000

如上已经能查看到新的实例啦,为什么6300这个新的实例的connected后面没有分配hash槽呢,别慌我们还没有reshard, 执行如下命令:

./redis-trib.rb reshard 127.0.0.1:6300

我们想从6000节点中分配1000个hash槽位出来:

这样有hash槽了,当crc16(key) / 16384 的结果在该节点的所在区间时,数据就放在该节点上。

redis 采用的crc16算法详见:http://blog.csdn.net/guodongxiaren/article/details/44706613

五、如何为每一个主节点增加从节点呢?

好吧,先创建6400端口实例看看,具体新建文件夹以及配置和重启实例我就不再讲了,上面以及有了。执行如下命令:

./redis-trib.rb add-node --slave 127.0.0.1:6400 127.0.0.1:6000

我们也可以试试在从节点6400上面做set操作:

127.0.0.1:6400> set da87 (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6400> set da (error) ERR wrong number of arguments for 'set' command

很不幸,确实不能做set操作会报错,从节点只能用于做读工作。

六、我们如何来删除一个节点呢?

[mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c' >>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000 [ERR] Node 127.0.0.1:6000 is not empty! Reshard data away and try again. [mysql@localhost src]$

我们发现删除6000端口的实例失败了,应该是上面还有一些数据如果直接删除就有数据丢失,我们应该把数据移到别的节点去:

./redis-trib.rb reshard 127.0.0.1:6000 //移除6000实例的数据 然后输出了很多信息,很多数值和ID都可以从这段信息中找到。 How many slots do you want to move (from 1 to 16384)? 5461 会问你要移动多少个哈希槽,我们把 6000上的所有哈希槽都移走,5461 这个数字可以从终端上看到,或许你的实际情况不是这个数字。 What is the receiving node ID? d4467ece7cca245345b71cc1f639508f4f7831c4 //选定移动到6300端口的实例上面,实例ID Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:eb868ce2c102b897ee0a48cd8893288c36bacf5c //选定移除掉6000端口的实例上面,实例ID Source node #2:done 之后,redis 列出了重新分片计划,最后问你 Do you want to proceed with the proposed reshard plan (yes/no)? yes

中间有一些重新分配的刷屏信息省略。

[mysql@localhost src]$ ./redis-cli -p 6300 127.0.0.1:6300> keys * 1) "aaa" 127.0.0.1:6300>

数据移到6300实例上面啦,我们再来试试删除6000端口实例吧:

[mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c' >>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. [mysql@localhost src]$ ./redis-cli -c -p 6000 Could not connect to Redis at 127.0.0.1:6000: Connection refused Could not connect to Redis at 127.0.0.1:6000: Connection refused

原文发布于微信公众号 - 马哥Linux运维(magedu-Linux)

原文发表时间:2016-09-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏米扑专栏

Linux crond 不执行原因分析

53811
来自专栏GreenLeaves

Oracle 数据库实例和数据库

本文参考自oracle数据库实例,数据库的理解,纯属读书笔记,用于加深记忆。 先看Tom关于这二者的解释: 1、数据库 物理操作系统文件或磁盘的集合(我觉得可以...

23610
来自专栏小尘哥的专栏

中小团队落地配置中心详解

对比了Disconf、Apollo等方案,最终选择了Etcd+Confd的方案,基本符合上边的原则,且Etcd我们在部署Kubernetes的时候已经有过使用,...

3202
来自专栏IMWeb前端团队

代码覆盖率工具 istanbul

代码覆盖率工具 istanbul 1. 代码覆盖率 在测试时,我们的用例把所有代码都覆盖了吗? 对于这个问题引出了代码覆盖率的测试指标,一共有以下4种: 行覆盖...

3025
来自专栏北京马哥教育

Linux学习笔记:文件的权限

Linux 是一个多用户、多任务的系统,常常有多人同时使用一台机工作,为了保护每个人的隐私权,“文件所有者”的角色就显得相当重要了。当Linux用户登录系统之后...

3769
来自专栏中国白客联盟

PIMS三个漏洞+里程密最新版V2.3 SQL注入漏洞

pims在线订单管理系统V4.2.7重装漏洞 程序整天结构如下 ? 安装程序在install目录下,虽然index有验证,代码如下 <?php //检测重...

4186
来自专栏wblearn

我的Github之Pull request的使用

GitHub已经成为的一切开放源码软件的基石。开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目。除了​​代码托管,GitHub的主要吸引力是使用它...

1212
来自专栏钟绍威的专栏

linux常用命令之压缩打包用法选项DEMO注意选项DEMO用法选项用法选项DEMO

DF df – report file system disk space usage 查看文件系统的使用清空 用法 df [-hi] [path]选项-h h...

2209
来自专栏北京马哥教育

出了Linux 故障找不到方法?看大牛简单、朴实的解决思路

本文由马哥教育Linux云计算面授班23期学员推荐,转载自互联网,作者为Lis,Linux资深技术专家,内容略经小编改编和加工,观点跟作者无关,最后感谢作者的辛...

4276
来自专栏云计算教程系列

如何在Ubuntu 14.04上安装Cassandra并运行单节点集群

Cassandra或Apache Cassandra是一个高度可扩展的开源NoSQL数据库系统,在多节点设置上实现了出色的性能。

2503

扫码关注云+社区

领取腾讯云代金券