【Redis】06--Redis架构设计应用
2021/10/19 2:09:58
本文主要是介绍【Redis】06--Redis架构设计应用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一,Redis主从复制
1.简介
单个Redis支持的读写能力还是有限的,此时我们可以使用多个redis来提高redis的并发处理能力,这些redis如何协同,就需要有一定的架构设计,这里我们首先从主从(Master/Slave)架构进行分析和实现.
2.基本架构
redis主从架构如图所示:
其中,master负责读写,并将数据同步到slave,从节点负责读操作.
3.快速入门
基于redis,设计一主从架构,一个Master,两个Slave,其中Master负责Redis读写操作,并将数据同步到Slave,Slave只负责读.,其步骤如下:
第一:将redis01拷贝两份,例如:
cp -r redis01/ redis02
cp -r redis01/ redis03
第二步:假如已有redis服务,先将原先所有redis服务停止(docker rm -f redis容器名),并启动新的redis容器,例如:
docker run -p 6379:6379 --name redis6379 \ -v /usr/local/docker/redis01/data:/data \ -v /usr/local/docker/redis01/conf/redis.conf:/etc/redis/redis.conf \ -d redis redis-server /etc/redis/redis.conf \ --appendonly yes
docker run -p 6380:6379 --name redis6380 \ -v /usr/local/docker/redis02/data:/data \ -v /usr/local/docker/redis02/conf/redis.conf:/etc/redis/redis.conf \ -d redis redis-server /etc/redis/redis.conf \ --appendonly yes
docker run -p 6381:6379 --name redis6381 \ -v /usr/local/docker/redis03/data:/data \ -v /usr/local/docker/redis03/conf/redis.conf:/etc/redis/redis.conf \ -d redis redis-server /etc/redis/redis.conf \ --appendonly yes
第三步 检测redis服务角色
启动三个客户端,分别登陆三台redis容器服务,通过info指令进行角色查看,默认新启动的三个redis服务角色都为master.
127.0.0.1:6379> info replication
第四步:检测redis6379的ip设置
docker inspect redis6379
第五步:设置Master/Slave架构
分别登陆redis6380/redis6381,然后执行如下语句
slaveof 172.17.0.2 6379
说明,假如master有密码,需要在slave的redis.conf配置文件中添加"masterauth 你的密码"这条语句,然后重启redis再执行slaveof 指令操作.
redis6380
redis6381
第六步:再次登陆redis6379,然后检测info
redis6380
redis6381
第七步: 登陆redis6379测试,master读写都可以
第八步: 登陆redis6380测试,slave只能读。
注意,如果这个redis容器重启了,则不会再有主从关系,需要再次设置,所以如果主从关系设置失败,也可以重启一下。
Java中的读写测试分析,代码如下:
package com.jt; import org.junit.Test; import redis.clients.jedis.Jedis; public class MasterSlaveTests { @Test //Master节点 public void testMasterWrite() { Jedis jedis = new Jedis("192.168.126.128",6379); jedis.set("a1","100"); String a1 = jedis.get("a1"); System.out.println(a1); jedis.close(); } @Test //Slave节点(只允许读) public void testSlaveRead() { Jedis jedis = new Jedis("192.168.126.128",6380); //jedis.set("a1","100"); String a1 = jedis.get("a1"); System.out.println(a1); jedis.close(); } }
运行结果:
如果执行写操作,则会报错
4.主从同步原理分析
Redis的主从结构可以采用一主多从结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。
Redis全量同步:
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
1)从服务器连接主服务器,发送SYNC命令;
2)主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
Redis增量同步
Redis增量复制是指Slave初始化后,开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
5.小节面试分析
如果redis要支持10万+的的并发你会怎么做?
单机的redis几乎不太可能说QPS超过10万+,除非一些特殊情况,比如你的机器性能特别好,配置特别高,物理机,维护做的特别好,而且你的整体的操作不是太复杂,一般的单机也就在几万。真正实现redis的高并发,需要读写分离。对缓存而言,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟几千。读的请求相对就会比较多,例如,一秒钟二十万次读。所以redis的高并发可以基于主从架构与读写分离机制进行实现。
Redis的replication机制是怎样的?
(1)redis采用异步方式复制数据到slave节点。
(2)一个master node是可以配置多个slave node的。
(3)slave node也可以连接其他的slave node。
(4)slave node做复制的时候,是不会block master node的正常工作的。
(5)slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了。
(6)slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量。
二,Redis哨兵模式
1.简介
哨兵(Sentinel)是Redis的主从架构模式下,实现高可用性(high availability)的一种机制。
由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
2.基本架构
3.哨兵快速入门
第一步:分别进入3台redis容器内部进行配置,在容器指定目录/etc/redis创建sentinel.conf文件,文件内容为:
sentinel monitor redis6379 172.17.0.2 6379 1
其中, 如上指令表示要的监控的master, redis6379为服务名, 172.17.0.2和6379为master的ip和端口,1表示多少个sentinel认为一个master失效时,master才算真正失效.
不出意外,是无法创建的文件的,因为再容器中,没有vim指令,会出现bash: vi: command not found类似的错误,可以执行如下指令来安装vim,也不一定需要安装,看下面
apt-get update apt-get install vim
直接复制这两句,执行就好,不用分开写
说明:假如网络不好,也可以在宿主机对应的挂载目录去创建文件,或者在容器中执行:
cat <<EOF > /etc/redis/sentinel.conf sentinel monitor redis6379 172.17.0.2 6379 1 EOF
第二步:在每个redis容器内部的**/etc/redis**目录下执行如下指令(最好是在多个客户端窗口执行),启动哨兵服务
redis-sentinel sentinel.conf
注意如上两步三个容器都需要执行
第三步:打开一个新的客户端连接窗口,关闭redis6379服务(这个服务是master服务)
docker stop redis6379
其它客户端窗口,检测日志输出,例如
第四步:登陆ip为172.17.0.3对应的服务进行info检测,例如:
127.0.0.1:6379> info replication
从上面的信息输出发现,redis6380服务现在已经变为master。
此时redis6380就可以执行读写操作,而redis6391仍然只可以执行读操作
此时我们再启动redis6379(原master),发现redis6379已是slave。
4.Sentinel 配置进阶
对于sentinel.conf文件中的内容,我们还可以基于实际需求,进行增强配置,例如:
cat <<EOF > /etc/redis/sentinel.conf sentinel monitor redis6379 172.17.0.2 6379 1 daemonize yes #后台运行 logfile "/var/log/sentinel_log.log" #运行日志 sentinel down-after-milliseconds redis6379 30000 #默认30秒 EOF
其中:
1)daemonize yes表示后台运行(默认为no)
2)logfile 用于指定日志文件位置以及名字
3)sentinel down-after-milliseconds 表示master失效了多长时间才认为失效
5.哨兵工作原理分析
1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。
2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值(这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒), 则这个实例会被 Sentinel 标记为主观下线。
3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 。
5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 。
6):当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 。
7):若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
8): 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
三,Redis集群高可用
1.简述
Redis单机模式可靠性保证不是很好,容易出现单点故障,同时其性能也受限于CPU的处理能力,实际开发中Redis必然是高可用的,所以单机模式并不是我们的终点,我们需要对目前redis的架构模式进行升级。
Sentinel模式做到了高可用,但是实质还是只有一个master在提供服务(读写分离的情况本质也是master在提供服务),当master节点所在的机器内存不足以支撑系统的数据时,就需要考虑集群了。
Redis集群架构实现了对redis的水平扩容,即启动N个redis节点,将整个数据分布存储在这N个redis节点中,每个节点存储总数据的1/N。redis集群通过分区提供一定程度的可用性,即使集群中有一部分节点失效或无法进行通讯,集群也可以继续处理命令请求。
2.基本架构
对于redis集群(Cluster),一般最少设置为6个节点,3个master,3个slave,其简易架构如下:
3.创建集群
第一步:准备网络环境
创建虚拟网卡,主要是用于redis-cluster能于外界进行网络通信,一般常用桥接模式。
docker network create redis-net
查看docker的网卡信息,可使用如下指令
docker network ls
查看docker网络详细信息,可使用命令
docker network inspect redis-net
第二步:准备redis配置模板
mkdir -p /usr/local/docker/redis-cluster
cd /usr/local/docker/redis-cluster
vim redis-cluster.tmpl
在redis-cluster.tmpl中输入以下内容
port ${PORT} cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 192.168.227.131 cluster-announce-port ${PORT} cluster-announce-bus-port 1${PORT} appendonly yes
按 i 进入编辑模式
按下 esc 键,:wq保存退出
其中:
各节点解释如下所示:
- port:节点端口,即对外提供通信的端口
- cluster-enabled:是否启用集群
- cluster-config-file:集群配置文件
- cluster-node-timeout:连接超时时间
- cluster-announce-ip:宿主机ip
- cluster-announce-port:集群节点映射端口
- cluster-announce-bus-port:集群总线端口
- appendonly:持久化模式
第三步:创建节点配置文件
在redis-cluser中执行以下命令
for port in $(seq 8010 8015); \ do \ mkdir -p ./${port}/conf \ && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf \ && mkdir -p ./${port}/data; \ done
其中:for 变量 in $(seq var1 var2);do …; done为linux中的一种shell 循环脚本, 例如:
指令envsubst <源文件>目标文件,用于将源文件内容更新到目标文件中.
通过cat指令查看配置文件内容
cat /usr/local/docker/redis-cluster/801{0..5}/conf/redis.conf
第四步:创建集群中的redis节点容器
for port in $(seq 8010 8015); \ do \ docker run -it -d -p ${port}:${port} -p 1${port}:1${port} \ --privileged=true -v /usr/local/docker/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \ --privileged=true -v /usr/local/docker/redis-cluster/${port}/data:/data \ --restart always --name redis-${port} --net redis-net \ --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf; \ done
其中, --privileged=true表示让启动的容器用户具备真正root权限, --sysctl net.core.somaxconn=1024 这是一个linux的内核参数,用于设置请求队列大小,默认为128,后续启动redis的启动指令需要先放到这个请求队列中,然后依次启动.
创建成功以后,通过docker ps指令查看节点内容。
第五步:创建redis-cluster集群配置
docker exec -it redis-8010 bash
redis-cli --cluster create 192.168.126.128:8010 192.168.126.128:8011 192.168.126.128:8012 192.168.126.128:8013 192.168.126.128:8014 192.168.126.128:8015 --cluster-replicas 1
注意:这里的192.168.126.128要对应你自己的ip
如上指令要尽量放在一行执行,其中最后的1表示主从比例,当出现选择提示信息时,输入yes即可。
第六步:连接redis-cluster,并添加数据到redis
redis-cli -c -h 192.168.126.128 -p 8010
可见,他会根据你的key值对应的哈希值找到对应的容器存储。
4.其它:
在搭建过程,可能在出现问题后,需要停止或直接删除docker容器,可以使用以下参考命令
批量停止docker 容器:
docker ps -a | grep -i "redis-801*" | awk '{print $1}' | xargs docker stop
批量删除docker 容器:
docker ps -a | grep -i "redis-801*" | awk '{print $1}' | xargs docker rm -f
批量删除文件
rm -rf 801{0..5}/conf/redis.conf
以上就是基于docker搭建redis-cluster的简单步骤,实际应用中可能并没有这么简单,该文也仅用于参考。
四,Jedis读写数据测试
public class JedisClusterTests { @Test public void testJedisCluster() { //1.创建Jedis集群操作对象 Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.126.128",8010)); nodes.add(new HostAndPort("192.168.126.128",8011)); nodes.add(new HostAndPort("192.168.126.128",8012)); nodes.add(new HostAndPort("192.168.126.128",8013)); nodes.add(new HostAndPort("192.168.126.128",8014)); nodes.add(new HostAndPort("192.168.126.128",8015)); //JedisCluster jedisCluster = new JedisCluster(nodes); //定义连接池的配置 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(100); config.setMinIdle(60); JedisCluster jedisCluster = new JedisCluster(nodes,config); //2.执行数据读写操作 jedisCluster.set("username","tony"); String username = jedisCluster.get("username"); System.out.println(username); //3.释放资源 jedisCluster.close(); } }
运行结果
小节面试分析
Redis的高并发跟整个系统的高并发是什么关系?
第一:Redis你要搞高并发的话,不可避免,要把底层的缓存搞得很好。例如,mysql的高并发,是通过一系列复杂的分库分表,订单系统,事务要求的,QPS到几万,比较高了。
第二:要做一些电商的商品详情页,真正的超高并发,QPS上十万,甚至是百万,一秒钟百万的请求量,只有redis是不够的,但是redis是整个大型的缓存架构中,支撑高并发的架构里面,非常重要的一个环节。
第三:你的底层的缓存中间件,缓存系统,必须能够支撑的起我们说的那种高并发,其次,再经过良好的整体的缓存架构的设计(多级缓存架构、热点缓存),支撑真正的上十万,甚至上百万的高并发。
这篇关于【Redis】06--Redis架构设计应用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-08阿里云Redis项目实战入门教程
- 2024-11-08阿里云Redis资料:新手入门与初级使用指南
- 2024-11-08阿里云Redis教程:新手入门及实用指南
- 2024-11-07阿里云Redis学习入门:新手必读指南
- 2024-11-07阿里云Redis学习入门:从零开始的操作指南
- 2024-11-07阿里云Redis学习:初学者指南
- 2024-11-06阿里云Redis入门教程:轻松搭建与使用指南
- 2024-11-02Redis项目实战:新手入门教程
- 2024-10-22Redis入门教程:轻松掌握数据存储与操作
- 2024-10-22Redis缓存入门教程:快速掌握Redis缓存基础知识