Redis-Cluster
简介
为何要搭建Redis集群。Redis是在内存中保存数据的,而我们的电脑一般内存都不大,这也就意味着Redis不适合存储大数据,适合存储大数据的是Hadoop生态系统的Hbase或者是MogoDB。Redis更适合处理高并发,一台设备的存储能力是很有限的,但是多台设备协同合作,就可以让内存增大很多倍,这就需要用到集群。
Redis集群搭建的方式有多种,例如使用客户端分片、Twemproxy、Codis等,但从redis 3.0之后版本支持redis-cluster集群,它是Redis官方提出的解决方案,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。其redis-cluster架构图如下:
客户端与 redis 节点直连,不需要中间 proxy 层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽.
分布存储机制-槽
(1)redis-cluster 把所有的物理节点映射到[0-16383]slot 上,cluster 负责维护
node<->slot<->value
-
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
例如三个节点:槽分布的值如下:
SERVER1: 0-5460
SERVER2: 5461-10922
SERVER3: 10923-16383
容错机制-投票
(1)选举过程是集群中所有master参与,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作. 故障节点对应的从节点自动升级为主节点
(2)整个集群不可用(cluster_state:fail)
如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态.
搭建Redis-Cluster
搭建环境
Centos6.5下的三台redis服务器:
192.168.182.131
192.168.182.132
192.168.182.133
每台服务器搭建两个节点,分别运行在7001和7002端口
准备工作
- 在三台服务器上安装gcc,Redis 是 c 语言开发的。安装 redis 需要 c 语言的编译环境。
yum install gcc-c++
- 将redis源码包上传到三台linux 系统 ,解压redis源码包。
- 编译redis源码 ,进入redis源码文件夹,输入make命令编译源码
make
- 创建目录和实例,创建的目录为:/usr/local/redis-cluster/redis-*(*号为1-6的实例名)
mkdir /usr/local/redis-cluster/redis-*
make install PREFIX=/usr/local/redis-cluster/redis-1
make install PREFIX=/usr/local/redis-cluster/redis-2
在192.168.182.131服务器下创建redis-1和redis-2实例
创建目录
在redis目录下创建实例
在192.168.182.132服务器下创建redis-3和redis-4实例
创建目录
创建实例
在192.168.182.133服务器下创建redis-5和redis-6实例
创建目录
创建实例
- 复制配置文件,将redis-6.2.2/redis.conf复制到各个实例的bin目录下
192.168.182.131:
192.168.182.132:
192.168.182.133:
配置集群
- 修改配置文件
- 更改每个节点的端口号,端口号配置如下
redis-1 192.168.182.131:7001
redis-2 192.168.182.131:7002
redis-3 192.168.182.132:7001
redis-4 192.168.182.132:7002
redis-5 192.168.182.133:7001
redis-6 192.168.182.133:7002
-
将cluster-enabled yes 前的注释去掉,开启集群
-
注释掉bind,关闭保护模式,使得redis可以远程连接
-
设置pidfile为当前实例所对应得端口号,例如配置168.182.131:7001的redis-1 实例,就应该修改其配置文件为7001,而修改redis-2的为7002,如下图
- 启动所有的实例
以第一个实例为例,启动命令如下:
/usr/local/redis-cluster/redis-1/bin/redis-server redis.conf
如果不想启动之后命令窗口被占用,可以让redis后台启动,只需要修改配置文件如下 即可
此时启动后就不会有提示信息了,可以通过进程命令查看,可以看到开启了两个redis实 例,分别运行在7001和7002端口:
ps -ef|grep redis
- 由于使用的是2.2,所以使用redis-cli搭建集群,若是redis5以下则需要使用ruby 搭建,在任意一个redis实例的bin目录下输入以下命令搭建集群,其中–cluster-replicas 1代表一个主节点需要一个从节点
./redis-cli --cluster create 192.168.182.131:7001 192.168.182.131:7002 192.168.182.132:7001 192.168.182.132:7002 192.168.182.133:7001 192.168.182.133:7002 --cluster-replicas 1
输入命令,搭建集群,可以看到集群有三个主节点和三个从节点,且16383个槽都分配 完成,集群搭建完成
连接集群
(1)客户端工具连接
redis-cli -h 主机ip -p 端口(集群中任意端口) -c
测试数据:
-
连接168.182.133:7001,存储name=abc,经过计算需要将name存储到槽5798, 所以重定向到了另一个节点192.168.182.133:7002存储了name的值,然后使用get获取 name的值,成功获取
-
再次连接168.182.133:7001,不加-c参数获取name,可以看到获取不到,因为此 时并没有连接集群,只连接了单个节点。
-
加上-c参数再次连接,获取name,可以看到显示重定向到168.182.133:7002,获 取到了name的值
-
连接集群的任一节点,获取name,都可以获取到
- SpringDateRedis连接
- 创建一个简单的maven项目,编写集群配置文件
redis-config.properties:
-
编写xml文件,配置六个节点:
-
编写测试类:
-
运行查看结果,成功设置和获取值:
-
通过客户端工具查看,可以看到数据的确添加到了集群。
配置集群开机自启和快速连接集群
1. 配置集群开机自启
- 进入/etc/init.d目录,编写一个名为redis的文件作为系统的服务
#!/bin/sh
#redis集群启动文件
#集群所在的端口号
REDISPORT=(7001 7002)
#集群的节点
NODE=(redis-5 redis-6)
#集群实例所在路径
SERVER_PATH=/usr/local/redis-cluster
for ((i=0;i<${#REDISPORT[@]};i++))
do
SERVER_PATH_PREFIX=$SERVER_PATH/${NODE[i]}/bin
#进程守护文件
PIDFILE=/var/run/redis_${REDISPORT[i]}.pid
#服务器执行文件
EXEC=$SERVER_PATH_PREFIX/redis-server
#客户端执行文件
CLIEXEC=$SERVER_PATH_PREFIX/redis-cli
#配置文件
CONF=$SERVER_PATH_PREFIX/redis.conf
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis cluster node ${NODE[i]}..."
cd $SERVER_PATH_PREFIX
$EXEC $CONF &
echo "${NODE[i]} started success!"
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ${NODE[i]} ..."
$CLIEXEC -p ${REDISPORT[i]} shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for ${NODE[i]} to shutdown ..."
sleep 1
done
echo "${NODE[i]} stopped complete!"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
done
echo "Redis cluster operation complete!"
- 将redis注册为一个系统服务,配置开机自启,最后查看redis,可以看到在运行级别都 是启动的
chkconfig --add redis
chkconfig redis on
chkconfig --list redis
- 使用命令开启和关闭redis集群,可以看到停止服务后,使用ps命令查看不到服务开启, 再次使用命令开启,使用ps命令可以看到服务已经开启了。
service redis start //开启服务
service redis stop //关闭服务
- 此时使用scp命令将此文件复制到其他两台服务器,然后在两台服务器上做同样的操作, 即可完成集群开机自启和快速启动,但是要注意此时需要修改redis文件,将实例的名 称修改为对应实例的名字,例如在168.182.132下的redis文件实例名应该为redis-3 和redis-4。
scp redis root@192.168.182.131:$PWD
scp redis root@192.168.182.132:$PWD
2. 快速连接集群
每次都要到bin目录下执行./redis-cli太麻烦了,所以在/bin目录下创建一个redis-cli的软连接,这样就可以在任何地方连接集群了
ln -s /export/servers/redis-6.2.2/src/redis-cli redis-cli
连接集群