Redis集群环境搭建:
Redis 集群简介:
Redis 是一个开源的 key-value 分布式存储系统,由于其出众的性能,大部分互联网企业将其用来作为服务端分布式缓存使用。Redis 在 3.0 以前仅支持单实例模式,也支持主从模式、哨兵模式来达到高可用,避免单点故障。在 3.0 版本以后推出了集群模式,更好的满足业务需求。
Redis 集群采用 P2P 模式,完全去中心化。将所有 Key 分成了 16384 个 slot,每个 Redis 实例负责其中一部分 slot。集群节点之间定期同步数据保持数据一致性。然后,Redis 客户端可以向任一 Redis 实例发起请求,如果所需数据在该实例中不存在,则会通过重定向命令引导客户端访问所需的其他实例。
本文基于 Redis4.0.1 版本搭建集群。
当然,如果你有 Docker 或 K8S 环境,直接从镜像仓库拉取现成的 Redis 镜像后,通过一些参数配置启动后,就可以很快的搭建一套集群环境。
但这种方式使用对你来说是黑盒的,也就是安装过程你是了解不到的。
为了大家方便学习了解,我们还是使用原始的,通过安装包的形式来部署 Redis。
我们准备三台虚拟机,搭建一个三主三从的 Redis 集群。
Redis集群
搭建集群过程如下:
1)下载并安装
下载安装包:
# wget下载安装包
wget http://download.redis.io/releases/redis-4.0.14.tar.gz
# 解压缩
tar xzf redis-4.0.14.tar.gz
# 重命名为redis,并拷贝到/usr/local目录
mv redis-4.0.14 redis
cp -r redis /usr/local
安装依赖包:
yum install -y tcl gcc zlib-devel openssl-devel
编译:
make MALLOC=libc
将常用命令添加到系统PATH:
cp -a /usr/local/redis/src/redis-server
/usr/local/redis/src/redis-cli
/usr/local/redis/src/redis-sentinel
/usr/local/redis/src/redis-trib.rb
/usr/local/redis/src/redis-check-aof
/usr/local/redis/src/redis-check-rdb
/usr/local/redis/src/redis-benchmark
/usr/local/bin/
这样就可以直接在服务器上任意目录使用命令了。
2)集群目录创建并添加配置
创建 Redis 集群目录:
mkdir -p /opt/redis-cluster/nodes-{7001,7002}
执行命令后,在 /opt/redis-cluster 目录会创建 nodes-7001 和 nodes-7002 两个目录。
在上述两个目录下新建 redis.conf 文件,添加文件内容:
# 当前机器IP地址绑定设置port
bind 192.168.0.111
# redis 监听端口
port 7001
# 使用 yes 启用守护进程
daemonize yes
# 当 Redis 以守护进程方式运行时,Redis 默认会把 pid
pidfile redis_7001.pid
# 日志记录级别,共4个级别:debug、verbose、notice(默认)、warning
loglevel notice
# 日志目录
logfile "/opt/redis-cluster/nodes-7001/redis_7001.log"
# 本地数据库存放目录
dir /opt/redis-cluster/nodes-7001/
# 保存节点配置,自动创建,自动更新
cluster-config-file nodes-7001.conf
# 通过upstart和systemd管理Redis守护进程,与具体的操作系统相关的
supervised no
# 每次更新操作后进行日志记录,默认:no
appendonly yes
# 开启集群模式
cluster-enabled yes
# 集群超时时间,节点超过这个时间没反应就断定是宕机
cluster-node-timeout 15000
# 多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
save 900 1
save 300 10
save 60 10000
# 本地数据库的名字
dbfilename dump.rdb
# 存储到本地文件开启压缩,默认:yes
rdbcompression yes
# 更新日志文件名
appendfilename "appendonly.aof"
# 指定更新日志条件:
# no: 等操作系统进行数据缓存同步到磁盘(快)
# always: 每次更新操作后手动调用 fsync() 将数据写磁盘(慢,安全)
# everysec: 每秒同步一次(折中,默认值)
appendfsync everysec
# 密码暂未设置,给出配置
# 当 master 服务设置了密码保护时,slav 服务连接 master 的密码
#masterauth
# 连接密码,客户端需使用AUTH <password>命令连接
#requirepass
其他参数可自行查阅官网文档。
3)下载并安装 ruby
搭建 Redis 集群会使用到 redis-trib.rb 脚本来协助创建,所以需要依赖 ruby。
当然,三台虚拟机都可以安装,或者你选择其中一台虚拟机安装,并记住它,到时就从这台机器上执行命令来创建 Redis 集群。
我们使用的 Centos 7 操作系统,默认没有带 ruby,所以需要单独下载安装。
下载并安装 ruby:
# wget下载ruby安装包
wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.4.tar.gz
# 解压缩
tar xzf ruby-2.3.4.tar.gz
# 拷贝到/usr/local目录下,重命名为ruby目录
mv ruby-2.3.4 /usr/local/ruby
# 编译
cd /usr/local/ruby/ && ./configure && mark && make install
# 查看下安装的版本
ruby -v
如果你的 ruby 版本过低,卸载重装:
ruby -v
rpm -qa | grep ruby
yum erase ruby
安装 ruby-redis.gem:
# 安装 ruby-redis.gem
cd /usr/local/redis && gem install redis
安装过程如果报错如下:
ERROR: Loading command: install (LoadError) cannot load such file – zlib ERROR: While executing gem … (NoMethodError) undefined method invoke_with_build_args for nil:NilClass
解决办法:
cd /usr/local/ruby/ext/zlib
ruby extconf.rb
make && make install
再次执行 gem install redis,如果报错如下:
ERROR: While executing gem … (Gem::Exception) Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources
解决办法:
cd /usr/local/ruby/ext/openssl
ruby extconf.rb
将上个步骤生成的MakeFile文件中的${top_srcdir}都替换为../..
make && make install
3)其他两台虚拟机上重复上述步骤1和2
请记得修改下 redis.conf 文件的端口:
不需要一个个端口修改,编辑文件
vi redis.conf
直接输入如下命令:
:%s/7001/7002/g
就可以批量将 7001 修改为 7002,然后输入 :wq! 退出保存。
4)创建 Redis 集群
使用 redis-trib.rb 脚本创建 Redis 集群,执行如下命令后,会自动分配集群中的 3 个 master 和 3 个 slave。
cd /usr/local/redis/src
./redis-trib.rb create --replicas 1 192.168.0.111:7001 192.168.0.111:7002 192.168.0.112:7001 192.168.0.112:7002 192.168.0.113:7001 192.168.0.113:7002
创建集群过程中遇到:
=>>>Creating cluster [ERR] Sorry, can’t connect to node 192.168.0.111:7001=
解决办法:
关闭防火墙,上文中也已提到过。
安装集群执行结果示例:
输入yes,回车,如下示例:
我们从图中看到了,三个 M(Master)分配了三台虚拟机的 7001 端口,三个 S(Slave)分配了三台虚拟机的 7002 端口。
如果虚拟机重启后,需要再次创建 Redis 集群或者集群中新增节点,可能遇到如下问题:
./redis-trib.rb create --replicas 1 192.168.0.111:7001 192.168.0.111:7002 192.168.0.112:7001 192.168.0.112:7002 192.168.0.113:7001 192.168.0.113:7002
>>> Creating cluster
[ERR] Node 192.168.0.111:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解决方法:
删除节点下面的 dump.rdb、appendonly.aof、nodes-7001.conf 文件,并重启 Redis。
cd /opt/redis-cluster/nodes-7001 && rm -rf dump.rdb appendonly.aof nodes-7001.conf
cd /opt/redis-cluster/nodes-7002 && rm -rf dump.rdb appendonly.aof nodes-7002.conf
# 重启redis,开机自启动,下文中会有详细描述
service redis restart
如果是新增节点,除执行上述命令外,可能会需要登录到节点上删除数据库。
redis-cli -c -h 192.168.0.114 -p 7001
192.168.0.114:7001> flushall
OK
5)测试 Redis 集群
为了测试方便,暂时没有设置集群密码,在上文配置中也有提到了密码设置参数。
使用 redis-cli 客户端登录:
# 直接通过redis-cli命令连接
redis-cli -c -h 192.168.0.111 -p 7001
192.168.0.111:7001> set name zhangsan
-> Redirected to slot [5798] located at 192.168.0.112:7001
OK
192.168.0.112:7001> get name
"zhangsan"
找到其他节点任一 IP 和端口连接查询这个 key:
redis-cli -c -h 192.168.0.113 -p 7001
192.168.0.113:7001> get name
-> Redirected to slot [5798] located at 192.168.0.112:7001
“zhangsan”
说明我们测试的数据在集群之间同步完成了。
查看下集群配置信息:
# redis-cli命令连接节点
redis-cli -c -h 192.168.0.111 -p 7001
# 执行 CLUSTER nodes,看到了集群节点分配的信息
192.168.0.112:7001> CLUSTER nodes
f3b21c6377853c8da63ac6a55fecb1937715ec3b 192.168.0.111:7002@17002 slave 6e81b09991104bf09129aa2bbd226d94d3fcdbe7 0 1574004839302 3 connected
75dec349e2b7fcbcad4d5f5d7979aadefdf69514 192.168.0.113:7002@17002 slave d32ab53d8f93661b09a3c31513fce8c4ed6cbf2b 0 1574004838284 6 connected
6388d80cd9f0a1fbf03d0ac2a309cfedfdb79dc4 192.168.0.111:7001@17001 master - 0 1574004836251 1 connected 0-5460
59f25e64a8ab1fc3309e15d51ea630f439793a94 192.168.0.112:7002@17002 slave 6388d80cd9f0a1fbf03d0ac2a309cfedfdb79dc4 0 1574004840322 1 connected
d32ab53d8f93661b09a3c31513fce8c4ed6cbf2b 192.168.0.113:7001@17001 master - 0 1574004839000 5 connected 10923-16383
6e81b09991104bf09129aa2bbd226d94d3fcdbe7 192.168.0.112:7001@17001 myself,master - 0 1574004837000 3 connected 5461-10922
# 执行 CLUSTER info,看到集群自身的信息
192.168.0.112:7001> 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:6
cluster_my_epoch:3
cluster_stats_messages_ping_sent:1256
cluster_stats_messages_pong_sent:1275
cluster_stats_messages_meet_sent:3
cluster_stats_messages_sent:2534
cluster_stats_messages_ping_received:1273
cluster_stats_messages_pong_received:1259
cluster_stats_messages_meet_received:2
cluster_stats_messages_received:2534
6)设置开机自启动
由于咱们使用的虚拟机,不用的时候可以直接关机,避免一直占用着系统的资源。
当重启虚拟机的时候,如果你不嫌繁琐,可以登录到虚拟机里,直接运行 redis-server 命令启动服务。
更为优雅的方式,当然是开机后自动启动 Redis 服务,这也是生产环境上,研发或运维都必须要关注的,服务器重启,对应的服务也要跟着自动启动,而不需要人为手动干预了。
进入 /etc/init.d/ 目录,创建并编辑 redis 文件:
#!/bin/bash
#chkconfig: 22345 10 90
#description: Start and Stop redis
IP=`ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d '/'`
REDISPORT_1=7001
REDISPORT_2=7002
PIDFILE_1=/opt/redis-cluster/nodes-7001/redis_7001.pid
PIDFILE_2=/opt/redis-cluster/nodes-7002/redis_7002.pid
CONF_1="/opt/redis-cluster/nodes-7001/redis.conf"
CONF_2="/opt/redis-cluster/nodes-7002/redis.conf"
EXEC=/usr/local/redis/src/redis-server
CLIEXEC=/usr/local/redis/src/redis-cli
case "$1" in
start)
if [ -f $PIDFILE_1 ];then
echo "$PIDFILE_1 exists,process is already running or crashed"
else
echo "Starting Redis server... $CONF_1"
$EXEC $CONF_1
fi
if [ -f $PIDFILE_2 ];then
echo "$PIDFILE_2 exists,process is already running or crashed"
else
echo "Starting Redis server... $CONF_2"
$EXEC $CONF_2
fi
;;
stop)
if [ ! -f $PIDFILE_1 ];then
echo "$PIDFILE_1 does not exist,process is not running"
else
PID=$(cat $PIDFILE_1)
echo "Stopping..."
$CLIEXEC -h $IP -p $REDISPORT_1 shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown..."
sleep 1
done
echo "Redis stopped $CONF_1"
fi
if [ ! -f $PIDFILE_2 ];then
echo "$PIDFILE_2 does not exist,process is not running"
else
PID=$(cat $PIDFILE_2)
echo "Stopping..."
$CLIEXEC -h $IP -p $REDISPORT_2 shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown..."
sleep 1
done
echo "Redis stopped $CONF_2"
fi
;;
restart)
"$0" stop
sleep 3
"$0" start
;;
*)
echo "Please use start or stop or restart as first argument"
;;
esac
每台虚拟机有两个 Redis 端口 7001 和 7002,所以对上述脚本做了修改,如果一台机器就一个 Redis 服务就简单多了,大家可自行拷贝脚本修改。
Redis 文件修改为可执行文件:
chmod +x /etc/init.d/redis
添加到系统服务列表:
# 将 /etc/init.d/redis 添加到系统服务列表
chkconfig --add redis
# 设置开机自启动
chkconfig redis on
# 查看所有注册的脚本文件
chkconfig --list
然后,你就不需要去找 Redis 启动命令和配置文件了,方便管理和运维。
有点 low 的启动方式:
/usr/local/redis/src/redis-server /opt/redis-cluster/nodes-7001/redis.conf
/usr/local/redis/src/redis-server /opt/redis-cluster/nodes-7002/redis.conf
比较优雅的启动方式:
# 启动服务
service redis start
# 停止服务
service redis stop
# 重启服务
service redis restart
另外一种开机自启动方式:
将启动命令直接添加到 /etc/rc.d/rc.local 文件中。
修改 rc.local 文件为可执行文件,否则重启后不执行:
chmod +x /etc/rc.d/rc.local
小结:
本文使用 VirtualBox 免费开源的虚拟机软件,一步一步来完成虚拟机环境的搭建。
然后基于三台虚拟机环境,搭建了一套 Redis 集群环境。
通过 redis-trib.rb 脚本来创建 Redis 集群环境,三台机器,6个通讯端口,自动构建为三主三从的集群架构。
根据执行 redis-trib.rb 脚本日志结果,自动分配IP的 Redis 集群架构如下所示:
redis集群架构
对虚拟机安装配置和 Redis 集群安装配置过程中,遇到的问题给出了相应的解决办法,如果你安装过程中还遇到一些新的问题,也可以自行查询相关资料解决。
并且,从上述安装实践过程中,也能学习到很多常用的 Linux 命令。