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

Redis--高可用(主从复制、哨兵模式、分片集群)

高可用(主从复制、哨兵模式、分片集群)

  • 高可用性
    • Redis如何实现高可用架构?
    • 主从复制
      • 原理
      • 1. 全量同步
      • 2. 命令传播
      • 3. 增量同步
    • Redis Sentinel(哨兵模式)
      • 为什么要有哨兵模式?
      • 哨兵机制是如何工作的?
        • 故障检测
        • 由哪个哨兵进行主从故障转移?
        • 主从故障转移的过程是怎样的?
      • 集群脑裂导致数据丢失怎么办?
        • 什么是脑裂?
        • 解决方案
    • Redis Cluster(分片集群)
      • 为什么需要Redis Cluster?
      • Redis Cluster 是如何分⽚的?
      • 为什么 Redis Cluster 的哈希槽是 16384 个?
      • Redis Cluster中的节点是怎么进行通信的?
        • Gossip 协议
        • 节点间的数据交换

高可用性

Redis如何实现高可用架构?

Redis 官方提供了三种分布式部署模式:

  • 主从复制:通过 slaveof 命令可以让任意的节点成为对应的节点的从节点,主节点通过主从复制机制向从主节点同步数据。其中,主节点提供读写功能,而从节点只提供读功能。当主节点出现故障时,需要手动进行主从切换完成故障转移。
  • Sentinel 哨兵模式:哨兵模式是主从的增强版本,它在主从模式的基础上添加了哨兵节点,哨兵节点通过心跳监控节点健康状态,并在主节点出现故障后,自动通过投票机制选举出新的主节点并完成故障转移。不过哨兵本身也需要做保证高可用,因此一般也会同时部署多个哨兵节点组成哨兵集群。
  • Cluster 集群模式:Redis Cluster 一般也叫分片集群,它是 Redis 提供的一个去中心化的集群部署方案。它将全部数据划分为 16394 个哈希槽,由集群中的每个节点负责其中的一部分槽位,使用时 Key 将通过哈希取模并最终指派到某个特定的槽位。在集群中,不同的 Redis 节点间通过 Gossip 协议与其他节点保持通信,每个主节点都将可以具备多个从节点,从节点不提供服务,当主节点出现故障时将会自动投票选举出新的主节点,并且完成故障转移。

此外,在 Redis Cluster 之前,也有一些基于中间代理路由或客户端路由的 Redis 的解决方案,比如 Jedis 自带的 ShardedJedis,或者推特的 Twemproxy。

主从复制

当 Redis 的访问量以及数据量随着随着业务规模一起扩大,单机部署的一些问题就逐渐体现出来,比如:

  • 服务器一旦宕机,所有 Redis 服务都不可用。
  • 读写请求全打到单个 Redis 实例上,会遇到性能瓶颈。

为了解决这些问题,Redis 中提供了主从复制(replication)的机制。简单的来说,当我们有多个 Redis 实例时,它们会被划分为两类节点

  • Master 主节点:负责处理客户端的读写请求,以及数据的修改操作。
  • Slave 从节点:通过复制主节点的数据,提供备份和读取服务。

img

也就是说,所有的数据修改只在主服务器上进行,然后将最新的数据同步给从服务器,这样就使得主从服务器的数据是一致的。

原理

当从节点初次连接到主节点,或者掉线重连后进度落后较多时会进行一次全量数据同步。此时,主节点会生成 RDB 快照并传输给从节点,在此期间,主节点接受到的增量命令将会先写入 replication_buffer 缓冲区,等到从节点加载完 RDB 快照的数据后,再将缓冲区的命令传输给从节点,以次完成初次同步。

当从节点掉线重连后,如果进度落后的不多,将会进行增量同步。主节点内部维护了一个环形的固定大小的 repl_backlog_buffer 缓冲区,它用于记录最近传播的命令。其中,主节点和从节点会分别在该缓冲区维护一个 offset ,用于表示自己的写进度和读进度。当从节点掉线重连后,将会检查主节点和从节点 offset 之差是否小于缓冲区大小,如果确实小于,说明从节点同步进度落后不多,则主节点将该缓冲区中的两 offset 之间的增量命令发送给从节点,完成增量同步。

当主从节点完成初次同步后,将会建立长连接进行命令传播。简单的来说,就是每当主节点执行一条命令,它就会写入 replication_buffer 缓冲区,随后再将缓冲区的命令通过节点间的长连接发送给对应的从节点。

1. 全量同步

一般来说,当两个节点第一次建立主从关系的时候,一定会触发一次全量同步。整个过程大致分为四步:

  1. 从节点向主节点发送 psync 请求获取 runID 和 offset;
  2. 主节点返回自己的 runID 与该从节点的 offset;
  3. 主节点生成 RDB 文件,并传输给从节点,从节点加载文件后获取全量数据。
  4. 主节点确认从节点加载完 RDB 文件后,将这期间缓存的增量命令发送给从节点,从节点加载完毕后结束第一次同步。

图片

1.获取 runID 与 offset

当我们对一个 Redis 实例使用 replicaof 让指定从节点与主节点构成主从关系时,从节点将会根据你指定的 host 和端口号请求对应的服务实例,并向主节点发送 psync {runID} {offset} 请求。

其中,runID 是主节点启动时生成的标识 ID,而 offset 则表示当前从节点从主节点复制数据的偏移量,也就是复制进度。最开始的时候,由于是第一次同步,因此从节点并不知道主节点的 runID,因此 runID 为 ?,由于也还没有复制过数据,因此 offset 为 -1。

当主节点响应请求时,将会返回主节点自己的 runID 和当前从节点的复制进度 offset。并且因为是首次同步,因此主节点会返回 FULLRESYNC 响应,表示从节点需要进行全量同步

2.加载 RDB 数据

在前文 Redis 的持久化部分,我们提到过,Redis 恢复数据或者进行主从同步的时候是通过 RDB 文件完成的,实际上指的就是全量同步。

在从节点接受了响应以后,主节点将会执行 bgsave 去生成一个 RDB 文件——这个流程与正常生成 RDB 文件一致——并发送给从节点,从节点接受后,由于是全量同步,因此会先清空自己的已有数据,然后再加载 RDB 文件中的数据

此时,从节点已经同步过来了主节点的大部分数据,不过由于 RDB 实际上只是一个快照,因此在生成 RDB 文件期间主节点的增量数据实际上还没有被从节点获取

  1. 获取增量数据

在主节点生成 RDB 文件期间,由于 RDB 文件是通过子进程异步生成的,因此在这个过程中主节点仍然还在正常的处理请求,这部分的增量命令将会写入 replication buffer 缓冲区

当从节点加载完 RDB 中的数据后,将会向主节点发送确认消息,此时主节点会再将缓冲区中的命令发送给从节点,从节点执行完这部分增量命令后,数据即与主节点基本一致,则全量同步完成。

不过,由于主从的更新已有延迟,因此无论如何数据是很难保证完全一致的,不过这就是后面命令的正常传播和增量同步的事情了。

2. 命令传播

当主从之间根据 psync 请求完成第一次全量或增量同步后,就会保持长连接,此后,将会通过长连接进行命令传播。

在这个过程中,主节点将会在每次执行完一个命令后,分别写两个缓冲区:

  • replication_buffer:主从复制缓冲区,主节点每拥有一个从节点,就会有一个对应的缓冲区,要传播给从节点的命令会先写入该缓冲区,随后在通过长连接发送给从节点。
  • repl_backlog_buffer:最近传播命令缓冲区,一个主节点只有一个,用于记录主节点最近传播出去的命令,主节点和全部从节点都会分别在上面维护一个 offset,用于表示自己已经写入或读取的命令进度。

在这里插入图片描述

3. 增量同步

在这里插入图片描述

repl_backlog_buffer 是主节点中一个比较特殊的缓冲区,和每个从节点都有一个 replication_buffer 不同,一个主节点只会有一个 repl_backlog_buffer

repl_backlog_buffer 是一个固定大小的“环形”区域,当主节点写入数据时,它会使用 master_offset 记录自己当前已经写到哪个字节,对应的,从节点也会有一个 slave_offset表示从节点已经读到的哪个字节。当主节点写的数据超过缓冲区大小后,它将会覆盖最早写过的内容。

在这里插入图片描述

因此,当从节点要与主节点进行同步时,仅需要在 psync 请求时给出自己的 slave_offset 即可,主节点将计算其与 master_offset 的差值:

  • 如果差值大于 repl_backlog_buffer 的大小,说明两者数据已经差了很多,那么需要重新进行全量同步。
  • 如果查找小于 repl_backlog_buffer 的大小,说明数据差还在容许范围内,则主节点将返回 CONTINUE 响应,让从节点准备进行增量同步,并把 repl_backlog_buffer 中的差值部分写入 replication_buffer 并发送给从节点,让从节点把同步进度追上来。

简单的来说,如果从节点最后一次读取的命令可以在上面找到,那么说明从节点的数据没有落后太多,因此可以增量同步,否则就需要进行全量同步。

当主从链接断开后,从节点会重新发送 psync 请求向主节点要求同步数据,在 2.8 之前总是会使用全量同步,而在 2.8 及以后的版本,将会使用增量同步。

综上,我们不难意识到,如果你的网络不太稳定,那么最好把 repl_backlog_buffer 调大一些,这样可以尽可能的避免从节点掉线重连后需要频繁的进行全量同步。

Redis Sentinel(哨兵模式)

为什么要有哨兵模式?

Redis 默认提供的主从模式不具备故障转移的能力,当主节点宕机后,需要用户手动的进行主从切换,在这段时间内整个集群实际上处于不可用的状态。为了解决这个问题,Redis 在 2.8 及以上版本提供了哨兵模式。

哨兵机制是如何工作的?

简单的来说,哨兵模式与普通的主从复制相比,新增了一类哨兵节点,它是一个特殊的 Redis 进程,哨兵节点本身不对外提供任何读写服务,它的作用是:

  • 监控与通知:与所有节点保持心跳,监控它们的监控状况。
  • 自动故障转移:当主节点故障后,自动选举新的主节点并完成主从切换,实现自动故障转移。
  • 通知告警:用户可以通过哨兵节点的 API 订阅消息,从而在节点状态异常时获得通知,又或者在完成主从切换后得知新的主节点地址。
故障检测

当哨兵节点启动以后,每隔 1 秒,它将会向集群中的主从节点与其他的哨兵节点发送 ping 请求,以确认对方的健康状况。如果在指定的超时时间 down-after-millisenconds 内没有收到响应,那么它就会认为没有响应的那个节点已经掉线,将其标记为 sdown。这种这种下线状态称为“主观下线”。

哨兵监控主从节点

如果下线的是从节点或者其他哨兵节点,那么直到其重新上线为止,哨兵都会认为其已经不可用。如果下线的是主节点,那么哨兵为了防止因为网络波动导致的误判,会向其他的哨兵节点发送 sentinel is-master-down-by-addr 请求,确认对方是否也认定该节点下线。当整个哨兵集群中有足够数量的哨兵(该值通过配置文件中的 quorum 进行配置)节点确认主节点主观下线,那么主节点就会被认定为“客观下线”,并标记为 odown

img

由哪个哨兵进行主从故障转移?

在一切开始前,哨兵集群会从所有的哨兵节点中挑选一个领头哨兵,领头哨兵将用来代表其他节点完成重新选主和主从切换的任务

Redis 基于 Raft 分布式共识算法来实现领头哨兵的选举,这个过程大致如下:

  1. 确认主节点客观下线的哨兵将成为候选者,它先投自己一票,然后邀请其他哨兵向自己投票;
  2. 其他哨兵如果尚未投票,则会将把赞同票投给邀请它投票的候选哨兵,否则就不投票;
  3. 所有的候选哨兵都统计自己的得票数,当得票数满足下述两条件时,该节点当选为领头哨兵:
    • 当得票数超过哨兵集群中节点数量的一半,即 n/2+1
    • 得票数且超过了认定节点客观下线所要求的哨兵数量(即配置文件中的 quorum 配置);
  4. 如果在规定时间内或投票结束后都没有选出领头哨兵,则再进行一轮投票,直到选出领头哨兵为止。

由于选举机制需要保证有一个节点可以拿到超半数票,因此为了保证哨兵集群的高可用,一个最小的哨兵集群至少需要有三个节点,这样当任意一个节点下线后,哨兵集群仍然可以正常选举出领头哨兵去做故障转移。

此外,我们可以注意到,由于故障检测只受 quorum 影响,而不受哨兵数量的影响。因此,当 quorum 被设置了一个过小的值 —— 比如为低于 n/2+1——的时候,可能会出现虽然哨兵确认节点客观下线了,但是却由于在线的哨兵数量不足以选举出领头哨兵,最终无法进行故障转移尴尬局面。

比如,我们有一个由五个节点组成的哨兵集群,当我们把 quorum 设置为 2 时,如果挂掉了三个哨兵节点,此时哨兵集群可以确认主节点已经客观下线,但是由于哨兵节点数量不足,无法选出领头哨兵,所以即使发现了问题也无法完成故障转移。

主从故障转移的过程是怎样的?

在哨兵集群中通过投票的方式,选举出了哨兵 leader 后,就可以进行主从故障转移的过程了,如下图:

img

主从故障转移操作包含以下四个步骤:

  • 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点。
  • 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
  • 第三步:将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
  • 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;

选举出领头哨兵后,它将从被自己监控的所有从节点中,先排除下述节点:

  • 排除所有已经掉线的从节点;
  • 排除五秒内没有响应哨兵的 INFO 命令的从节点(当出现主节点客观下线后,哨兵对节点的 INFO 命令已经变为一秒请求一次)。
  • 排除与主节点断连超过 down-after-milliseconds * 10 毫秒的从节点(down-after-milliseconds即为主节点的超时时间)。

然后剩下的节点都有资格参与选举,此时哨兵再根据以下条件选择出优先级最高的节点作为新的主节点:

  1. 优先级配置:先尝试根据 slave-priority 配置,选出一个优先级最高的节点;
  2. 数据同步进度:如果所有节点优先级配置均相同,则从中挑选出一个复制进度最高的(即主从复制中提到的从节点的 offset);
  3. 启动时间:如果所有的节点复制进度均相同,则挑选一个 runID 最小的节点(即最新的从节点)。

当选出一个新的主节点后,领头哨兵将会发送 slave no one 命令将该节点真正的升级为主节点,然后向其他的从节点发送 slaveof 命令让它们成为这个新主节点的从节点,至此,故障转移的就完成了。

需要注意的是,在这个过程中,由于主从复制延迟,当主从切换后,旧的主节点尚未同步从节点的数据可能就会丢失。

集群脑裂导致数据丢失怎么办?

什么是脑裂?

在正常情况下,当发生主从切换时,客户端将会从哨兵收到主节点切换的通知,然后与旧的主节点断开连接,并连接到新的主节点。不过,如果有的客户端与哨兵也断开了连接,那么它将无法意识到主节点已经切换,并且还是连接到旧的主节点。此时,整个 Redis 集群实际上同时有两个主节点在工作,这就是脑裂问题。

解决方案

我们可以通过调整两个参数防止这种情况出现:

  • min-replicas-to-write:主节点必须要有至少 x 个从节点连接,如果小于这个数,主节点会禁止写数据。
  • min-replicas-max-lag:主从数据复制和同步的延迟不能超过 x 秒,如果超过,主节点会禁止写数据。

分别给它们设置一定的阈值,假设为 N 和 T。

这两个配置项组合后的要求是,主库连接的从库中至少有 N 个从库,和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主库就不会再接收客户端的写请求了。

如此一来,当主节点掉线时,我们就可以让客户端能够及时发现问题,然后重新向哨兵确认当前的主节点。在最大限度的避免的数据不一致问题后,当旧的主节点节点重新上线,就可以放心的让它去当从节点,而不必担心数据丢失的问题。

不过,有得必有失,为了避免主节点“罢工”,min-replicas-to-write 调的越高,从节点就需要部署的越多,min-replicas-max-lag 调的越小,那主从节点间的网络就要越稳定。因此,实际使用时,还是需要结合自己的业务需求来衡量要采用什么样的配置。

Redis Cluster(分片集群)

为什么需要Redis Cluster?

高并发场景下,使⽤ Redis 主要会遇到的两个问题:

  1. 缓存的数据量太⼤ :实际缓存的数据量可以达到⼏⼗ G,甚至是成百G;
  2. 并发量要求太大:虽然 Redis 号称单机可以⽀持 10w 并发,

主从复制和 Redis Sentinel 这两种⽅案本质都是通过增加主库(master)的副本(slave)数量的⽅式来提⾼ Redis 服务的整体可⽤性和读吞吐量,都不⽀持横向扩展来缓解写压⼒以及解决缓存数据量过⼤的问题。

Redis 切⽚集群 就是部署多台 Redis 主节点(master),这些节点之间平等,并没有主从之说,同时对外提供读写服务。缓存的数据库相对均匀地分布在这些 Redis 实例上,客户端的请求通过路由规则转发到⽬标 master 上。

总结⼀下 Redis Cluster 的主要优势:

  • 可以横向扩展缓解写压⼒和存储压⼒,⽀持动态扩容和缩容;
  • 具备主从复制、故障转移(内置了 Sentinel 机制,⽆需单独部署 Sentinel 集群)等开箱即⽤的功能。

Redis Cluster 是如何分⽚的?

Redis Cluster 并没有使⽤⼀致性哈希,采⽤的是 哈希槽分区 ,每⼀个键值对都属于⼀个 hash slot(哈希槽) 。

Redis Cluster 通常有 16384 个哈希槽 ,要计算给定 key 应该分布到哪个哈希槽中,我们只需要先对每个 key 计算 CRC-16(XMODEM) 校验码,然后再对这个校验码对 16384(哈希槽的总数) 取模,得到的值即是 key 对应的哈希槽。

在这里插入图片描述

为什么 Redis Cluster 的哈希槽是 16384 个?

CRC16 算法产⽣的校验码有 16 位,理论上可以产⽣ 65536(2^16,0 ~ 65535)个值。为什么 Redis Cluster 的哈希槽偏偏选择的是 16384(2^14)个呢?

Redis Cluster 的哈希槽的数量选择 16384 ⽽不是 65536 的主要原因:

  • 哈希槽太⼤会导致⼼跳包太⼤,消耗太多带宽;
  • 哈希槽总数越少,对存储哈希槽信息的 bitmap 压缩效果越好;
  • Redis Cluster 的主节点通常不会扩展太多,16384 个哈希槽已经⾜够⽤了。

Redis Cluster中的节点是怎么进行通信的?

由于 Redis 的集群是去中心化的,这意味着集群中实际上没有一个类似注册中心一样的角色,所以每个节点都需要通过 Gossip 协议与其他节点保持通信,这个通信端口通常是默认的服务端口加 10000,比如默认的服务端口是 6379,那么集群通信端口就是 16379。

Gossip 协议

尽管我们常说节点之间会“保持通信”,但实际上,Redis 集群并不要求每个节点都必须一直与其他所有节点同时保持连接,这要归功于 Redis 使用的 Gossip 协议,Gossip 可以译为流言或者八卦,这很好的反映了这个协议的特点。

举个例子,假如现在有一个新节点 D 要加入:

  1. C 邀请 D 加入集群,现在 C 知道了 D 的存在;
  2. B 与 C 进行 ping & pong,通过 C 得知 D 加入了集群,现在 B 知道了 D 的存在;
  3. A 与 B 进行 ping & pong,通过 B 得知 D 加入了集群,现在 A 也知道了 D 的存在。

可见,当有一个新的事件发生后,它会逐步的在集群中传播,即使中间有节点挂掉,只要消息的传播路径没有完全被切断,那么其他节点也会最终会被通知到,比如新节点的加入,或者节点下线……等。

当然,实际上 Redis 也不是完全依赖这种方式传播消息,对于一些时效性要求比较强的消息 —— 比如节点下线或者主从切换 —— 则会直接通过广播的方式进行通知

节点间的数据交换

组群后,每个 Redis 实例都会在本地维护一个集群实例列表,然后定期从中挑选节点发送 ping 消息,而另一个节点收到了之后会回以 pong 响应。两个节点通过这个步骤来确认彼此健康状态,并传递其其他节点的下线状态,以及交换彼此持有的槽位信息等数据。

需要注意的是,ping 的目标并不是完全随机的,它遵循两个规则:

  • 默认情况下,Redis 实例每隔一秒都会从已知的集群节点中挑选出 5 个实例,然后再从中挑选出一个最久没有 ping 过的节点发送消息。
  • 每隔一段时间,Redis 将会检查其他节点对当前节点请求的响应情况,如果发现有节点最近一次响应距今已接近超时时间 cluster-node-timeout,那么它会立刻向该节点发起 ping 请求,若再无响应则会标记为主观下线。

相关文章:

Redis--高可用(主从复制、哨兵模式、分片集群)

高可用(主从复制、哨兵模式、分片集群) 高可用性Redis如何实现高可用架构?主从复制原理1. 全量同步2. 命令传播3. 增量同步 Redis Sentinel(哨兵模式)为什么要有哨兵模式?哨兵机制是如何工作的?…...

框架(Mybatis配置日志)

mybatis配置日志输出 先导入日志依赖 <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency> 编写log4j.properties配置文件 # Root logger option log4j.rootLogge…...

人工智能-Python上下文管理器-with

概念 Python提供了 with 语句的这种写法&#xff0c;既简单又安全&#xff0c;并且 with 语句执行完成以后自动调用关闭文件操作&#xff0c;即使出现异常也会自动调用关闭文件操作&#xff1b;其效果等价于try-except-finally with 拥有以下两个魔术方法 __enter__() 上文管理…...

每天40分玩转Django:Django类视图

Django类视图 一、知识要点概览表 类别知识点掌握程度要求基础视图View、TemplateView、RedirectView深入理解通用显示视图ListView、DetailView熟练应用通用编辑视图CreateView、UpdateView、DeleteView熟练应用Mixin机制ContextMixin、LoginRequiredMixin理解原理视图配置U…...

自动化测试之Pytest框架(万字详解)

Pytest测试框架 一、前言二、安装2.1 命令行安装2.2 验证安装 三、pytest设计测试用例注意点3.1 命名规范3.2 断言清晰3.3 fixture3.4 参数化设置3.5 测试隔离3.6 异常处理3.7 跳过或者预期失败3.8 mocking3.9 标记测试 四、以案例初入pytest4.1 第一个pytest测试4.2 多个测试分…...

基于51单片机(STC32G12K128)和8X8彩色点阵屏(WS2812B驱动)的小游戏《贪吃蛇》

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、定时器02、矩阵按键模块3、8X8彩色点阵屏 四、主函数总结 系列文章目录 前言 《贪吃蛇》&#xff0c;一款经典的、怀旧的小游戏&#xff0c;单片机入门必写程序。 以《贪吃蛇》为载体&#xff0c;熟悉各种屏幕…...

2011-2020年各省粗离婚率数据

2011-2020年各省粗离婚率数据 1、时间&#xff1a;2011-2020年 2、来源&#xff1a;国家统计局 3、指标&#xff1a;地区、年份、粗离婚率 4、范围&#xff1a;31省 5、指标解释&#xff1a;粗离婚率指某地区当年离婚对数占该地区年平均人口的比重。计算公式为&#xff1a…...

C++高级编程技巧:模板元编程与性能优化实践

C高级编程技巧&#xff1a;模板元编程与性能优化实践 在C编程的世界里&#xff0c;模板元编程&#xff08;Template Metaprogramming&#xff09;是一项强大的技术&#xff0c;它允许程序员在编译时而非运行时进行计算和类型操作。这项技术的核心在于C模板系统&#xff0c;它…...

Mac 版本向日葵退出登录账号

找遍整个软件&#xff0c;Mac 版本的向日葵甚至逆天到没有提供退出登录的功能… 随后我发现可以直接删除向日葵的配置文件达到退出登录的效果&#xff0c;具体操作如下&#xff1a; cd /etc # 确认存在 orayconfig.conf 文件 ls orayconfig.conf  # 删除 sudo rm -f oray…...

SOLIDWORKS Composer在产品设计、制造与销售中的应用

SOLIDWORKS Composer是一款专为技术团队设计的高效沟通工具&#xff0c;广泛应用于产品设计、制造、销售及售后等领域。它能从复杂的CAD数据中提取关键信息&#xff0c;轻松转化为高质量的产品文档、交互式3D动画及说明视频&#xff0c;显著提升产品沟通效率。 Composer擅长制…...

Win11+WLS Ubuntu 鸿蒙开发环境搭建(一)

参考文章 Windows11安装linux子系统 WSL子系统迁移、备份与导入全攻略 如何扩展 WSL 2 虚拟硬盘的大小 Win10安装的WSL子系统占用磁盘空间过大如何释放 《Ubuntu — 调整文件系统大小命令resize2fs》 penHarmony南向开发笔记&#xff08;一&#xff09;开发环境搭建 一&a…...

[CSAW/网络安全] Git泄露+命令执行 攻防世界 mfw 解题详析

Home界面&#xff1a; Home界面翻译如下&#xff1a; 欢迎访问我的网站&#xff01; 我自己从头开始写的&#xff01; 您可以使用上面的链接浏览页面&#xff01; About界面&#xff1a; 观察到Git&#xff0c;联想Git泄露 Git泄露 Git是一个非常流行的开源分布式版本控制系…...

MySQL 锁那些事

Q1 : MySQL有哪些锁,功能是什么,如何项目中使用?Q2 : 行锁是如何实现的?什么情况下会使用行锁?Q3 : 四种事务隔离形式的行锁有什么不一样?读未提交读提交可重复读串行 Q4 : MySQL 的读写都是怎样加锁的?Q5 : 需要注意什么? Q1 : MySQL有哪些锁,功能是什么,如何项目中使用…...

Linux中常用的基本指令和一些配套的周边知识详解

目录 一些基本指令 一些常用指令 注&#xff1a;配套的周边知识是直接跟在指令的讲解后面的。 补充&#xff1a;(重要) 如何看待这么多指令&#xff1f;&#xff1f;&#xff1f;记不住怎么办&#xff1f;&#xff1f;&#xff1f; 首先&#xff0c;指令不用刻意去记&#xf…...

深入理解Java中的Set集合:特性、用法与常见操作指南

一、HashSet集合 1.HashSet集合的特点 2.HashSet常用方法 ①&#xff1a;add(Object o)&#xff1a;向Set集合中添加元素&#xff0c;不允许添加重复数据。 ②&#xff1a;size()&#xff1a;返回Set集合中的元素个数 ③.remove(Object o)&#xff1a; 删除Set集合中的obj对…...

Oracle 使用 sql profile 固定执行计划

测试使用 sql profile 固定执行计划&#xff1a; Oracle 10g之前有outlines,10g之后 sql profile 。如果针对非绑定变量的sql,outlines则效果不佳&#xff0c;不建议使用 。 1、准备测试用表 SQL> create table zzh_ob as select * from dba_objects; SQL> create inde…...

数字电路期末复习

*前言&#xff1a;*写的东西不太全面&#xff0c;更多的是一个复习大纲&#xff0c;让你发现自己有哪些不懂的问题&#xff08;不懂的地方就去翻书或者问AI&#xff09;&#xff0c;如果能够解决提出的所有问题&#xff0c;那么过期末考一定不是问题。 这里写目录标题 数制和码…...

正则表达式 - 使用总结

正则表达式 - 使用总结 正则表达式(Regular Expression,简称Regex)是一种强大的文本处理工具,它允许我们通过特定的模式(pattern)来搜索、匹配和操作字符串。在编程、数据分析和文本处理等领域,正则表达式发挥着非常重要的作用。本文将总结正则表达式的基本概念、使用方…...

通过Xshell远程连接wsl2

目录 一、WSL网络原理 二、 下载XShell 三、Ubuntu里配置ssh 1.查看是否已经安装SSH 2.安装SSH 3.修改SSH配置 4.重启ssh 5.查看ip 四、在Xshell中链接电脑 五、设置端口转发 1.设置主机端口映射到wsl2的端口 六、防火墙设置开放8989端口 方式一(推荐): 方式二:…...

【ubuntu】安装OpenSSH服务器

参考:https://blog.csdn.net/fanjufei123456/article/details/139264814 要在Ubuntu上使用SSH连接&#xff0c;需要确保系统上安装并运行了SSH服务器。SSH服务器负责接受来自其他计算机的SSH连接请求&#xff0c;并提供对目标系统的访问权限。 在Ubuntu上&#xff0c;默认情况…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...