Redis主从、集群从理论到实践

Redis主从、集群

学习一下Redis主从备份和集群的一些概念,动手搭建一个有主从备份的集群。

安装

简单说明一下安装方式,分为tar包安装和docker安装两种。

tar包安装

wget http://download.redis.io/releases/redis-6.0.5.tar.gz
tar xzf redis-6.0.5.tar.gz
cd redis-6.0.5
make

启动

src/redis-server

访问

src/redis-cli

docker 安装

首先我们下载redis镜像:

  • docker search redis:4.0
  • docker pull redis:4.0

创建docker容器的本地挂载文件夹,所有数据保存在该文件夹下:

  • mkdir ~/文档/_04dockervolume/redis/{conf,data} -p

获取 redis 的默认配置模版并进行配置的修改,主要是redis 的 logpasswordappendonly

cd ~/文档/_04dockervolume/redis

wget https://raw.githubusercontent.com/antirez/redis/4.0/redis.conf -O conf/redis.conf
# 修改 config 文件中的以下内容
appendonly yes
dbfilename dump.rdb
appendfilename "appendonly.aof"
logfile "access.log"
requirepass 123456

创建并运行一个名为 myredis 的容器:

cd ~/文档/_04dockervolume/redis

docker run \
-v $PWD/data:/data:rw \
-v $PWD/conf/redis.conf:/etc/redis/redis.conf:rw \
--privileged=true \
--name myredis \
-d redis:4.0 redis-server /etc/redis/redis.conf

访问容器:

  • docker exec -it myredis redis-cli -a 123456
  • 或者进入redis后,直接auth ${password}

配置管理

# 获取全部config键值
config get *
# 获取某个config键
config get loglevel
# 设置某个config键l
config set loglevel debug

主从实践

Redis虽然具有持久化功能,但是硬盘坏了就没办法了。所以需要主从备份。其中一个磁盘坏了,还有其他机器可用。

主从机制:一主可以多从。从机连接主机后,申请同步,主机先发送rdb,再发送这段实践缓存的命令。

本例设置主从两个redis实例,主机负责写入,从机读取。

起两个容器

  • name为:redis-master、redis-slave
  • 日志分别为:access_master.log、access_slave.log
  • 备份文件分别为:dump_master.rdb、dump_slave.rdb

redis_master

  • conf,修改以下内容
#save 900 1
#save 300 10
#save 60 10000
# 可写
appendonly no
appendfilename "appendonly_master.aof"
dbfilename dump_master.rdb
requirepass 123456
#bind 127.0.0.1
protected-mode no

-启动脚本

cd ~/文档/_04dockervolume/redis

docker run \
-p 6380:6379 \
-v $PWD/data:/data:rw \
-v $PWD/conf/redis_master.conf:/etc/redis/redis.conf:ro \
--privileged=true \
--name redis_master \
-d redis redis-server /etc/redis/redis.conf

redis_slave

  • conf,修改以下内容
# 备份,n秒内m个key变化,则全局备份
save 900 1
save 300 10
save 60 10000
# 只读
appendonly yes
dbfilename dump_slave.rdb
requirepass 123456
#bind 127.0.0.1
protected-mode no
# 主机信息
slaveof redis_master 6379
masterauth 123456

-启动

cd ~/文档/_04dockervolume/redis

docker run \
-p 6381:6379 \
-v $PWD/data:/data:rw \
-v $PWD/conf/redis_slave.conf:/etc/redis/redis.conf:ro \
--link redis_master:redis_master \
--privileged=true \
--name redis_slave \
-d redis redis-server /etc/redis/redis.conf

主从验证

进入master容器:docker exec -it redis_master redis-cli -a 123456

# 查看全部信息
info
# 查看replication信息,看到connected slave=1
info replication
# 设置一个键
set name master

进入slave容器:docker exec -it redis_slave redis-cli -a 123456

info replication
# 返回master,说明备份起作用了
get name
# 提示 You can't write against a read only replica
set name2 slave

集群分区sharding

单个Redis实例,内存上限可以通过config set maxmemory改变,但是内存过大会导致持久化速度变慢,并且单台物理机的内存总是有限的。所以我们需要的是多个适当大小Redis实例组成的集群,能将不同的数据,分派到不同的Redis实例上。

Redis集群数据的分配算法,现在都是哈希槽,而以前用的哈希一致性,也可以了解一下原理。

哈希一致性

以前很流行的一种算法,决定某个key分派到哪个Redis实例。大致意思是实现一个算法

  1. 可以将 Hash(key) 的值保持在 0 ~ 2^32-1内。
  2. 将每个node的一些属性(比如IP、hostname)拿出来,算出一个Hash(node),也在0 ~ 2^32-1内。
  3. 计算一个key对应的node:首先,Hash(node)>Hash(key);其次,Hash(node)最小的那个node;再次,若Hash(key)大于所有Hash(node),就取Hash(node)最小的。

hash一致性环

上图中,起点坐标0、终点坐标2^32-1、Redis节点(node1、node2、node3)、key值(k1…k10)

node1上key值:k6 k7 k8 k9 k10 k1

node2上key值:k2 k3

node3上key值:k4 k5

哈希一致性的缺点是,每个node负责的区域大小不均匀,或者区域内密度不均匀,导致最终的负载不平衡。

这时就衍生出虚拟节点的方式,即每一个节点node,会生成多个Hash(node),称为virtualnode,存在于哈希一致性的环上,通过虚拟节点的庞大的数量,使得每个节点上的key数量趋于平均。

哈希槽

Redis集群现在基本上都是使用hash slot即哈希槽。

一个Redis集群有16384个哈希槽,会分配到集群的master实例上。不同的key,根据CRC16算法,得到一个值,取模16384后,找到对应的slot。换句话说:key对应slot,slot对应master实例。

hash slot和哈希一致性中的virtual node的相同点在于:添加删除master节点,都会导致一部分hash slot的迁移;区别是:哈希一致性的virtual node数量变化了,导致key寻址不再是之前的virtual node,而hash slot的key和slot是严格绑定的,需要迁移的key更容易计算。

常见命令

help @cluster

实际操作

  • 本地创建六个配置文件,在默认的redis.conf内容下,添加以下内容,注意每个文件都要替换序号。
cd ~/文档/_04dockervolume/redis/conf

cat <<EOF >> redis_1.conf
cluster-enabled yes
cluster-config-file "node_1.conf"
dbfilename dump_1.rdb
logfile "access_1.log"
appendfilename "appendonly_1.aof"
appendonly no
EOF
  • 创建redis实例,这里使用docker模式,如果你在物理机上起6个实例也差不多多少
cd ~/文档/_04dockervolume/redis
# 子网
docker network create -d bridge --subnet 172.18.0.0/24 --gateway 172.18.0.1 my_net
# 这里简单处理,不再映射物理磁盘,容器关闭后,数据丢失
awk 'BEGIN{for(i=1; i<=6; i++) print "docker run -d -v $PWD/data:/data:rw -v $PWD/conf/redis_"i".conf:/etc/redis/redis.conf:ro --network my_net --name redis_"i" --privileged=true redis:4.0 redis-server /etc/redis/redis.conf"}'|bash
# 如果上一步有什么问题,通过下面的命令,清除容器
awk 'BEGIN{for(i=1; i<=6; i++) print "docker stop redis_"i" && docker rm redis_"i}'|bash
# 进入某个redis实例
docker exec -it redis_1 redis-cli -h redis_1 -a 123456
  • 使用Cluster命令,连接六个实例,建立集群。
# 查看各个实例地址,172.18.0.2--7
docker inspect redis_1|grep IPAddress
# 以下为redis命令
# 可以看到当前实例所连接的节点
cluster nodes
# 和其他redis实例握手连接,3-7连一遍即可,其他节点会自己互连
cluster meet 172.18.0.3 6379
# 全部握手后,可以看到能互连的节点有6个了。
cluster nodes
# 查看集群状态
cluster info

redis集群互连

  • 由上图可知,slot尚未分配,cluster状态是failed,同时所有节点都是master。
  • 所以我们需要:主从备份、分配slot
  • 以下是设置主从实例
# 查看节点信息
cluster nodes
# 将redis456实例作为从节点,redis234作为主节点
cluster replicate 2915edfe805d6d28e5e9812aca23a10a7e296d1a
# 查看节点信息,需要一点时间同步其他节点的信息,最后能看到3个master 3个slave
cluster nodes

配的图是redis2作为从节点的,就不重新截图了。

cluster replicate

  • 分配hash slot,在三台redis实例
# 这个redis指令在我的4.0版本无法运行,欢迎留言告知原因
cluster addslots {
    
    0..5461}
# 改用shell做一下
echo "docker exec redis_1 redis-cli -h redis_1 -a 123456 cluster addslots "$(awk 'BEGIN{
     
     for(i=0; i<=5461; i++) print i}') | bash
echo "docker exec redis_2 redis-cli -h redis_2 -a 123456 cluster addslots "$(awk 'BEGIN{
      
      for(i=5462; i<=10922; i++) print i}') | bash
echo "docker exec redis_3 redis-cli -h redis_3 -a 123456 cluster addslots "$(awk 'BEGIN{
     
     for(i=10923; i<=16383; i++) print i}') | bash
# 查看
cluster nodes
cluster slots

哈希槽分配

集群验证

# 计算3个key的slot,分别落在哪个节点
cluster keyslot aaaa
cluster keyslot abc
cluster keyslot ab
# 保存key,可以看到如果节点不对,不给保存
set aaaa "should be in 1"
set abc "should be in 2"
set ab "should be in 3"
# 换个正确节点,保存成功。
docker exec -it redis_1 redis-cli -h redis_2 -a 123456 set abc "should in 2"
docker exec -it redis_1 redis-cli -h redis_3 -a 123456 set ab "should in 3"
# 错误节点也无法读取
docker exec -it redis_1 redis-cli -h redis_1 -a 123456 get abc

# 但是加上 -c 参数后,保存和读取都能自动跳转
docker exec -it redis_1 redis-cli -c -h redis_1 -a 123456 get abc
docker exec -it redis_1 redis-cli -c -h redis_1 -a 123456 set ab "should in 3"
# 当然,使用 -c 参数进入redis后,所有操作都自动跳转

集群验证

猜你喜欢

转载自blog.csdn.net/weixin_36572983/article/details/106810465