当前位置: 首页 > news >正文

Redis 篇-初步了解 Redis 持久化、Redis 主从集群、Redis 哨兵集群、Redis 分片集群

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

 

文章目录

        1.0 分布式缓存概述

        2.0 Redis 持久化

        2.1 RDB 持久化

        2.1.1 RDB 的 fork 原理

        2.2 AOF 持久化

        2.3 RDB 与 AOF 之间的区别

        3.0 Redis 主从集群

        3.1 搭建主从集群

        3.2 主从的全量同步原理

        3.3 主从的增量同步原理

        4.0 Redis 哨兵集群

        4.1 搭建哨兵集群

        4.2 RedisTemplate 连接哨兵

        5.0 Redis 分片集群

        5.1 搭建分片集群

        5.2 散列插槽

        5.3 集群伸缩

        5.4 故障转移

        5.5 RedisTemp 访问分片集群


        1.0 分布式缓存概述

        分布式缓存是一种用于提高系统性能和可扩展性的技术,它通过在多个节点上存储数据副本来减少数据访问延迟和负载。分布式的出现是为了解决在单点 Redis 的问题。

        在单点 Redis 存在的问题:

        数据丢失问题:通过实现 Redis 数据持久化来解决当前问题。

        并发能力问题:通过搭建主从集群,实现读写分离来解决当前问题。

        存储能力问题:利用 Redis 哨兵,实现健康检测和自动恢复。

        故障恢复问题:搭建分片集群,利用插槽机制实现动态扩容。

  

        2.0 Redis 持久化

        因为 Redis 存储的数据都是在内存中的,所以当 Redis 出现宕机或者断电等情况导致停止服务,那么 Redis 中的数据就会直接丢失掉。

        让 Redis 中的数据可以持久化,也就是将 Redis 中的相关的数据保存在磁盘中。因此,Redis 持久化常见有两种形式:RDB 持久化、AOF 持久化。

        这样就算 Redis 服务出现了宕机,不需要担心数据丢失,可以从磁盘中重新读取之前的数据再进行服务。

        2.1 RDB 持久化

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

        该文件称为 RDB 文件,默认是保存在当前运行目录。

        1)通过执行 Save 命令,Redis 中的数据就会被重新创建一个 dump.rdb 文件记录,来替换原先的文件。

        通过时间,可以看出来已经替换成功了。证明 save 可以用来将 Redis 内存数据进行拷贝到磁盘中,来保证数据持久化。

        但是使用 save 命令会有一个弊端:save 命令由 Redis 主进程来执行 RDB,因此会阻塞所有命令。通过 save 命令来进行数据持久化,一般常用于将当前 Redis 服务器清除之前将数据保证起来,通常 Redis 服务正在运行的时候,是不会直接用 save 命令来保证数据持久化的,因为会阻塞其他请求,从而影响效率。

        在主动将 Redis 服务进行停机之前会自动执行 save 命令,将数据进行保存。重新启动该 Redis 服务之后,会自动从 RDB 文件中获取数据,重新将数据放到内存中。

        2)使用 bgsave 命令开启子进程执行 RDB,避免主进程受到影响。

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

        #3600 秒内,如果至少由一个 key 被修改,则执行 bgsave,如果是 save"" 则表示禁用 RDB

        符合条件就会自动触发,每隔一段时间自动触发。这就保证了在 Redis 服务过程中也可以将数据进行持久化。

RDB 的其他配置也可以在 Redis.conf 文件中设置:

        设置是否压缩 RDB 文件,建议不开启,压缩也会消耗 cpu,磁盘不值钱。

        设置 RDB 文件名称。

        设置 RDB 文件保存的路径目录,默认是当前路径下。

        2.1.1 RDB 的 fork 原理

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

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

        当主进程执行读操作时,访问共享内容。

        当主进程执行写操作时,则会拷贝一份数据,执行写操作。

        简单来说,主进程在进行 fork 子进程的时候会阻塞其他请求,因此需要加快 fork 子进程过程。主进程通过页表来操作内存,因为通过拷贝页表,子进程也就可以读取内存数据了。fork 过程结束之后,主进程解除阻塞状态,可以正常响应请求,而子进程则将内存数据进行读操作,写入磁盘中。在子进程写入磁盘过程中,主进程有可能会进行写操作,所有为了防止脏读的情况,在写数据的时候,将内存的数据进行拷贝,再来进行写操作。

        这也说明了当子进程写入数据的过程中,主进程写操作的请求越多,拷贝的数据也就越多,可能会导致数据溢出。

RDB 的缺点:

        RDB 执行间隔时间长,两次 RDB之间写入数据有丢失风险。

        fork 子进程、压缩、写出 RDB 文件都比较耗时。

        2.2 AOF 持久化

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

        当 Redis 服务需要重新启动,那么直接来读取 AOF 文件,执行所有命令。这就保证了数据持久化。

AOF 持久化,默认是关闭的:

        将 no 改为 yes,则启动 AOF 持久化,通过设置 appendfilename 来修改 AOP 文件名。

AOF 的命令记录的频率:

        AOF 也是异步的将命令写入到磁盘中。

# If unsure, use "everysec".# 表示每执行一次命令,立即记录到AOF文件
# appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每个1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放到AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
# appendfsync no

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

当然不需要我们手动去敲命令,Redis 也会在触发阈值时自动去重写 AOF 文件:

        在配置文件中可以看到:

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

        2.3 RDB 与 AOF 之间的区别

        1)持久化方式:

        RDB:定时对整个内存做拷贝。

        AOF:记录每一次执行的命令。

        2)数据完整性:

        RDB:不完整,两次备份之间会丢失。

        AOF:相对完整,取决于刷盘策略。

        3)文件大小:

        RDB:会有压缩,文件体积小。

        AOF:记录命令,文件体积大。

        4)宕机恢复速度:

        RDB:很快。

        AOF:慢。

        5)数据恢复优先级:

        RDB:低,因为数据完整性不如 AOF。

        AOF:高,因为数据完整性更高。

        6)系统资源占用:

        RDB:高,大量CPU 和内存消耗。

        AOF:低,但是 AOF 重写时会占用大量 CPU 和内存资源。

        7)使用场景:

        RDB:可以容忍数分钟的数据丢失,追求更快的启动速度。

        AOF:对数据安全性要求较高。

        3.0 Redis 主从集群

        在主从集群架构中,主节点(Master)负责处理所有的写操作,而从节点(Slave)则负责处理读操作。这样可以将读写请求分开,从而提高系统的并发处理能力。

        通过搭建主从集群实现读写分离,来解决高并发能力问题。简单来说,就是通过搭建多个从节点来提供"只读"的服务。

        3.1 搭建主从集群

        使用一台云服务器搭建一个主节点和两个从节点。

        将 redis.conf 文件拷贝到三个目录。

root@iZ2ze0lv9jcc14x57qtu1dZ:~/temp# cp /opt/redis-6.2.5/redis.conf 7001
root@iZ2ze0lv9jcc14x57qtu1dZ:~/temp# cp /opt/redis-6.2.5/redis.conf 7002
root@iZ2ze0lv9jcc14x57qtu1dZ:~/temp# cp /opt/redis-6.2.5/redis.conf 7003

        接着分别将文件中 redis.conf 配置进行修改,比如:端口号、RDB 文件的存放路径。

        再来修改每个实例的声明 IP

        为了避免将来混乱,需要在 redis.conf 文件中指定每一个实例的绑定 ip 信息:

        将 ip 换成自己云服务器的 ip 地址。

        启动三个 redis 服务:

        成功启动 redis 服务。

        最后来开启主从关系:

        将 7001 作为 master 主节点、而 7002、7003 作为 slave 从节点。

        其中有临时和永久两种模式:

                1)修改配置文件(永久生效)

                        在 redis.conf 中添加一行配置:

REPLICAOF <masterip> <masterport>

                2)使用 redis-cli 客户端连接到 redis 服务,执行 replicaof 命令(重启后会失效)

                接下来使用临时模式来实现一下:

        此时,已经将 7002 配置成 7001 的从节点。

        因此,不能进行写操作了,读写已经完成分离,主节点负责写操作,而从节点负责读操作。

         需要注意的是,如果主节点已经配置密码了,那么在连接主节点的时候,在从节点的配置文件中设置主节点密码:

         配置完之后,查看连接情况:

        现在已经 7002、7003 两个 slave 节点连接到 7001 master 节点上了。在 7001 中可以读和写,而 7002、7003 只能进行读操作。

        那么考虑一个问题,当 7001 完成写操作之后,7002 可以成功获取数据,数据同步的原理是什么呢?

        因为 7002、7003 自动完成了主从的全量同步或者是增量同步,详细讲解如下:

        3.2 主从的全量同步原理

        先来了解两个概念:

        1)Replication Id:简称 replid,是数据集的标记,id 一致则说明是同一数据集。每一个 master 都有唯一的 replid,slave 则会继承 master 节点的 replid 。

        2)offset:偏移量,随着记录在 rep_baklog 中的数据增多而逐渐增大。slave 完成同步也会记录当前同步的 offset 。如果 slave 的 offset 小于 master 的 offset,说明 slave 数据落后于 master,需要更新。

        当 slave 从节点执行完 replicaof 命令建立连接时,会发送 replid、offset 给 master 节点,接着 master 主节点会判断发送过来的 replid 是否跟当前的 master 的 replid 是否一致,

        如果一致,则说明已经同步过的 slave 从节点,则只需要将在 offset 之后的 repl_baklog 命令发送给 slave 从节点执行接收到的命令即可; 

        如果是不一致,则说明有可能是第一次来建立连接的,那么 master 先会返回主节点的 replid 和 offset ,slave 将版本信息进行保存,master 会 fork 子进程来执行 bgsave,生成 RDB 文件并且发送给 slave ,slave 先清空本地数据,再来加载 RDB 文件。

        在 slave 加载 RDB 文件的时候,master 也会不断接收写操作的请求命令,这些命令会先保存到 repl_baklog 文件中,等待 slave 加载完成之后,master 发送 repl_baklog 中的命令到 slave 节点中,而 slave 节点接收到命令就会执行。

        完成以上的步骤之后,slave 就完成了数据同步了。

        3.3 主从的增量同步原理

        增量同步一般都是用于 slave 重启后同步。

        slave 重启之后,给 master 发送 replid、offset,当 master 判断 replid 与当前 master 的 replid 一致,那么就不会触发 RDB 发送了,而是 master 去 repl_baklog 中获取 offset 后的命令,并且发送到 slave 中,slave 执行命令,这就是增量同步原理。

        需要注意:repl_baklog 大小有上限,写满后会覆盖最早的数据。如果 slave 断开时间过久,导致数据被覆盖,则无法实现增量同步,只能再次全量同步。

        需要知道的是,执行全量同步消耗的资源是非常大的,因此需要优化全量同步或者减少全量同步发生:

        1)在 master 中配置 repl-diskless-sync yes 启用无磁盘复制,避免全量同步的磁盘 IO 。

        2)Redis 单节点上的内存占用不要太大,减少 RDB 导致的过多磁盘 IO 。

        3)适当提高 repl_baklog 的大小、发现 slave 宕机时尽快实现故障,尽可能避免全量同步。

        4)限制 master 上的 slave 节点数量,如果实现是太多 slave,则可以采用主-从-从链式结构。减少 master 压力。

        4.0 Redis 哨兵集群

        思考:slave 节点宕机恢复后可以找 master 节点同步数据,那 master 节点宕机怎么办?

        这时候就需要用到哨兵了。

        Redis 提供了哨兵机制来实现主从集群的自动故障恢复,哨兵的主要功能:

        1)监控:哨兵会不断检查主从集群中的 master 和 slave 是否按预期工作。

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

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

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

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

        首先会判断 slave 与 master 节点断开时间长短,如果超过指定值(down-after-milliseconds*10)则会排除该 slave 节点。

        然后判断 slave 节点的 slave-priority 值,越小优先级越高,如果是 0 则永不参与选举。

        如果 slave-prority 一样,则判断 slave 节点的 offset 值,越大说明数据越新,优先级越高。

        最后是判断 slave 节点的运行 id 大小,越小优先级越高。

        2)自动故障恢复:如果 master 故障,哨兵会将一个 slave 提升为 master 。当故障实例恢复后也以新的 master 为主。

        故障转移步骤:

        sentinel 给备选的 slave 节点发送 slaveof no one 命令,让该节点成为 master。

        sentinel 给所有其他 slave 发送 slaveof 新选举的 master 的 IP 和 Port 命令,让这些 slave 成为新的 master 的从节点,开始从新的 master 上进行全量同步。

        最后,sentinel 将故障节点标记为 slave ,当故障节点恢复后会自动成为新的 master 的 slave 节点。

        3)通知:哨兵充当 Redis 客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给 Redis 的客户端。

        4.1 搭建哨兵集群

        搭建三个哨兵节点,哨兵的配置文件:

解释:

        port 27003:是当前 sentinel 实例的端口。

        sentinel monitor mymaster 8.152.162.150 7001 2:指定 master 节点信息:

                mymaster:主节点名称,自定义。

                8.152.162.159 7001:主节点的 IP 和 端口号。

                2:选举 master 时的 quorum 值。

需要注意:

        如果之前设置密码了,那么在 sentinel.conf 配置文件中添加如下配置:

##如果配置了密码打开下面的注释写上密码 格式: sentinel auth-pass mymaster 12345678
# sentinel auth-pass <master-name> <password>

        最后启动三个哨兵:

redis-sentinel s1/sentinel.conf
redis-sentinel s2/sentinel.conf
redis-sentinel s3/sentinel.conf

        现在三个 sentinel 已经开始运作了。

测试:

        现在手动将 7001 master 主节点停机,测试哨兵是如何进行故障转移:

        现在 master 已经停机了。

        哨兵也很快发现了 7001 停止服务了。

         接着重新选举新的 master,此时是 7002 被选中称为主节点。

        再接着哨兵会广播给其他 slave 节点,重新进行全量同步,这时候的主节点为 7002

        最后,将 7001 标记为 slave,当 7001 重启之后,是一个 slave,并且进行全量同步。

        4.2 RedisTemplate 连接哨兵

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

        1)在 pom 文件中引入 redis 的 starter 依赖:

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

        2)然后在配置文件 application.yml 中指定 sentinel 相关信息:

spring:data:redis:password: ******host: 8.152.162.159lettuce:pool:max-active: 10max-idle: 10min-idle: 1time-between-eviction-runs: 10sdatabase: 0port: 6379sentinel:master: mymasternodes:- 8.152.162.159:27001- 8.152.162.159:27002- 8.152.162.159:27003
logging:level:io.lettuce.core: debugpattern:dateformat: MM-dd HH:mm:SSS

        3)配置主从读写分离

    @Beanpublic LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);}

        这里的 ReadFrom 是配置 Redis 的读取策略,是一个枚举,包括下面选择:

        MASTER:从主节点读取

        MASTER_PREFERRED:优先从 master 节点读取,master 不可用才读取 replica

        REPLICA:从 slave 节点读取

        RREPLICA_PREFERRED:优先从 slave 节点读取,所有的 slave 都不可用才读取 master。

做一个测试:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class Text {@AutowiredStringRedisTemplate stringRedisTemplate;@GetMapping("get/{key}")public String getKey(@PathVariable String key){return stringRedisTemplate.opsForValue().get(key);}@GetMapping("set/{key}/{value}")public String setKey(@PathVariable String key,@PathVariable String value){stringRedisTemplate.opsForValue().set(key,value);return "OK";}}

        当发送请求之前,会尝试与 sentinel 节点建立连接,再由哨兵节点去订阅 redis 主从节点,主要是从 slave 节点来获取数据。

        5.0 Redis 分片集群

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

        1)海量数据存储问题。

        2)高并发写的问题。

        使用分片集群可以解决上述问题,分片集群特征:

        1)集群中有多个 master,每个 master 保存不同数据。

        2)每个 master 都可以有多个 salve 节点

        3)master 之间通过 ping 监测彼此健康状态。

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

        5.1 搭建分片集群

         redis.conf 配置文件如下:

        不同节点的端口号需要进行调整,日志存放的位置也要进行调整。

        接着创建每个节点之间在集群中的关系:

命令说明:

        redis-cli --cluster 或者 ./redis-trib.rb:代表集群操作命令。

        create:代表创建集群。

        --replicas 1 或者 --cluster-replicas 1:指定集群中每个 master 的副本个数为 1,此时节点总数÷(replicas + 1)得到的就是 master 的数量。因此节点列表中的前 n 个就是 master,其他节点都是 slave 节点,随机分配得到不同的 master 。

查看集群状态:

redis-cli -p 7001 cluster nodes

 

        5.2 散列插槽

        Redis 的散列插槽(Hash Slots)是 Redis 集群模式下用于数据分布和路由的一种机制。Redis 集群将数据分散到多个节点上,以实现高可用性和可扩展性。

        Redis 集群总共有 16384 个散列槽。每个键在存储时会被映射到这 16384 个槽中的一个。Redis 使用 CRC16 散列算法来计算键的散列值,并通过取模运算将其映射到 0 到 16383 的范围内。例如,slot = CRC16(key) % 16384

        每个 Redis 节点负责一部分散列槽。通过将键映射到散列槽,Redis 可以确定该键应该存储在哪个节点上。在集群中,客户端在执行命令时会根据键的散列槽来确定目标节点。

        5.3 集群伸缩

        Redis 集群支持动态伸缩,允许用户根据需求增加或减少节点。

添加 7004 节点:

给 7004 分配插槽:

 

        5.4 故障转移

        利用 cluster failover 命令可以手动让集群中的某个 master 宕机,切换到执行 cluster failover 命令的这个 slave 节点,实现无感知的数据迁移。

流程如下:

7002 从节点转换为 master 的命令:

        5.5 RedisTemp 访问分片集群

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

        1)引入 redis 的 starter 依赖

        2)配置分片集群地址

        3)配置读写分离

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

相关文章:

Redis 篇-初步了解 Redis 持久化、Redis 主从集群、Redis 哨兵集群、Redis 分片集群

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 分布式缓存概述 2.0 Redis 持久化 2.1 RDB 持久化 2.1.1 RDB 的 fork 原理 2.2 AOF 持久化 2.3 RDB 与 AOF 之间的区别 3.0 Redis 主从集群 3.1 搭建主从集群 3.2…...

算法基础-二分查找

左闭右闭 [ left&#xff0c;right ] [1,1]可以 while( left < right ) if( a[mid] > target ) right mid - 1 else if( a[mid] < target ) left mid 1 左闭右开 [ left&#xff0c;right ) …...

LeetCode:1184. 公交站间的距离 一次遍历数组,复杂度O(n)

1184. 公交站间的距离 today 1184 公交站间的距离 题目描述 环形公交路线上有 n 个站&#xff0c;按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离&#xff0c;distance[i] 表示编号为 i 的车站和编号为 (i 1) % n 的车站之间的距离。 环线上的公交车都…...

牛客周赛 Round 60(A,B,C,D,E,F)

比赛链接 官方题解 这场基本都是数学题&#xff0c;官方题解讲的还不错&#xff0c;F能听懂的话其实不难。E是一个球盒模型的组合问题&#xff0c;F是化简递推式&#xff0c;成环时的解决方法很不错。 A 困难数学题 思路&#xff1a; 一个数异或两次结果为 0 0 0&#xff…...

vueCropper裁剪图片(不模糊)以及记录使用方法

需求&#xff1a;上传限定比例的图片。前端框架是vue3 element plus。 问题&#xff1a;使用vueCropper后比例固定。但是上传后的图片很模糊 vueCropper官网 解决办法 vueCropper中有一个full和high两个参数&#xff0c;记得开启 const options: any reactive({img: , // 原…...

【HTML】HTML页面和常见标签

文章目录 什么是前端HTML 页面编写如何快速生成代码框架常见标签注释标签标题标签段落标签换行标签格式化标签 什么是前端 Web 前端&#xff0c;用来直接给以用户呈现的一个一个的网页。一个软件通常是由 后端前端 完成的 后端&#xff1a;通过 Java/C等语言&#xff0c;完成相…...

鸿蒙 ArkUI组件二

ArkUI组件&#xff08;续&#xff09; 文本组件 在HarmonyOS中&#xff0c;Text/Span组件是文本控件中的一个关键部分。Text控件可以用来显示文本内容&#xff0c;而Span只能作为Text组件的子组件显示文本内容。 Text/Span组件的用法非常简单和直观。我们可以通过Text组件来显…...

PHP 实现 redis 分布式锁

分布式锁 如果是强一致性保证&#xff0c;在获取锁或者失败后引入数据库存储扫表、mq 等方式进行补偿 如果可以容忍少量异常就不需要考虑了 像这里的代码&#xff0c;没吃建立一个链接铺货&#xff0c;性能损耗时间延迟也是很大的&#xff0c;也可在一块代码中进行服务&…...

vue3 自定义el-tree树形结构样式

这里样式设置主要用到了 windcss 实现效果 模拟数据 这里也可以用模拟的数据,下面用的是后端请求的真实数据 [{"id": 5,"rule_id": 0,"status": 1,"create_time": "2019-08-11 13:36:09","update_time": "…...

【网络安全】分享4个高危业务逻辑漏洞

未经许可,不得转载。 文章目录 正文逻辑漏洞1逻辑漏洞2逻辑漏洞3逻辑漏洞4其它正文 该目标程序是一家提供浏览器服务的公司,其核心功能是网页抓取和多账户登录操作,类似于浏览器中的隐身模式,但更加强大和高效。通过该平台,用户可以轻松管理并同时运行数百个隐身浏览器实…...

【装机教程】Visual Studio Community 2019离线安装

Visual Studio 2019离线安装 由于现在 官网只支持在线安装最新版的Visual Studio 2022&#xff0c;因此 Visual Studio Community 2019需要离线安装。 下载离线安装镜像&#xff0c;并解压。点击vs_setup.exe运行。 选择安装位置&#xff0c;四处位置需要确定。 选择语言包&…...

NumPy 线性代数

NumPy 线性代数 NumPy 是 Python 中用于科学计算的核心库之一&#xff0c;它提供了一个强大的数学函数库&#xff0c;特别是在处理大型多维数组和矩阵时表现出色。线性代数是 NumPy 的一个重要组成部分&#xff0c;它包含了大量的函数和运算符&#xff0c;用于执行矩阵和向量的…...

家装材料之水泥,最容易被忽视的基础材料!

由于水泥在装修中扮演辅料的角色&#xff0c;很多业主往往会忽视它们的质量。事实上&#xff0c;装修无小事&#xff0c;不能抱有抓大放小的态度。      更何况水泥是装修工程的基础材料&#xff0c;在家居装修中&#xff0c;地面、墙面的找平以及瓷砖、大理石的铺贴&#…...

openstack之keystone介绍

功能 keystone在OpenStack中负责&#xff1a; 管理&#xff1a;用户、租户和权限&#xff1b; 认证&#xff1a;组件相互访问的身份认证&#xff1b; 鉴权&#xff1a;提供 RBAC&#xff08;Role Based Access Control&#xff09; 权限体系&#xff1b; 服务注册与发现&#…...

【图像拼接】基于SIFT/SURF特征算法的图像拼接,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于SIFT/SURF特征算法的图像拼接&#xff0c;用matlab实现。 一、案例背景和算法介…...

《微信小程序实战(2) · 组件封装》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

LaTex2024 下载安装运行HelloWorld—全流程笔记

LaTex安装教程&#x1f680; 这是读博之后写的第一篇文章&#xff0c;来到新课题组之后&#xff0c;新课题组主要是用Latex&#xff0c;在之前的课题组&#xff0c;还是比较常用world&#xff0c;所以就研究了一下Latex的下载和安装&#xff0c;虽然网上已经有了不少教程&#…...

Golang | Leetcode Golang题解之第404题左叶子之和

题目&#xff1a; 题解&#xff1a; func isLeafNode(node *TreeNode) bool {return node.Left nil && node.Right nil }func sumOfLeftLeaves(root *TreeNode) (ans int) {if root nil {return}q : []*TreeNode{root}for len(q) > 0 {node : q[0]q q[1:]if no…...

基于yolov8+lprnet的中文车牌识别系统python源码+pytorch模型+精美GUI界面

【算法介绍】 基于YOLOv8和LPRNet的中文车牌识别系统是一种高效且准确的解决方案&#xff0c;结合了目标检测与字符识别的先进技术。YOLOv8作为最新的实时目标检测算法&#xff0c;以其高速度和精确度著称&#xff0c;能够迅速在图像或视频中定位车牌位置。LPRNet则是一种专为…...

电信创维光猫DT741超级密码

正常的D740系是创维系列光猫如&#xff1a;SK-D740 之类的超密获取办法-光猫/adsl/cable无线一体机-恩山无线论坛 但是我这个固件是DT741v1.0 我只能说很S -B&#xff0c;这个版本如果是1.02那就可以很轻松的去用通用办法解决&#xff0c;但是呢&#xff01;还有办法就是用最传…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...