Redis Cluster
1. Redis Cluster 介绍
Redis Cluster 是 Redis 分布式的解决方案。在 Redis3.0版本正式推出,有效的解决了 Redis 分布式方面的需求。当遇到单机内存不够,并发、流量等瓶颈时,可以采用 Cluster 架构达到负载均衡的目的。
1.1 数据分布理论
分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一部分。常见的分区规则有:哈希分区 和 顺序分区,Redis Cluster 采用哈希分区规则。
常见的哈希分区规则:
- 节点取余
- 一致性哈希
- 虚拟槽
Redis Cluster 采用虚拟槽分区。
虚拟槽分区巧妙的使用了哈希空间,使用分散度良好的哈希函数将所有的数据映射到一个固定范围的整数集合,整数定位为槽(slot)。
Redis Cluster 的哈希槽是0~16384,槽是集群内数据管理和迁移的基本单位。采用大范围的槽,主要目的是为了方便数据的拆分和集群的扩展,每个节点负责一定数量的哈希槽。
1.2 Redis 数据分区
Redis Cluster 采用虚拟槽分区,所有的键根据哈希函数映射到16384个分区,计算公式:slot=CRC16(key)&16383 。每个节点负责维护一部分槽以及槽所映射的键值数据。
Redis 虚拟槽的特点:
- 解耦数据和节点之间的关系,简化了节点扩容和收容的难度。
- 支持自身维持槽的映射关系,不需要客户端或代理服务器维护槽分区元数据。
- 支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景。
1.3 Reids 集群功能限制
Redis Cluster 相对于单机在功能上有一定的限制:
- key 批量操作支持有限。如:mset、mget,目前只支持在同一个slot上执行批量操作。
- key 事务操作支持有效。仅支持在同一节点上多个key的事务操作,不能跨越节点进行事务操作。
- key 作为数据分区的最小粒度,不能将一个大的键值映射到不同的节点。如:hash,set,list
- 集群状态下,只能使用一个数据控件:db0
- 主从复制结构不支持级联,即从节点不能再有从节点
2. 搭建Redis Cluster
使用环境:Centos7.6 + Redis6.0.8
准备工作,具体可看 Linux安装Redis:
# 下载Redis
wget http://download.redis.io/releases/redis-6.0.8.tar.gz
# 将Centos7默认的gcc4,升级到gcc9 (https://www.cnblogs.com/sivanchan/p/13664495.html)
yum install centos-release-scl
yum install devtoolset-9-gcc*
scl enable devtoolset-9 bash
# 将Redis的包解压到安装目录,编译安装
tar -zxvf redis-6.0.8.tar.gz -C /usr/local/redis/
cd /usr/local/redis/redis-6.0.8/
make
make install PREFIX=/usr/local/redis/redis-6.0.8
单机采用多端口的方式,模拟Redis集群。三台主机,每台主机搭配两台从机
# 在Redis目录创建cluster文件夹,并在cluster文件夹下创建9个文件夹保存节点数据,这里使用7001-7009
mkdir -pv cluster/{7001,7002,7003,7004,7005,7006,7007,7008,7009}
修改Redis配置文件:
vi /usr/local/redis/redis-6.0.8/redis.conf
# 将绑定IP注释
bind 127.0.0.1
# 关闭保护模式
protected-mode no
# 修改服务端口号
port 7001
# 后台启动
daemonize yes
# 修改pid保存位置
pidfile /usr/local/redis/redis-6.0.8/cluster/7009/redis_7009.pid
# 设置快照文件的存放路径,是一个目录
dir /usr/local/redis/redis-6.0.8/cluster/7009
# 修改内存策略
maxmemory-policy allkeys-lru
# 开启集群配置
cluster-enabled yes
# 配置node节点
cluster-config-file nodes-7009.conf
# 开启集群超时设定
cluster-node-timeout 15000
# 定义日志级别。
# 默认值为notice,有如下4种取值:
# debug(记录大量日志信息,适用于开发、测试阶段)
# verbose(较多日志信息)
# notice(适量日志信息,使用于生产环境)
# warning(仅有部分重要、关键信息才会被记录)
loglevel notice
# 日志文件
logfile "/usr/local/redis/redis-6.0.8/cluster/log/redis_7001.log"
Redis在生产环境中,采用配置参数maxmemory 的方式来限制内存大小。当实际存储内存超出maxmemory 参数值时,开发者们可以通过这几种方法——Redis内存淘汰策略,来决定如何腾出新空间继续支持读写工作。
参考:Redis内存策略
| Redis内存策略 | 说明 |
|---|---|
| volatile-lru | 为已经添加了超时时间的数据采用LRU算法进行删除 |
| allkeys-lru | 所有的key中通过LRU算法进行删除 |
| volatile-random | 在已经设定超时时间的数据中,随机删除 |
| allkeys-random | 在所有的key中,使用LRU算法进行随机删除 |
| volatile-ttl | 在已经设定超时时间的数据中,根据TTL机制排序,将马上要过期的数据删除 |
| noeviction | (默认的) 如果采用该机制,那么内存数据不会删除,将报错消息返回给用户 |
调整配置文件
# 将原来修改的redis.conf复制到对应的节点目录,并给改成对应的节点信息(端口号等)
cp /usr/local/redis/redis-6.0.8/redis.conf /usr/local/redis/redis-6.0.8/cluster/7001/redis.conf
...
# vim 快速替换 %s/7000/7001/g
启动全部Redis
# !/bin/bash
for i in {1..9}
do
/usr/local/redis/redis-6.0.8/bin/redis-server /usr/local/redis/redis-6.0.8/cluster/700$i/redis.conf
done
# 查看
ps -ef | grep redis
# 杀死全部Redis进程
pkill -9 redis
# 重启不了请清除节点数据
创建集群命令
# --cluster-replicas 2 表示每台主机配置两台从机
# 低版本的使用redis/src/redis-trib.rb create --replicas 2 ...
# 设置了密码的话,加上-a masterauth
./usr/local/redis/redis-6.0.8/bin/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 127.0.0.1:7007 127.0.0.1:7008 127.0.0.1:7009 --cluster-replicas 2
进行测试
public static void main(String[] args) {
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort("152.136.24.98", 7009));
nodes.add(new HostAndPort("152.136.24.98", 7001));
nodes.add(new HostAndPort("152.136.24.98", 7002));
nodes.add(new HostAndPort("152.136.24.98", 7003));
nodes.add(new HostAndPort("152.136.24.98", 7004));
nodes.add(new HostAndPort("152.136.24.98", 7005));
nodes.add(new HostAndPort("152.136.24.98", 7006));
nodes.add(new HostAndPort("152.136.24.98", 7007));
nodes.add(new HostAndPort("152.136.24.98", 7008));
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("Redis", "Redis集群入门");
String result = jedisCluster.get("Redis");
System.out.println(result);
}

浙公网安备 33010602011771号