• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Redis集群搭建

技术杂谈 勤劳的小蚂蚁 3个月前 (01-14) 73次浏览 已收录 0个评论 扫描二维码

Redis 是一个开源的 key-value 存储系统,由于出众的性能,大部分互联网企业都用来做服务器端缓存。Redis 在3.0版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决单点故障,但是现在互联网企业动辄大几百G的数据,可完全是没法满足业务的需求,所以,Redis 在 3.0 版本以后就推出了集群模式。
Redis 集群采用了P2P的模式,完全去中心化。Redis 把所有的 Key 分成了 16384 个 slot,每个 Redis 实例负责其中一部分 slot 。集群中的所有信息(节点、端口、slot等),都通过节点之间定期的数据交换而更新。
Redis 客户端可以在任意一个 Redis 实例发出请求,如果所需数据不在该实例中,通过重定向命令引导客户端访问所需的实例。
安装环境
  • OS: centos 7.2.1511
  • redis : 最新版 v4.0.1
单台redis安装
下载
tar zxvf redis-4.0.10.tar.gz
mv redis-4.0.10 /usr/local/redis/
如果是离线安装,则需要从官网下载指定版本,然后上传到生产环境。这里安装的是最新版redis,指定安装路径 /usr/local/redis/
编译安装
cd /usr/local/redis
make
make install
安装完成,这时候会在/usr/local/bin/目录下看到redis-server、redis-cli等可执行脚本,进入看一下,如果没有,就要去解压目录复制进去了。
配置redis.conf
redis.conf在默认在安装目录下
$ vim /usr/local/redis/redis.conf
这里要修改两个地方,一个bind和daemonize就行。
要注意的点:
  • bind这里配置要注意,默认是只有一个127.0.0.1,这个时候只能自己连接,其他局域网内是连接不上的。所以,需要配置多个 IP ,这样就可以局域网内进行连接了。我设置的0.0.0.0,虽然这不太安全,方便我在其它地方连接。
  • daemonize是设置是否后台启动 Redis,默认no,正常都需要以服务形式启动 Redis,所以这里设置为yes。
  • 可以设置密码 requirepass mypassord
  • redis v3.0+版本增加了保护机制,默认protected-mode yes, 这样目标机器调用可能会报错,需要设置为no
关于更多配置文件参数的解释,可以参考:
启动redis
cd /usr/local/bin/
redis-server /usr/local/redis/redis.conf
测试redis服务
端口已开启:
netstat -anp | grep6379
命令行连接:
➜  redisredis-cli
127.0.0.1:6379> keys *
1) “city
2) “usage
3) “idc
4) “region
127.0.0.1:6379> setnamejzhou
OK
127.0.0.1:6379> getname
jzhou
127.0.0.1:6379>
关闭服务
可以通过杀进程的方式强制关闭服务,也可以通过命令:
redis-cli shutdown
通过 netstat 可以看出来端口已经是TIME_WAIT状态了
以上是centos7单机部署redis的过程,下面集群搭建和上述类似,不过在目录结构和配置文件不同,当然,遇到的坑也多,主要配置集群依赖一些外部包,但说实话光搭建个集群是没有啥技术含量但…..
redis集群搭建
简介
redis-cluster架构设计
架构细节:
  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效.
  3. 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  4. redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->key
  5. Redis集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。
环境准备
Redis集群中要求奇数节点,所以至少要有三个节点,并且每个节点至少有一备份节点,所以至少需要6个redis服务实例。
这里演示的是我搭的生产环境redis集群,3台服务器,每台起3个服务,共9个节点,生产环境搭建的很顺利,但测试环境一台服务器开6个端口遇到了很多问题,各种依赖包问题,后续会说明。
三台服务器
172.28.37.29
172.28.37.30
172.18.38.219
(每台服务器redis三个端口号 7000~7002)
按照上面搭建单台redis服务的方式在三台服务器分别安装redis,从配置文件开始会有所不同。下面会说明搭建过程。
依赖包安装
注意,下述均安装最新版本,否则会和redis版本不匹配
lib
zlib
ruby
rubugems
开始集群搭建
1. 准备目录结构
三台机器一样,建立如下目录结构:
$ mkdir -p /usr/local/redis/redis-cluster/{7000,7001,7002}
分别进入每个端口目录创建配置文件:
cd  /usr/local/redis/redis-cluster/7000 && touch redis.conf
port7000   # 端口7000,7001,7002,与目录对应
bind 172.28.37.29#默认ip为127.0.0.1,需要改为其他节点机器可访问的ip,否则创建集群时无法访问对应的端口,无法创建集群
daemonize yes   #redis后台运行
cluster-enabled yes  #开启集群
cluster-config-file nodes_7000.conf  #集群的配置,配置文件首次启动自动生成 7000,7001,7002  
cluster-node-timeout 8000   #请求超时,默认15秒,可自行设置
appendonly yes  #开启aof持久化模式,每次写操作请求都追加到appendonly.aof文件中
appendfsync always  #每次有写操作的时候都同步
logfile “/data/redis/logs/redis.log”#redis服务日志
pidfile /var/run/redis_7000.pid  #pidfile文件对应7000,7001,7002
注意,上述有些配置项要对应服务和目录,三个目录按照上述配置好后,启动服务
3.启动/关闭集群服务
可以在每个服务器上写一个启动脚本start-redis.sh:
for((i=0;i<3;i++));
do /usr/local/bin/redis-server /usr/local/redis/redis-cluster/700$i/redis.conf;
done
关闭服务类似:
for((i=0;i<=2;i++));
do /usr/local/bin/redis-cli -c -h $IP -p 700$i shutdown;
done
$IP分别为三台服务器IP。
这时只是启动了9个单独的redis服务,它们还不是一个集群,下面就说明创建集群
4.创建集群
注意:在任意一台上运行 不要在每台机器上都运行,一台就够了
Redis 官方提供了 redis-trib.rb 这个工具,就在解压目录的 src 目录中
在其中一台执行:
$cd /root/redis-4.0.10/src
$ ./redis-trib.rb create –replicas 1 172.28.37.29:7000 172.28.37.29:7001 172.28.37.29:7002 172.28.37.30:7000 172.28.37.30:7001 172.28.37.30:7002 172.18.38.219:7000 172.18.38.219:7001 172.18.38.219:7002
敲完这个命令后会提示是否按照默认的推荐方式配置集群主从,一般选yes就行了
截图中看出,推荐了4个masters,5个从节点
>>> Creatingcluster
>>> Performinghashslotsallocationon 9 nodes
Using 4 masters:
172.28.37.29:7000
172.28.37.30:7000
172.18.38.219:7000
172.28.37.29:7001
Addingreplica 172.18.38.219:7001to 172.28.37.29:7000
Addingreplica 172.28.37.29:7002to 172.28.37.30:7000
Addingreplica 172.28.37.30:7002to 172.18.38.219:7000
Addingreplica 172.18.38.219:7002to 172.28.37.29:7001
Addingreplica 172.28.37.30:7001to 172.28.37.29:7000
下面这个显示了集群和slot分配结果
5.集群验证
参数 -C 可连接到集群,因为 redis.conf 将 bind 改为了ip地址,所以 -h 参数不可以省略,-p 参数为端口号
[root@172-28-37-29 src]# redis-cli-c-p 7000 -h 172.28.37.29
172.28.37.29:7000> setnamezhoujie
> Redirectedtoslot[5798]locatedat 172.28.37.30:7000
OK
172.28.37.30:7000> getname
zhoujie
172.28.37.30:7000>
可以看到在29的7000上设置了name,重定向到了30的7000节点。到此为止集群搭建成功!
友情提示:
当出现集群无法启动时,删除集群配置文件,再次重新启动每一个redis服务,然后重新构件集群环境。
redis-trib.rb命令常见用法
1)列出集群节点-cluster nodes
[root@172-283730 src]# redis-cli -h 172.28.37.30  -c -p 7000
172.28.37.30:7000> cluster nodes
0d260c47f10ecbbfd9c3c1707da82a3dd7951313 172.18.38.219:7001@17001 slave f85a9a80aca5e4c4a1437c7b58abd5895ee66855 015314970020618 connected
6d3db545319a8d41f4ad0666885856257fc2ab5f 172.18.38.219:7002@17002 slave 0cdeba26690238582ad7705abac6de71d1817c9e 015314970020629 connected
3f6c1449e60fe0d868e0bdc655165419ed7cd193 172.18.38.219:7000@17000 master – 015314970030007 connected 819212287
4004ad507da2e7cbae465d7f01864d53972f595c 172.28.37.30:7002@17002 slave 3f6c1449e60fe0d868e0bdc655165419ed7cd193 015314970030627 connected
f85a9a80aca5e4c4a1437c7b58abd5895ee66855 172.28.37.29:7000@17000 master – 015314970040641 connected 04095
7fc5072406e47cd58822f17f5e1ce3b15328352e 172.28.37.30:7000@17000 myself,master – 015314970020004 connected 40968191
fb4554a4fa2bd4af1c213b90ec32d3f7fb12e87b 172.28.37.30:7001@17001 slave f85a9a80aca5e4c4a1437c7b58abd5895ee66855 015314970050665 connected
967243e807a1c0c32ad56db47007c54a2d1d6e2e 172.28.37.29:7002@17002 slave 7fc5072406e47cd58822f17f5e1ce3b15328352e 015314970040644 connected
0cdeba26690238582ad7705abac6de71d1817c9e 172.28.37.29:7001@17001 master – 015314970040642 connected 1228816383
172.28.37.30:7000>
2)查看集群信息- cluster info
172.28.37.30:7000> clusterinfo
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:9
cluster_size:4
cluster_current_epoch:9
cluster_my_epoch:4
cluster_stats_messages_ping_sent:2243335
cluster_stats_messages_pong_sent:2220197
cluster_stats_messages_meet_sent:4
cluster_stats_messages_sent:4463536
cluster_stats_messages_ping_received:2220192
cluster_stats_messages_pong_received:2243339
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:4463536
172.28.37.30:7000>
3)检查集群状态-check
下面内容是测试环境搭建的,一台服务器6个节点
[root@192-168-151-110 redis]# /root/redis-4.0.10/src/redis-trib.rbcheck192.168.151.110:7000
>>> PerformingClusterCheck (using node 192.168.151.110:7000)
M: 7bf58adaafbfee1643785ea7b5da723d6595bbaf192.168.151.110:7000
  slots:0-5460 (5461 slots) master
additionalreplica(s)
S: 90072487e6227544c079b2d8214ef5fd050575b5192.168.151.110:7004
  slots: (0 slots) slave
  replicatesf7374d1b48562c9e54523948915c99bb00a12ba7
M: c6cf17370fc94aabc88e862fa72229ebd9b94166192.168.151.110:7002
  slots:10923-16383 (5461 slots) master
additionalreplica(s)
S: 59d25294cbfb63f2d4d75410e66ce58899c65469192.168.151.110:7003
  slots: (0 slots) slave
  replicates7bf58adaafbfee1643785ea7b5da723d6595bbaf
S: 6256051389337640691e4b44d7de2b7b8c8fa25f192.168.151.110:7005
  slots: (0 slots) slave
  replicatesc6cf17370fc94aabc88e862fa72229ebd9b94166
M: f7374d1b48562c9e54523948915c99bb00a12ba7192.168.151.110:7001
  slots:5461-10922 (5462 slots) master
additionalreplica(s)
[OK]Allnodesagreeaboutslotsconfiguration.
>>> Checkforopenslots
>>> Checkslotscoverage
[OK]All16384slotscovered.
[root@192-168-151-110 redis]#
4)其它常用命令
  • create:创建一个集群环境host1:port1 … hostN:portN(集群中的主从节点比例)
  • call:可以执行redis命令
  • add-node:将一个节点添加到集群里,第一个参数为新节点的ip:port,第二个参数为集群中任意一个已经存在的节点的ip:port
  • del-node:移除一个节点
  • reshard:重新分片
集群操作
//集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
//节点(node)
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
//槽(slot)
CLUSTER ADDSLOTS <slot> [slot …] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot …] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
//键 (key)
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。
向集群中添加节点或删除节点
  • 我们新建两个服务,按照之前搭建的集群方式新增俩个节点:(一主一从 master、slave)。
  • Mater:7007 slave:7008
  • 创建7007/7008文件夹。拷贝redis.conf文件到对于的7007,7008目录下 ,再进行修改配置文件。
  • 启动7007和7008俩个服务并查看服务状态。
1. 集群中添加一个主节点
步骤一:使用add-node命令:绿色为新增节点,红色为已知存在节点
[root@wlan124 local]# /usr/local/redis/src/redis-trib.rbadd-node192.168.151.110:7007  
192.168.151.110:7001
注意:当添加节点成功以后,新增的节点不会有任何数据,因为他没有分配任何slot。需要为新节点手动分配slot。
步骤二:reshard命令,分配slot:
[root@wlan124 local]# /usr/local/redis-3.0.0/src/redis-trib.rb reshard  
192.168.151.110:7007
提示一
How many slots do you want tomove (from1to16384)? 2000
提示二
What is the receiving node ID? 382634a4025778c040b7213453fd42a709f79e28
Please enter all the source node IDs.
 Type ‘all’to use all the nodes assource nodes for the hash slots.
 Type ‘done’ once you entered all the source nodes IDs.
Source node #1:all
提示三
Do you want to proceed with the proposed reshard plan (yes/no)? yes
  1. 提示一:是希望你需要多少个槽移动到新的节点上,可以自己设置,比如200个槽。
  2. 提示二:是你需要把这200个slot槽移动到那个节点上去(需要指定节点id),并且下个提示是输入all为从所有主节点(7001 7002 7003)中分别抽取相应的槽数(一共为200个槽到指定的新节点中!,并且会打印执行分片的计划。)
  3. 提示三:输入yes确认开始执行分片任务
2. 集群中添加一个从节点
步骤一:使用add-node命令:绿色为新增节点,红色为已知存在节点
[root@wlan124 local]# /usr/local/redis/src/redis-trib.rbadd-node192.168.151.110:7008  
192.168.151.110:7001
步骤二:首先需要登录到7008节点的客户端,然后使用集群命令,执行replicate命令来指定当前节点的主节点id为哪一个。把当前的7008(slave)节点指定到一个主节点下(这里使用之前创建的7007主节点,绿色表示节点id)。
[root@wlan124 ~]# /usr/local/redis/bin/redis-cli -c -h 192.168.151.110 -p 7008
192.168.1.124:7008> cluster replicate 4d4cb840519eef342a5730168b6c7e14dd811542
7007的id)

OK

3.集群中删除一个主节点
 如果主节点有从节点,将从节点转移到其他主节点。如果主节点有slot,先将主节点里的slot分配到其他可用节点中,然后再删除节点才行,否则会有数据的丢失。
步骤一:删除7007(master)节点之前,我们需要先把其全部的数据(slot槽)移动到其他节点上去(目前只能把master的数据迁移到一个节点上,暂时做不了平均分配功能)。
[root@wlan124 ~]# /usr/local/redis/src/redis-trib.rb reshard 192.168.151.110:7007
How many slots do you want tomove (from 1to16384)? 1999
(注释:这里不会是正好200个槽)
What is the receiving node ID? 614d0def75663f2620b6402a017014b57c912dad
(注释:这里是需要把数据移动到哪?7001的主节点id)
Please enter all the source node IDs.
 Type ‘all’to use all the nodes assource nodes for the hash slots.
 Type ‘done’ once you entered all the source nodes IDs.
Source node #1:4d4cb840519eef342a5730168b6c7e14dd811542
(注释:这里是需要数据源,也就是我们的7007节点id)
Source node #2:done
(注释:这里直接输入done 开始生成迁移计划)
Do you want to proceed with the proposed reshard plan (yes/no)? yes
(注释:这里输入yes开始迁移)
步骤二:最后我们直接使用del-node命令删除7007主节点即可(蓝色表示7007的节点id)。
[root@wlan124 ~]# /usr/local/redis-3.0.0/src/redis-trib.rb del-node 192.168.151.110:7007 4d4cb840519eef342a5730168b6c7e14dd811542
4.集群中删除一个从节点
步骤一:删除从节点7008,输入del-node命令,指定删除节点ip和端口,以及节点id(蓝色为7008节点id),移除了7008 slave节点,前节点的服务进程也会随之销毁。
[root@wlan124 ~]# /usr/local/redis-3.0.0/src/redis-trib.rb del-node 192.168.151.110:7008 a78c8a41f6430b51a7eca1fdb50092c463a8f1ac
nodejs连接redis集群示例
目前用得最多的 Node.js Redis 库是 node redis,不过这个库基本已经不再维护了,存在很多 bug(在生产环境中碰到过),也缺失了很多功能(如 pipeling 和脚本优化)。而 ioredis 不仅支持了 Cluster 和 Sentinel,还在 API 层面和 node redis 保持了兼容。
const Redis = require(‘ioredis’);
let redis_members = [{
 port: 7000,
 host: ‘172.28.37.29’
}, {
 port: 7001,
 host: ‘172.28.37.29’
}, {
 port: 7002,
 host: ‘172.28.37.29’
}, {
 port: 7000,
 host: ‘172.28.37.30’
}, {
 port: 7001,
 host: ‘172.28.37.30’
}, {
 port: 7002,
 host: ‘172.28.37.30’
}, {
 port: 7000,
 host: ‘172.18.38.219’
}, {
 port: 7001,
 host: ‘172.18.38.219’
}, {
 port: 7002,
 host: ‘172.18.38.219’
}]
var cluster = new Redis.Cluster(redis_members);
cluster.set(‘foo’, ‘bar’);
cluster.get(‘foo’, function (err, res) {
 console.log(‘=====’,res) //===== bar
});
你以为结束了?其实还没有!
集群搭建过程的各种奇葩错误这里汇总,当然下面错误不是一定会遇到,但不保证一定不会不遇到。生产环境我搭的挺顺利,但是测试环境几乎所有能遇到的问题全都遇到了,最后都解决了,特此记录!

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Redis集群搭建
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00