1 常见redis集群
常见redis集群有RedisCluster、Codis、Twemproxy,其中Codis、Twemproxy是有中心节点的,而RedisCluster是没中心节点,而且是redis内置的集群方案,推荐使用redisCluster集群。
redisCluster特点:
- 无中心节点,客户端与 redis节点直连,不需要中间代理层。
- 数据可以被分片存储,集群数据加起来就是全量数据。
- 可以通过任意一个节点,读写不属于本节点的数据。
- 管理方便,后续可自行增加或删除节点。
由于RedisCluster是分片存储,当集群中一个节点故障时,会损失该节点数据,为了实现高可用,需要对每个节点各添加一个从节点,形成主从同步,当主redis(集群节点)出现故障时,从节点替换故障的主节点。
- Redist集群中的数据库复制是通过主从同步来实现的。
- 主节点( Master)把数据分发给从节点(Slave)。
- 主从同步的好处在于高可用, Redis节点有冗余设计。
- 集群节点个数最好是奇数并且3个以上, 奇数个的好处是,有一个节点出现故障了,集群数量过半数,集群可以继续正常使用,数量少于半数则认为集群瘫痪了。
如果客户端本身带有负载均衡功能,可以省去使用haproxy搭建负载均衡,也可以在程序简单的实现负载均衡功能。
2 单机版redis集群
在单机上搭建3个节点的集群,3个主节点分别有各自的从节点,如图所示:
2.1 修改redis配置文件
因为官方镜像中没有redis配置,也没有启动redis,需要去官方下载对应版本的redis源码获取redis.conf和redis-trib.rb文件,下载官方源码地址:http://download.redis.io/releases/
mkdir redis-cluster
cd redis-cluster
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
tar zxvf redis-4.0.11.tar.gz
# 从源码中复制redis.conf和redis-trib.rb文件到当前目录
cp redis-4.0.11/redis.conf .
cp redis-4.0.11/src/redis-trib.rb .
# 删除redis源码文件
rm -rf redis-4.0.11 redis-4.0.11.tar.gz
因为redis默认没有开启集群功能,需要修改redis配置文件redis.conf,主要修改下面几个参数
bind 0.0.0.0 # 允许外部登录
cluster-enabled yes # 开启集群
cluster-config-file nodes-6379.conf # 集群配置文件
cluster-node-timeout 15000 # 超时时间
appendonly yes # 并开启AOF模式
2.2 重新打包redis镜像
下载指定版本redis官方镜像
docker pull redis:4.0.11
因为官方redis镜像不能满足搭建redis集群要求,需要在官方镜像基础上添加ruby和启动redis命令功能,在当前目录创建Dockerfile文件,文件内容如下:
FROM redis
# 安装ruby
RUN apt-get -y update
RUN apt-get -y install ruby
RUN apt-get -y install rubygems
# ruby 安装redis接口
RUN gem install redis
# 安装vim
RUN apt-get -y install vim
# 启动redis
CMD redis-server /usr/local/etc/redis/redis.conf
2.3 编辑docker-compose.yml文件
在当前目录创建docker-compose.yml文件来管理容器,共6个容器,文件内容如下:
version: "3"
services:
redis-node1:
build:
context: .
dockerfile: Dockerfile
ports:
- 20001:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
# 创建集群的配置文件,只需创建一次,其他节点不需要映射此文件
- ./redis-trib.rb:/usr/local/etc/redis/redis-trib.rb
networks:
- redis-net
redis-node2:
build:
context: .
dockerfile: Dockerfile
ports:
- 20002:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-node3:
build:
context: .
dockerfile: Dockerfile
ports:
- 20003:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-node4:
build:
context: .
dockerfile: Dockerfile
ports:
- 20004:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-node5:
build:
context: .
dockerfile: Dockerfile
ports:
- 20005:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
redis-node6:
build:
context: .
dockerfile: Dockerfile
ports:
- 20006:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
networks:
- redis-net
networks:
redis-net:
driver: bridge
2.4 创建redis集群
当前目录下完整文件列表如下所示:
.
├── docker-compose.yml
├── Dockerfile
├── redis.conf
└── redis-trib.rb
准备好文件后,开始创建redis集群:
# 先打包好新的redis镜像
docker-compose build
# 启动容器
docker-compose up -d
# 获取所有启动redis容器ip地址,获取ip地址是用来创建集群准备
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) | grep redis
# 执行命令的结果如下:
# /redis-cluster_redis-node2_1 - 172.20.0.6
# /redis-cluster_redis-node4_1 - 172.20.0.7
# /redis-cluster_redis-node6_1 - 172.20.0.4
# /redis-cluster_redis-node1_1 - 172.20.0.5
# /redis-cluster_redis-node5_1 - 172.20.0.3
# /redis-cluster_redis-node3_1 - 172.20.0.2
# 进入redis-node1容器,因为只有redis-node1容器映射了redis-trib.rb文件
docker-compose exec redis-node1 bash
# 创建集群
/usr/local/etc/redis/redis-trib.rb create --replicas 1 172.20.0.2:6379 172.20.0.3:6379 172.20.0.4:6379 172.20.0.5:6379 172.20.0.6:6379 172.20.0.7:6379
# 其中参数--replicas 1表示每个主节点有一个从节点。
# 在创建集群过程会提示Can I set the above configuration? 在终端输入yes即可,如果不出现错误,很快就完成集群的创建。
# 创建完集群后,在任意一个redis节点都可以进入redis集群,-c表示连接的是集群
redis-cli -c
# 查看集群节点
127.0.0.1:6379> cluster nodes
# afb979236e96b6e9aac972af7508e4cd9505676d 172.20.0.6:6379@16379 slave 9715f836310b872961a7defc64bdb4a319f9848d 0 1537636386000 5 connected
# 1ffa00413a5f75465e1bb5aaef551c38fb3db1f3 172.20.0.5:6379@16379 myself,master - 0 1537636387000 7 connected 10923-16383
# 9715f836310b872961a7defc64bdb4a319f9848d 172.20.0.2:6379@16379 master - 0 1537636387811 1 connected 0-5460
# d59a0ad710f35fe349f62eda4279e02972983fd3 172.20.0.3:6379@16379 master - 0 1537636386000 2 connected 5461-10922
# c9371c4936d12b9f764e5bf5a7257928aa36cbc2 172.20.0.7:6379@16379 slave d59a0ad710f35fe349f62eda4279e02972983fd3 0 1537636385000 6 connected
# b39a684ad281f03c1befcd90048c503d95526645 172.20.0.4:6379@16379 slave 1ffa00413a5f75465e1bb5aaef551c38fb3db1f3 0 1537636386807 7 connected
# 测试集群的主从复制
127.0.0.1:6379> set testkey 100
# -> Redirected to slot [4757] located at 172.20.0.2:6379
# OK
# 根据172.20.0.2查到对应节点为redis-node3,暂停该容器
docker-compose pause redis-node3
# 然后再次读看是否能够读取到数据
172.20.0.2:6379> get testkey
# "100"
# 此时可以查看到集群节点状态,显示172.20.0.2和集群连接失败状态
127.0.0.1:6379> cluster nodes
2.5 创建带有密码的redis集群
实际使用中一般连接redis是需要密码授权的,添加密码很简单,创建集群前修改redis.conf配置和gems的redis客户端client.rb配置。
删除没有密码的集群容器,重新建一个集群,然后在原来基础上修改配置文件。
docker-compose down
修改redis.conf配置
masterauth 123456
requirepass 123456
进入redis-node1容器,修改redis客户端client.rb配置
# 找出client.rb配置文件位置
find / -name client.rb
# 在配置中添加密码
# 把 :password => nil 改为 :password => 123456
# 创建集群
/usr/local/etc/redis/redis-trib.rb create --replicas 1 172.20.0.2:6379 172.20.0.3:6379 172.20.0.4:6379 172.20.0.5:6379 172.20.0.6:6379 172.20.0.7:6379
# 带密码登录集群
redis-cli -a 123456 -c
2.5 创建集群中遇到的问题
redis-trib.rb create –replicas 1 redis-node1:6379 redis-node2:6379 redis-node3:6379 redis-node4:6379 redis-node5:6379 redis-node6:6379
问题1:使用容器名创建去创建集群报错:”ERR Invalid node address specified”
答:redis-trib.rb 不支持域名或主机名,必须使用ip:port的方式
问题2:创建集群时报错:err slot 0 is already busy (redis::commanderror)
答:由于第一次创建集群没有成功,但还在待创建状态,需要将nodes.conf和dir里面的文件全部删除,如果是在docker创建的话,删除容器重新创建。
专题「数据库」的其它文章 »
- etcd基础与使用 (Nov 15, 2020)
- mongoDB基础和使用 (Feb 24, 2019)
- mysql基础和使用 (Feb 17, 2019)
- redis基础和使用 (Dec 27, 2018)
- 搭建高可用mysql集群PXC (Sep 21, 2018)