Redis在分布式场景下的应用

news/2024/5/6 13:56:23/文章来源:https://blog.csdn.net/qq_55272229/article/details/133860224

分布式缓存

缓存的基本作用是在高并发场景下对应服务的保护缓冲

– 基于Redis集群解决单机Redis存在的问题

单机的Redis存在四大问题:

  • redis由于高强度性能采用内存 但是意味着丢失的风险
  • 单结点redis并发能力有限
  • 分布式服务中数据过多 依赖内存的redis 明显单机不能满足
  • 如果发生故障 需要能继续服务

很明显上述效果需要集群才能实现

解决方案

在这里插入图片描述

1.Redis持久化

Redis有两种持久化方案:

  • RDB持久化
  • AOF持久化

1.1.RDB持久化

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。

1.1.1.执行时机

RDB持久化在四种情况下会执行:

  • 执行save命令
  • 执行bgsave命令
  • Redis停机时
  • 触发RDB条件时

1)save命令

执行save的命令,可以立即执行一次RDB:
redis是单线程,所以这里会耗时较久
在这里插入图片描述

save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。

2)bgsave命令

下面的命令可以异步执行RDB(background save):

在这里插入图片描述

这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。(异步执行持久化)

3)停机时

Redis停机时会执行一次save命令,实现RDB持久化。
比如先启动redis
在这里插入图片描述
然后停机
在这里插入图片描述
发现redis 输出log 数据保存到磁盘, 以及保存到磁盘上(一般是运行目录无论windos还是linux)
在这里插入图片描述
再次启动
之前保存的数据被读取 实现redis的持久化
在这里插入图片描述
日志输出数据从磁盘读取

4)触发RDB条件

Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1  
save 300 10  
save 60 10000 

RDB的其它配置也可以在redis.conf文件(windos系统是redis.windos.conf)中设置:
在这里插入图片描述
redis
默认持久化策略

# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes# RDB文件名称
dbfilename dump.rdb  # 文件保存的路径目录
dir ./ 

这里为了测试把触发持久化事件改短一点
在这里插入图片描述
5秒内发生修改就持久化
重启后 设置一个数据
日志输出
在这里插入图片描述
后台备份成功
设置备份时间的间隔应该考虑业务中数据量的大小和耗时

1.1.2.RDB原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

在这里插入图片描述

所以如果在分布式业务中,有一台服务器是专门用于做缓存,那么的为了redis的备份机制正常运行,应该预留一些内存给子进程fork

1.1.3.小结

RDB方式bgsave的基本流程

  • fork主进程得到一个子进程,共享内存空间
  • 子进程读取内存数据并写入新的RDB文件
  • 用新RDB文件替换旧的RDB文件

RDB会在什么时候执行

  • 默认是服务停止时
  • 可以通通过配置环境修改频率

RDB的缺点

  • RDB执行间隔时间长(如果修改配置备份时间变短,会大致大量资源消耗,耗时压力更大),两次RDB之间写入数据有丢失的风险
  • fork子进程、压缩、写出RDB文件都比较耗时

1.2.AOF持久化

1.2.1.AOF原理

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,因为记录的不是完整的数据,而是数据的操作命令 可以看做是命令日志文件。

在这里插入图片描述
当redis 宕机 ,redis重启后 读取aof文件,执行指令来恢复数据

1.2.2.AOF配置

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"

选择执行AOF前先将rdb 策略进行注释

在这里插入图片描述
开启aof策略
在这里插入图片描述

重启redis
在这里插入图片描述
log rdb 没有读取 说明确实禁止了
然后写几个存储
在这里插入图片描述

此时aof 文件出现当前目录
在这里插入图片描述
打开查看 确实记录的是命令
在这里插入图片描述
关闭服务且从重启
在这里插入图片描述
关闭时候同步到本地日志
在这里插入图片描述
读取数据 成功 并没丢失
在这里插入图片描述

AOF的命令记录的频率也可以通过redis.conf文件来配:

# 表示每执行一次写命令,立即记录到AOF文件 redis是单线程业务 这样的同步需求 对性能消耗较大
appendfsync always 
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

三种策略对比:

在这里插入图片描述

1.2.3.AOF文件重写

因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

在这里插入图片描述

如图,AOF原本有三个命令,但是set num 123 和 set num 666都是对num的操作,第二次会覆盖第一次的值,因此第一个命令记录下来没有意义。

所以重写命令后,AOF文件内容就是:mset name jack num 666

在最后一次写入操作后执行
在这里插入图片描述

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写 
auto-aof-rewrite-min-size 64mb 

1.3.RDB与AOF对比

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

在这里插入图片描述

2.Redis主从

2.1.搭建主从架构

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群(之前的常用集群模式是负载均衡),实现读写分离。

Redis集群和主从复制是两种不同的Redis部署模式,它们各自解决不同的问题和提供不同的功能。以下是它们的主要区别和用途:

  1. Redis主从复制(Replication):

  2. 用途: 主从复制的主要目的是提高数据的可用性和可靠性。在主从复制中,一个Redis主节点(master)会将数据复制给一个或多个从节点(slaves)。

  3. 数据复制: 主节点负责写操作,从节点复制主节点的数据。这有助于实现数据备份和故障恢复。如果主节点出现故障,可以快速切换到从节点来提供服务,从而降低了系统的单点故障风险。

  4. 性能: 主从复制通常不旨在提高性能,因为主节点仍然处理所有的写操作,而从节点主要用于读取和故障切换。

Redis集群(Cluster):

  1. 用途: Redis集群的主要目的是横向扩展Redis以处理大规模的数据和请求。它是一种分布式系统,用于提高性能、负载均衡和高可用性。
    7.数据分片: Redis集群将数据分为多个分片,每个分片可以在集群中的不同节点上。这有助于平衡负载和提高性能,因为请求可以同时分布到多个节点上。
  2. 高可用性: Redis集群也提供了高可用性,因为它可以自动管理节点故障,并在需要时重新分配分片。

为什么不采用负载均衡来搭建Redis集群呢?

负载均衡和Redis集群的目标不同: 负载均衡通常用于分发流量到多个相同的后端服务器,以提高性能和可用性。但Redis集群的目标更广泛,包括数据分片、高可用性、负载均衡等,它们是分布式系统的一部分。

数据一致性和分片: 在负载均衡中,通常不会考虑数据一致性,因为它主要关注请求的分发。然而,Redis集群需要确保数据的一致性和可用性,因此它使用数据分片和复制来实现这一目标。
性能和可用性需求: 如果您需要横向扩展Redis以处理大量请求并提供高可用性,那么Redis集群是更合适的选择。负载均衡通常在单一后端服务或多个相同的后端服务之间分发请求,但它不提供数据的分片和自动故障切换。

综上所述,Redis主从复制和Redis集群是针对不同需求的两种不同部署方式。您应根据您的具体需求和目标来选择适当的部署方式。如果需要横向扩展和高可用性,Redis集群可能更适合您。如果只需备份和故障切换,主从复制可能足够。负载均衡通常在应用层用于分发请求到多个Redis节点,但它通常不提供数据分片和高可用性功能。

在这里插入图片描述

这里采用docker实现采用

Docker 部署主从redis集群

创建一个目录作为演示集群的文件目录,其中创建三个7001,7002,7003表示redis的三台实列目录,端口和目录名字对应

在这里插入图片描述
进行各个子目录创建对应数据卷挂载目录

创建一个data目录 和re创建一个redis.config
在这里插入图片描述
配置文件的内容就按照自己从默认reidis中按照需求写更改
然后运行docker 进行挂载
挂载数据券和配置文件

docker run -d -p 7001:6379   -v /home/hadoop/Redis-cluster/7001/redis-data-7001/:/data   
-v /home/hadoop/Rediscluster/7001/redis.config:/data/redis.conf   --name redis7001 redis redis-server /data/redis.conf

进入容器

docker exec -it redis7001  redis-cli

根据配置文件的密码登录后创建数据,在进行重启
在这里插入图片描述
关闭服务

docker stop redis7001

在这里插入图片描述
日志和之前一样

重启

docker start redis7001

日志输出
在这里插入图片描述

读取数据 发现可以做到数据持久化
在这里插入图片描述
按照同样步骤在启动俩台redis容器
在这里插入图片描述
成功启动三台实列
为了实现主从同步 ,将aof模式关闭,开始RDB配置

# 开启RDB
# save ""
save 3600 1
save 300 100
save 60 10000# 关闭AOF
appendonly no

集群配置

在使用Docker搭建Redis集群时,Redis官方提供了一个叫做Redis集群模式的特性。使用集群模式,Redis实例可以在不修改配置文件的情况下组成集群。Redis集群模式是通过Redis的内建集群支持实现的,不需要手动修改配置文件。
在Redis集群中,每个节点都可以是主节点也可以是从节点。节点之间通过Gossip协议进行通信。在Docker中,你可以简单地通过运行多个Redis容器,并在它们之间配置集群。
以下是在Docker中使用集群模式配置Redis集群的步骤:

  1. 创建Redis集群网络:
    首先,创建一个Docker网络,以便在Redis容器之间进行通信。你可以使用以下命令创建一个名为redis-net的网络:
    docker network create redis-net

  2. 启动Redis容器:
    运行多个Redis容器,并将它们加入到redis-net网络中。在这里,你只需要指定容器的名称、网络、端口映射等信息。Docker会为每个容器自动分配一个唯一的Container ID和IP地址。

docker run -d --name redis-node1 --net redis-net -p 7001:6379 redis
docker run -d --name redis-node2 --net redis-net -p 7002:6379 redis
docker run -d --name redis-node3 --net redis-net -p 7003:6379 redis
# ...添加更多的Redis节点
  1. 配置集群:
    连接到任意一个Redis容器中,并使用redis-cli命令配置集群。在下面的命令中,你需要指定所有的Redis节点地址及端口,以及–cluster-replicas 1参数表示每个主节点有一个从节点:
docker exec -it redis-node1 redis-cli --cluster create \172.18.0.2:6379 172.18.0.3:6379 172.18.0.4:6379 \172.18.0.5:6379 172.18.0.6:6379 172.18.0.7:6379 \--cluster-replicas 1

上述命令中,172.18.0.2至172.18.0.7是各个Redis容器的IP地址。运行这个命令后,Redis集群就会自动配置好,每个节点都知道其他节点的信息。
4. 验证集群配置:
你可以使用以下命令验证Redis集群的配置是否成功:

docker exec -it redis-node1 redis-cli cluster nodes

这将显示Redis集群的节点信息。如果所有节点都显示正常,那么你的Redis集群就已经配置成功了,这里主要演示主从结果,所以不做演示

请注意,这种配置方式是基于Docker内建的集群支持实现的,不需要手动修改配置文件。但在生产环境中,你可能需要进一步配置安全性、持久性和高可用性等方面的参数,以确保集群的稳定性和安全性。

2.2.主从数据同步原理

2.2.1.全量同步

主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程:

在这里插入图片描述

这里有一个问题,master如何得知salve是第一次来连接呢??

有几个概念,可以作为判断依据:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid,从节点第一次申请同步id不同,所以会接收到 主节点的数据,后续操作进行通信时,id相等,说明以及是同步
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。

因为slave原本也是一个master,有自己的replid和offset,当第一次变成slave,与master建立连接时,发送的replid和offset是自己的replid和offset。

master判断发现slave发送来的replid与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。

master会将自己的replid和offset都发送给这个slave,slave保存这些信息。以后slave的replid就与master一致了。

因此,master判断一个节点是否是第一次同步的依据,就是看replid是否一致

如图:

在这里插入图片描述

完整流程描述:

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

2.2.2.增量同步

全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了,资源消耗过多。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步

什么是增量同步?就是只更新slave与master存在差异的部分数据(主节点数据更新,从结点因为宕机或网络问题没有一直,只做这部分差异更新)。如图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.2.3.repl_backlog原理

master怎么知道slave与自己的数据差异在哪里呢?

这就要说到全量同步时的repl_baklog文件了。

这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。

repl_baklog中会记录Redis处理过的命令日志及offset,包括master当前的offset,和slave已经拷贝到的offset:

在这里插入图片描述

slave与master的offset之间的差异,就是salve需要增量拷贝的数据了。

随着不断有数据写入,master的offset逐渐变大,slave也不断的拷贝,追赶master的offset:

在这里插入图片描述

直到数组被填满:

在这里插入图片描述

此时,如果有新的数据写入,就会覆盖数组中的旧数据。不过,旧的数据只要是绿色的,说明是已经被同步到slave的数据,即便被覆盖了也没什么影响。因为未同步的仅仅是红色部分。

但是,如果slave出现网络阻塞,导致master的offset远远超过了slave的offset:

在这里插入图片描述

如果master继续写入新数据,其offset就会覆盖旧的数据,直到将slave现在的offset也覆盖:
在这里插入图片描述

棕色框中的红色部分,就是尚未同步,但是却已经被覆盖的数据。此时如果slave恢复,需要同步,却发现自己的offset都没有了,无法完成增量同步了。只能做全量同步。

在这里插入图片描述

2.3.主从同步优化

主从同步可以保证主从数据的一致性,非常重要。

可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。(要求服务器网络高,而读取磁盘慢,不然会造擦网络服务堵塞)
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

主从从架构图:

在这里插入图片描述

主从关系实现

现在三个实例还没有任何关系,要配置主从可以使用replicaof 或者slaveof(5.0以前)命令。

有临时和永久两种模式:

  • 修改从结点配置文件(永久生效)
    官方配置文件默认注释
    在这里插入图片描述

    • 在redis.conf中添加一行配置:slaveof <masterip> <masterport>
    • 有密码的需要配置密码
slaveof 192.168.249.132 7001
masterauth 222222
  • 使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):

    slaveof <masterip> <masterport>
    

这里有密码 所以配置主从模式的信息 7002,7003配置
在这里插入图片描述
删除旧容器,按照配置文件在启动一遍

关闭任一容器查看日志 修改配置成功变回了redis默认的RDB
在这里插入图片描述
进入主节点容器7001 使用

# 查看状态
info replication

发现只有master一个结点,这里需要配置

docker 容器进入同一网络

因为docker 容器是互相独立的是,很多时候网络不在一起无法链接删除三个容器,先配置在同一docker网络中

  1. 创建网络
docker network create my_redis_network

2.运行时候指定docker网络 三个容器使用同一个网络

network=xxxx
改进后

docker run -d -p 7001:6379   -v /home/hadoop/Redis-cluster/7001/redis-data-7001/:/data   -v /home/hadoop/Redis-cluster/7001/redis.config:/data/redis.conf     --network my_redis_network     --name redis7001 redis redis-server /data/redis.confdocker run -d -p 7002:7002   -v /home/hadoop/Redis-cluster/7002/redis-data-7002/:/data   -v /home/hadoop/Redis-cluster/7002/redis.config:/data/redis.conf     --network my_redis_network     --name redis7002 redis redis-server /data/redis.confdocker run -d -p 7003:6379   -v /home/hadoop/Redis-cluster/7003/redis-data-7003/:/data   -v /home/hadoop/Redis-cluster/7003/redis.config:/data/redis.conf     --network my_redis_network     --name redis7003 redis redis-server /data/redis.conf
  1. 三个容器运行时候都拉入同一网络,查看从结点日志
    在这里插入图片描述
    这个时候不在拒绝而是successful ,进入主节点容器后查看结点状态
  2. docker exec -it redis7001 redis-cli进入容器
  3. 登录redis后查看状态
    输入INFO 在这里插入图片描述
    此时就可以看到完整的主从结构
    在这里插入图片描述
    主结点写一个数据
    在这里插入图片描述
    从结点可以读取出来
    在这里插入图片描述
    并且无法在进行写数据了
    在这里插入图片描述
    所以默认主从结点完成读写分离,从结点失去写入功能,从节点作为数据读取的副本

这里采用指令链接,但是后续搭配哨兵机制以后修改为配置文件链接,因为测试哨兵机制需要多次重启,并且由主从结构的日志截图可以看出,同一网络下运行的docker容器交互采用的是容器内的端口,为了防止后期哨兵集群部署后,结点数据量大,容器内端口冲突等,建议容器内端口修改为和映射宿主机端口一致

这样避免一些为网络问题
在这里插入图片描述

docker运行redis主从模式总结

1.首先配置创建对应的redis容器的数据卷和配置文件,方便挂载
2. 数据备份采用默认的RDB
3. 创建一个docker 网络 运行时候保证在同一网络
4.子实列配置文件写清楚主节点信息

slaveof 主结点ip 端口
masterauth 密码
  1. docker 运行时指定network

2.4.小结

简述全量同步和增量同步区别?

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。
  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave

什么时候执行全量同步?

  • slave节点第一次连接master节点时
  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

3.Redis哨兵

微服务中有专门的安全保护框架seatenl来对整个分布式进行保护,redis集群躲起来以后,同样的也内置了redis缓存集群监控保护机制
Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

3.1.哨兵原理

3.1.1.集群结构和作用

哨兵的结构如图:

在这里插入图片描述

哨兵的作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

3.1.2.集群监控原理

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

•主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线

•客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

在这里插入图片描述

3.1.3.集群故障恢复原理

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  • 如果slave-prority一样,则判断slave节点的offset值,越大(偏移量越大,主从数据越接近)说明数据越新,优先级越高
  • 最后是判断slave节点的运行id大小,越小优先级越高。

当选出一个新的master后,该如何实现切换呢?

流程如下:
这里假设master7001出现故障

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

在这里插入图片描述

3.1.4.小结

Sentinel的三个作用是什么?

  • 监控
  • 故障转移
  • 通知

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线(和nacos一样的心跳机制)
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点配置,添加slaveof 新master

3.2.搭建哨兵集群 (docker实现)

依旧采用docker 实现,相比于直接部署服务器,docker 环境隔离,轻量的优点可太爽了

  1. 创建Docker网络:
    首先确保所有的Redis实例和哨兵实例都在同一个网络中:
docker network create redis-net  #之前的redis 主从集群就已经运行到一个网络了
  1. 启动Redis容器:
    您可以启动多个Redis容器实例。假设您启动了三个:
docker run -d --name redis1 --net redis-net redis
docker run -d --name redis2 --net redis-net redis
docker run -d --name redis3 --net redis-net redis

这里之前就已经创建并且启动了三个容器
在这里插入图片描述

  1. 创建哨兵配置文件:
    新建三个目录存放哨兵文件,以及后续的docker中哨兵工作目录的挂载
    s1,s2,s3
    在这里插入图片描述

创建一个基础的sentinel.conf文件:

port 27001 #端口
sentinel monitor mymaster 192.168.249.132 7001 2
# 设置主服务器结点密码
sentinel auth-pass mymaster 222222
sentinel down-after-milliseconds mymaster 5000 #超时时间默认
sentinel failover-timeout mymaster 60000

解读:

  • port 27001:是当前sentinel实例的端口
  • sentinel monitor mymaster 192.168.249.132 7001 2:指定主节点信息 (通过主节点就可以检测到从结点,所以redis主从架构中,主节点可以代表一个集群)
    • mymaster:主节点名称,自定义,任意写
    • 192.168.249.132 7001 :主节点的ip和端口
    • 2:选举master时的quorum(这里三个哨兵 超过2就检查不到心跳ping就客观下下线)值
    • 如果不i是docker的话 工作目录实在这个配置文件中指定的目录
      dir “/tmp/s1”
      s1新建一个如上配置
      在这里插入图片描述
  1. 把配置文件复制到其他哨兵工作目录:

在这里插入图片描述
然后修改端口,端口需要修改的,虽然docker 可以映射到宿主机的端口,但是docker网络内通信,使用的是docker 容器端口
在这里插入图片描述
在这里插入图片描述

  1. 启动哨兵容器:
    启动前先查看docker 网络,要确定哨兵和容器能够在同一网络,确保容器通行
 docker network ls

就像之前的主从结构一样,docker容器之间通信需要保证同一网络,并且在通信端口是容器内端口
可以申明时定义同一网络 端口和ip
使用这两个参数后,从节点发送给主节点的ip和端口信息就是这里设定好了
实列在其他电脑,在Docker哨兵的配置中将sentinel announce-ip设置为远程计算机上Redis节点的IP地址。这样,Docker哨兵将正确地宣告Redis节点的位置给其他哨兵和Redis客户端,以便它们知道如何连接到Redis节点。

replica-announce-ip 5.5.5.5
replica-announce-port 1234

哨兵的配置

sentinel announce-ip <ip>
sentinel announce-port <port>

sentinel announce-ip :此选项允许您指定Redis Sentinel应向其他Sentinel实例宣告其监视的Redis实例的IP地址。您应该将其设置为Redis实例所在主机的IP地址。这在Redis实例的实际IP地址与其他Redis Sentinel实例和客户端应用于连接的IP地址不同时非常有用。例如,如果Redis运行在Docker容器中,您可能希望宣告主机机器的IP地址。

sentinel announce-port :此选项指定Redis Sentinel应向其他Sentinel实例宣告的Redis实例的端口。您应该将其设置为Redis实例实际监听的端口。

如果出现同一dockker网络下无法通信就要配置上面的试试

每个哨兵都需要有它自己的配置文件,并挂载到对应的工作目录:

 docker run -d --name sentinel1 --net my_redis_network -p 27001:27001 -v /home/hadoop/Redis-cluster/s1:/data -v /home/hadoop/Redis-cluster/s1/sentinel.conf:/etc/sentinel.conf redis redis-sentinel /etc/sentinel.confdocker run -d --name sentinel2 --net my_redis_network -p 27002:27002 -v /home/hadoop/Redis-cluster/s2:/data -v /home/hadoop/Redis-cluster/s2/sentinel.conf:/etc/sentinel.conf redis redis-sentinel /etc/sentinel.confdocker run -d --name sentinel3 --net my_redis_network -p 27003:27003 -v /home/hadoop/Redis-cluster/s3:/data -v /home/hadoop/Redis-cluster/s3/sentinel.conf:/etc/sentinel.conf redis redis-sentinel /etc/sentinel.conf

docker ps检查运行状态
在这里插入图片描述

现在,哨兵容器会使用s1,s2和s3这三个目录作为它们的工作目录(突然发现好多容器的工作目录都是/data 配置文件目录是/etc)。当哨兵进行某些操作时,您可以查看这些目录来观察它们的状态。
6. 测试您的哨兵集群:
停止主节点,并观察哨兵是否将其他节点提升为新的主节点:

docker stop redis7001

但是发现并没有切换主节点 并且发现日志

Could not rename tmp config file (Device or resource busy)
WARNING: Sentinel was not able to save the new configuration on disk!!!: Device or resource busy

细节

因为Sentinel会在启动后向自己的配置文件中追加内容,它采用的是先创建一个临时配置文件,然后使用它替换掉原来的配置文件的方式。

如果是使用挂载卷直接挂载文件的方式,docker貌似不允许这样操作,所以会出现这个错误,你可以将配置文件放到单独的目录中,然后将目录挂载到容器。

所以三个哨兵目录创建config进行配置目录挂载,而不是文件
每个哨兵文件 新建配置目录config,并把之前的配置文件放进入

在这里插入图片描述
进入整个目录的挂载

docker run -d --name sentinel1 --net my_redis_network -p 27001:27001 -v /home/hadoop/Redis-cluster/s1/data/:/data -v /home/hadoop/Redis-cluster/s1/config/:/etc/ redis redis-sentinel /etc/sentinel.confdocker run -d --name sentinel2 --net my_redis_network -p 27002:27002 -v /home/hadoop/Redis-cluster/s2/data/:/data -v /home/hadoop/Redis-cluster/s2/config/:/etc/ redis redis-sentinel /etc/sentinel.confdocker run -d --name sentinel3 --net my_redis_network -p 27003:27003 -v /home/hadoop/Redis-cluster/s3/data:/data -v /home/hadoop/Redis-cluster/s3/config/:/etc/ redis redis-sentinel /etc/sentinel.conf

此时查看任一哨兵日志
在这里插入图片描述
不在出现警告无法写入磁盘
并且进入任一哨兵容器

docker exec -it 哨兵容器 redis-cli -p 哨兵端口

查看监视该集群的哨兵由那些,就能知道是否能通信了

 SENTINEL sentinels <master-name>

发现可以监控
在这里插入图片描述

日志哨兵日志
在这里插入图片描述
发现成功监控并且知道从主从信息已经同一监控
现在测试停止监控的redis集群 7001

在这里插入图片描述
输出哨兵日志,哨兵监控到结点服务异常

在这里插入图片描述
最重要的一条
在这里插入图片描述
发现选择哨兵选择了7003结点代替原来的主节点,进入7003容器

docker exec -it redis7003 redis-cli -p 7003

输入info
在这里插入图片描述
此时7003成为主要结点,说明哨兵的功能起到作用,防止业务瘫痪,监视集群并且替换主节点

3.2.1 哨兵集群结构

在这里插入图片描述

3.3.RedisTemplate

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

下面,我们通过一个测试来实现RedisTemplate集成哨兵机制。

假如一个一般springboot项目
主要就以下一个controller 通过restful接口 风格操作redis

@RestController
public class HelloController {@Autowiredprivate StringRedisTemplate redisTemplate;@GetMapping("/get/{key}")public String hi(@PathVariable String key) {return redisTemplate.opsForValue().get(key);}//    接口操作数据库@GetMapping("/set/{key}/{value}")public String hi(@PathVariable String key, @PathVariable String value) {redisTemplate.opsForValue().set(key, value);return "success";}
}

3.3.2.引入依赖

在项目的pom文件中引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3.3.3.配置Redis地址

然后在配置文件application.yml中指定redis的sentinel相关信息:
在sentinel 模式下,主从模式的集群有可能会随着业务变更,所以只需要配置监控者,就可以得到被监控的信息

spring:redis:sentinel:master: mymasternodes:- 192.168.249.132:27001- 192.168.249.132:27002- 192.168.249.132:27003password: 222222

我redis密码集群吧都是222222

3.3.4.配置读写分离

在项目的启动类中,添加一个新的bean:

Lettuce 是实现redisTemplate客户端的底层实现框架

@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
//接口不能new 而只有一个方法明显是函数接口return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

主节点设置数据
在这里插入图片描述

测试游览器输入对应api 路径
在这里插入图片描述
游览器操作redis设置数据
在这里插入图片描述
因为controller 返回的
在这里插入图片描述
在redis 图形化库查看
在这里插入图片描述
说明resttemplate都能实现,并且日志也很详细
从集群中的7001端口结点读取
在这里插入图片描述
从7003端口的结点写入
在这里插入图片描述
这个时候手动挂机主节点看看日志‘
在这里插入图片描述
哨兵是已经发先了,并且switch 7002作为新的主结点
而java客户端的日志是不断的发同步数据
在这里插入图片描述
最后确定新的主从结构
检查新的现象 。。。。详细信息
在这里插入图片描述

这个bean中配置的就是读写策略,包括四种:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave(replica)节点读取
  • REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

4.Redis分片集群

4.1.搭建分片集群

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题

  • 高并发写的问题

基本只要可以存储数据的分布式中间件都是采用这种方式,比如hadfs使用分片集群可以解决上述问题,如图:

在这里插入图片描述

分布式场景建议单结点的redis不应该给予太多内存资源,数据输入量大无论是RDB,AOF,数据备份占用的内存都是很高的,大量的io会给架构带来压力

分片集群特征:

  • 集群中有多个master,每个master保存不同数据,保证存储大量数据

  • 每个master都可以有多个slave节点,读写分离,扩大存储量的同时还不会降低读的能力

  • master之间通过ping监测彼此健康状态,这样就代表不在需要哨兵机制,集群间相互通信,自动检查集群内存状态

  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

4.1.0 docker实现redis分片集群

因为我的虚拟机内存大小优先

  1. 删除之前的7001、7002、7003这几个目录,重新创建出7001、7002、7003、8001、8002、8003目录:
    在这里插入图片描述
    每个文件的结构
    在这里插入图片描述

  2. 新建一个配置文件 通用的 redis.conf

#端口
port 7001
#2、修改bind或注释掉
bind 0.0.0.0
#3、保护模式关闭,因为用docker否则无法访问
protected-mode no
#4、关闭后台运行
daemonize no
#5、设置密码
#requirepass myredis
#6、配置与主节点验证的密码
#masterauth 设置密码
#7、开启aof日志
appendonly yes
#8、开启集群模式
cluster-enabled yes
#9、根据你启用的节点来命名,最好和端口保持一致,这个是用来保存其他节点的名称,状态等信息的
cluster-config-file nodes_7001.conf
#10、超时时间
cluster-node-timeout 5000
#11、集群节点 IP:服务器就填公网ip,或者内部对应容器的ip 
cluster-announce-ip 192.168.249.132#12、集群节点映射端口
cluster-announce-port 7001
#13、总线监控ip默认端口+10000 如 7001 就是 17001
cluster-announce-bus-port 17001

每个Redis集群中的节点都需要打开两个TCP连接。用于客户端提供服务,比如6379,还有一个额外的端口(通过在这个端口号上加10000)作为数据端口,例如:redis的端口为6379,那么另外一个需要开通的端口是:6379 + 10000, 即需要开启 16379。16379端口用于集群总线,这是一个用二进制协议的点对点通信信道。这个集群总线(Cluster bus)用于节点的失败侦测 ,如果不配置该项,很可能出现创建集群中一直waiting 线程堵塞

复制到每个文件夹,按照自己的需求进行更改

运行

 docker run -d -p 7001:7001 -p 17001:17001  -v /home/hadoop/Redis-cluster/7001/data/:/data/   -v /home/hadoop/Redis-cluster/7001/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7001   redis redis-server /data/redis.conf docker run -d -p 7002:7002 -p 17002:17002  -v /home/hadoop/Redis-cluster/7002/data/:/data/   -v /home/hadoop/Redis-cluster/7002/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7002   redis redis-server /data/redis.conf docker run -d -p 7003:7003  -p 17003:17003 -v /home/hadoop/Redis-cluster/7003/data/:/data/   -v /home/hadoop/Redis-cluster/7003/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7003   redis redis-server /data/redis.conf docker run -d -p 8001:8001 -p 18001:18001  -v /home/hadoop/Redis-cluster/8001/data/:/data/   -v /home/hadoop/Redis-cluster/8001/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8001  redis redis-server /data/redis.conf docker run -d -p 8002:8002  -p 18002:18002  -v /home/hadoop/Redis-cluster/8002/data/:/data/   -v /home/hadoop/Redis-cluster/8002/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8002  redis redis-server /data/redis.conf docker run -d -p 8003:8003  -p 18003:18003 -v /home/hadoop/Redis-cluster/8003/data/:/data/   -v /home/hadoop/Redis-cluster/8003/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8003  redis redis-server /data/redis.conf 

容器运行成功

在这里插入图片描述
)构建集群

我们使用的是Redis6.2.4版本,集群管理以及集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.249.132:7001 192.168.249.132:7002 192.168.249.132:7003 192.168.249.132:8001 192.168.249.132:8002 192.168.249.132:8003
  • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令
  • create:代表是创建集群
  • --replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master
    因为docker的部署的redis,redis-cli 在容器内 所以运行
  docker exec -it redis7001(任一结点)  redis-cli --cluster create --cluster-replicas 1 192.168.249.132:7001 192.168.249.132:7002 192.168.249.132:7003 192.168.249.132:8001 192.168.249.132:8002 192.168.249.132:8003

结构输出
在这里插入图片描述
redis集群正在分配插槽,然后询问你是否满意这样的分配
回复yes后开始创建集群
在这里插入图片描述
如果出现上述截图就是线程堵塞了,需要开启线程总线配置,并且除了redis端口还要自己暴露总线结点

docker部署redis集群

修改后命令

 docker run -d -p 7001:7001 -p 17001:17001  -v /home/hadoop/Redis-cluster/7001/data/:/data/   -v /home/hadoop/Redis-cluster/7001/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7001   redis redis-server /data/redis.conf docker run -d -p 7002:7002 -p 17002:17002  -v /home/hadoop/Redis-cluster/7002/data/:/data/   -v /home/hadoop/Redis-cluster/7002/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7002   redis redis-server /data/redis.conf docker run -d -p 7003:7003  -p 17003:17003 -v /home/hadoop/Redis-cluster/7003/data/:/data/   -v /home/hadoop/Redis-cluster/7003/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis7003   redis redis-server /data/redis.conf docker run -d -p 8001:8001 -p 18001:18001  -v /home/hadoop/Redis-cluster/8001/data/:/data/   -v /home/hadoop/Redis-cluster/8001/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8001  redis redis-server /data/redis.conf docker run -d -p 8002:8002  -p 18002:18002  -v /home/hadoop/Redis-cluster/8002/data/:/data/   -v /home/hadoop/Redis-cluster/8002/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8002  redis redis-server /data/redis.conf docker run -d -p 8003:8003  -p 18003:18003 -v /home/hadoop/Redis-cluster/8003/data/:/data/   -v /home/hadoop/Redis-cluster/8003/conf/redis.conf:/data/redis.conf  --network my_redis_network   --name redis8003  redis redis-server /data/redis.conf 

此时运行成功
在这里插入图片描述

测试链接任一主节点
集群数据操作时,需要给redis-cli加上-c参数才可以:

redis-cli -c -p 7001

发现保存数据到该节点,最后却转发到另一个结点

在这里插入图片描述

集群中数据插入是根据集群算法来的,会根据转发到这个插槽的结点

redis集群中保存数据,会先对key进行计算,然后保存到计算放置的插槽节点中,并且转发到该结点,这样取值的时候也会根据插槽
进行转发

查看结点情况

 docker exec -it redis7001 redis-cli -p 7001 cluster nodes

在这里插入图片描述

4.2.散列插槽

4.2.1.插槽原理

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

在这里插入图片描述

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  • key中不包含“{}”,整个key都是有效部分

例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

在这里插入图片描述

如图,在7001这个节点执行set a 1时,对a做hash运算,对16384取余,得到的结果是15495,因此要存储到103节点。

到了7003后,执行get num时,对num做hash运算,对16384取余,得到的结果是2765,因此需要切换到7001节点

4.2.1.小结

Redis如何判断某个key应该在哪个实例?

  • 将16384个插槽分配到不同的实例
  • 根据key的有效部分计算哈希值,对16384取余
  • 余数作为插槽,寻找插槽所在实例即可

如何将同一类数据固定的保存在同一个Redis实例?(数据分类)

  • 这一类数据使用相同的有效部分,例如key都以{typeId}为前缀

比如我这里对name 作为key 进行分组,每个组的前缀不同作为分组
在这里插入图片描述

4.3.集群伸缩

redis-cli --cluster提供了很多操作集群的命令,可以通过下面方式查看:

在这里插入图片描述

比如,添加节点的命令:

在这里插入图片描述

4.3.1.需求分析

需求:向集群中添加一个新的master节点,并向其中存储 num = 10

  • 启动一个新的redis实例,端口为7004
  • 添加7004到之前的集群,并作为一个master节点
  • 给7004节点分配插槽,使得num这个key可以存储到7004实例

这里需要两个新的功能:

  • 添加一个节点到集群中
  • 将部分插槽分配到新插槽

4.3.2.创建新的redis实例

创建一个文件夹:

mkdir 7004

拷贝之前配置文件:

cp redis.conf /7004

修改配置文件:

sed /s/6379/7004/g 7004/redis.conf

启动

在这里插入图片描述

4.3.3.添加新节点到redis

添加节点的语法如下:

执行命令:

docker exec -it redis7001 redis-cli --cluster add-node 192.168.249.132:7004  192.168.249.132:7001 

在这里插入图片描述

显示ok 已经成功
通过命令查看集群状态:

redis-cli -p 7001 cluster nodes

如图,7004加入了集群,并且默认是一个master节点:

在这里插入图片描述

在这里插入图片描述

但是,可以看到7004节点的插槽数量为0,因此没有任何数据可以存储到7004上

在这里插入图片描述

4.3.4.转移插槽

我们要将num存储到7004节点,因此需要先看看num的插槽是多少:

如上图所示,num的插槽为2765.

我们可以将0~3000的插槽从7001转移到7004,命令格式如下:

在这里插入图片描述

具体命令如下:

建立连接:

在这里插入图片描述

得到下面的反馈:

在这里插入图片描述

询问要移动多少个插槽,我们计划是3000个:

复制这个id(nodes 命令中7004的id),然后拷贝到刚才的控制台后:

在这里插入图片描述

这里询问,你的插槽是从哪里移动过来的?

  • all:代表全部,也就是三个节点各转移一部分
  • 具体的id:目标节点的id
  • done:没有了

这里我们要从7001获取,因此填写7001的id:可以从多结点分配插槽

在这里插入图片描述

填完后,点击done,这样插槽转移就准备好了:

确认要转移吗?输入yes:
在这里插入图片描述
日志不断输出转移结果
然后,通过命令查看结果:

docker exec -it redis7001 redis-cli -p 7001 cluster nodes在这里插入图片描述

可以看到:

目的达成。

4.4.故障转移

现在集群状态是这样的:

在这里插入图片描述

其中7001、7002、7003,7004都是master,我们计划让7002宕机。

4.4.1.自动故障转移

当集群中有一个master宕机会发生什么呢?

直接停止一个redis实例,例如7002:

 docker stop redis7002

1)首先是该实例与其它实例失去连接

2)然后是疑似宕机:

在这里插入图片描述

3)最后是确定下线,自动提升一个slave为新的master:

4)当7002再次启动,就会变为一个slave节点了:

在这里插入图片描述
这样就通过各个主机之间的心跳检查实现了哨兵的故障转移机制

4.4.2.手动故障转移

利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知(一般是用于服务器硬件升级)的数据迁移。其流程如下
在这里插入图片描述

这种failover命令可以指定三种模式:

  • 缺省:默认的流程,如图1~6歩
  • force:省略了对offset的一致性校验
  • takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见

比如我这个演示的集群手动把7002结点重新变为master

 docker exec -it redis7002 redis-cli -p 7002

在这里插入图片描述
查找结点情况

docker exec -it  redis7001 redis-cli -p 7001 cluster nodes

7002再次成为master
在这里插入图片描述

4.5.RedisTemplate访问分片集群

RedisTemplate底层同样基于lettuce实现了分片集群的支持,所以使用的步骤与哨兵模式基本一致:

1)引入redis的starter依赖

2)配置分片集群地址

3)配置读写分离

与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下:

哨兵

spring:redis:password: 222222sentinel:master: mymasternodes:- 192.168.249.132:27001- 192.168.249.132:27002- 192.168.249.132:27003

集群

spring:redis:cluster:nodes:- 192.168.150.101:7001- 192.168.150.101:7002- 192.168.150.101:7003- 192.168.150.101:8001- 192.168.150.101:8002- 192.168.150.101:8003

测试
使用之前演示的restful操作
在这里插入图片描述
读取成功
在这里插入图片描述
查看日志
在这里插入图片描述
发现主节点7002写内存
而从节点8002读
说明实现了读写分离
在这里插入图片描述
在这里插入图片描述
并且保存结点是根据key计算来确定插槽位置的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_186308.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE编程题目练习(三)

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名Coder&#xff0c;欢迎关注小弟&#xff01; 博主小留言&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟Cool&#xff0…

超低延迟直播技术路线,h265的无奈选择

超低延迟&#xff0c;多窗显示&#xff0c;自适应编解码和渲染&#xff0c;高分辨低码率&#xff0c;还有微信小程序的标配&#xff0c;这些在现今的监控和直播中都成刚需了&#xff0c;中国的音视频技术人面临着困境&#xff0c;核心门户浏览器不掌握在自己手上&#xff0c;老…

前言:自动化框架的设计模式

1、UI自动化框架的设计模式 自动化测试框架有很多种&#xff0c;常见的自动化框架分类如下&#xff1a; 在使用上面的自动化框架时&#xff0c;通常会结合使用分层思想&#xff0c;也就是一些自动化框架设计模式&#xff0c;今天重点分享一下UI自动化框架设计使用比较多的一种…

2023/10/30-LED灯驱动开发

k1.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "head.h" char kbuf[128] {}; unsigned int major; //定义三个指针指向映射后的虚拟内…

STM32:TIM通道输入捕获

本文主要讲解如何使用TIMER通道的输入脉冲捕获功能。基于STM32F7的Timer2 Channel3来进行讲解。 配置时钟 Timer2的时钟频率&#xff0c;对应APB1 Timer。 分频设置为96-1&#xff0c;这样设置每次count计数&#xff0c;对应的时间为1us。Counter设置为最大即可&#xff0c;默…

VMware Workstation里面安装ubuntu20.04的流程

文章目录 前言一、获取 desktop ubuntu20.04 安装镜像二、VMware Workstation下安装ubuntu20.041. VMware Workstation 创建一个新的虚拟机2. ubuntu20.04的安装过程3. 登录ubuntu20.044. 移除 ubuntu20.04 安装镜像总结参考资料前言 本文主要介绍如何在PC上的虚拟机(VMware W…

使用Spyder进行动态网页爬取:实战指南

导语 知乎数据的攀爬价值在于获取用户观点、知识和需求&#xff0c;进行市场调查、用户画像分析&#xff0c;以及发现热门话题和可能的新兴领域。同时&#xff0c;知乎上的问题并回答也是宝贵的学习资源&#xff0c;用于知识图谱构建和自然语言处理研究。爬取知乎数据为决策和…

SolidWorks2021 安装教程(亲测可用)

1.安装教程&#xff1a;&#xff08;断网进行&#xff0c;否则安装了后还是无法用&#xff09; 1.运行sw2021_network_serials_licensing 2. 注册表编辑器确定 3.成功添加到注册表中 4.复制SolidWorks_Flexnet_Server文件夹 5.运行SolidWorks_Flexnet_Server下的lserver_insta…

测试Android webview 加载本地html

最近开发一个需要未联网功能的App, 不熟悉使用Java原生开发界面&#xff0c;于是想使用本地H5做界面&#xff0c;本文测试了使用本地html加载远程数据。直接上代码&#xff1a; MainActivity.java package com.alex.webviewlocal;import androidx.appcompat.app.AppCompatAct…

UE4 UltrDynamicSky与场景物体进行交互

找到材质 找到其最父类的材质 把这个拖过去连上即可

OSI笔记

由7层组成&#xff0c;由下自上分别为&#xff1a; 物理层&#xff08;硬件方面&#xff0c;例如物理网络设备、布线电缆、光纤等&#xff09;&#xff0c; 传输数据主要是比特流0 1 、电信号数据链路层&#xff08;确定了0 1 的分组方式&#xff0c;通过广播的方式&#xff0…

VTK8.0.0编译+QT5.9.2+VS2017

背景 VTK网上资料较多并且使用较多的版本可能是VTK8.2.0&#xff0c;但是由于之前先配置了QT 5.9.2 msvc2017 PCL1.8.1 VTK8.0.0环境&#xff0c;听说有人PCL1.8.1配置VTK8.2.0实测版本不兼容&#xff0c;需修改源码调试&#xff0c;比较麻烦&#xff0c;所以之前就使用的VT…

元梦之星内测上线,如何在B站打响声量?

元梦之星是腾讯天美工作室群研发的超开星乐园派对手游&#xff0c;于2023年1月17日通过审批。该游戏风格可爱软萌&#xff0c;带有社交属性&#xff0c;又是一款开黑聚会的手游&#xff0c;备受年轻人关注。 飞瓜数据&#xff08;B站版&#xff09;显示&#xff0c;元梦之星在…

迅为RK3588开发板Android12单摄方案设备树修改

打开 3588-android12/kernel-5.10/arch/arm64/boot/dts/rockchip/topeet_camera_config.dtsi 设备树&#xff0c;此设备树中对底板上的摄像头接口进行了配置&#xff0c;如下图所示&#xff1a; 如果想要使用 J1 接口打开摄像头 OV5695 或者 摄像头 OV13850&#xff0c;只需要在…

在 Windows Server RDS 服务器 上重置 120 天宽限期

如果您出于测试目的安装了 RDS Server 2016/2019/2022&#xff0c;并且 RDS 许可宽限期已过期&#xff0c;请继续阅读下面的内容以了解如何重置 120 天宽限期。您可能知道&#xff0c;在安装 RDS Server 2016 时&#xff0c;您有 120 天的时间来安装 RD 客户端访问许可证 &…

nginx负载均衡(动静分离)

nginx负载均衡&#xff08;动静分离&#xff09; 文章目录 nginx负载均衡&#xff08;动静分离&#xff09;工作原理&#xff1a;环境说明&#xff1a;部署nginx负载均衡步骤&#xff1a;在负载均衡&#xff08;NGINX&#xff09;主机上做配置&#xff1a;测试&#xff1a;在浏…

驱动编写应用程序控制三盏灯亮灭

应用程序 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> int main(int argc, char const *argv[]) {char buf[128] {0};int fd open("/dev/mych…

点云平面拟合新国标怎么应对?

文章目录 一、应用背景二、算法原理三、代码实现首先我们看一下平面度的概念: 平面度:测量点集合中,在平面上方且距离基准平面最远的点到平面的距离+在平面下方且距离基准平面最远的点到平面的距离。 一、应用背景 在旧标准中,使用最小二乘法去拟合全部点,以拟合平面作为…

QT的QStringList的使用

初始 化 默认构造函数创建一个空列表。可以使用初始值设定项列表构造函数创建包含元素的列表&#xff1a; QStringList fonts { "Arial", "Helvetica", "Times" }; 添加字符串 可以使用insert 、append&#xff08;&#xff09; 和 operator…

RK3568驱动指南|第七期-设备树-第57章 实例分析:中断

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…