前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis集群及管理讲解

Redis集群及管理讲解

作者头像
小小科
发布2018-05-04 14:49:49
1.1K0
发布2018-05-04 14:49:49
举报
文章被收录于专栏:北京马哥教育北京马哥教育

一、为什么要弄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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-09-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马哥Linux运维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档