redis-Redis主从,哨兵和集群模式

一,Redis的主从复制

​ 主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。这样做的好处是读写分离,性能扩展,容灾快速恢复。

1.1 环境搭建

如果你的redis在不同的服务器上,可以不看同一台服务器上启动多个redis的实现步骤:

将redis的配置文件redis.conf到/myredis文件夹中:

cp redis.conf /myredis/redis.conf

编辑拷贝后的redis.conf文件,查找bing 127.0.0.1配置有没有注释掉,没有的话,自己注释了

vi /myredis/redis.conf

在/myredis文件夹中,新建redis6379.conf,填写以下内容:

include /myredis/redis.conf
pidfile /var/run/redis_6379.pid
daemonize yes
port 6379
logfile "6379.log"
dir ./6379

解释:

  • daemonize yes:daemonize守护线程,默认是NO、daemonize是用来指定redis是否要用守护线程的方式启动,
  • include:表示引入redis.conf的配置。
  • pidfile :使用该配置文件启动后,redis的线程id。
  • port: 使用该配置文件启动后,redis的端口。
  • logfile:使用该配置文件启动后,日志生成文件名称。
  • dir:使用该配置文件启动后,RDB和AOF数据持久化生成的文件路径。

同样的方式在/myredis文件夹中,新建redis6380.conf,填写以下内容:

include /myredis/redis.conf
pidfile /var/run/redis_6380.pid
daemonize yes
port 6380
logfile "6379.log"
dir ./6379

在/myredis文件夹中,新建redis6381.conf,填写以下内容:

include /myredis/redis.conf
pidfile /var/run/redis_6381.pid
daemonize yes
port 6381
logfile "6381.log"
dir ./6381

启动三台redis服务器在/myredis文件夹中,输入如下命令:

redis-server redis6379.conf 
redis-server redis6380.conf 
redis-server redis6381.conf 

查看系统进程,看看三台服务器是否启动:

ps -ef | grep redis

到这就通过生成三个不同的redis.conf文件启动了,三台不同的redis。

配置主从关系

在配置主从关系之前,先查看三台主机运行情况,通过如下命令连接三台主机:

redis-cli -p 端口   

连接成功后,通过如下命令查看当前redis的主从复制的相关信息:

info replication

在这里插入图片描述

可以看出在没有配置,主从关系前,上图中role:master都是主库.

配置主从关系,只需要配置从库不需要主库,也就是说从库只需要认主即可,认主的命令是:

-- 5.0之前命令
slaveof <ip> <port>
-- 5.0之后命令
replicaof <ip> <port>

通过命令的方式,只是在当前链接有效,重启redis后就不行了,如果想要一直生效,可以在对应的配置文件中添加如下内容:

# 5.0之前
slaveof <ip> <port>
# 5.0之后
replicaof <ip> <port> 
replica-read-only yes  

假设在6380和6381上执行命令或者在redis6380.conf和redis6381.conf文件中添加了内容后:

在这里插入图片描述

从上截图可以看到6380和6381的角色变成了slave。

1.2 原理解析

​ 如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC命令给master请求复制数据。master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。

​ 当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

全量复制:

​ 当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。

​ master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

部分复制,断点续传流程图:

​ 如果有很多从节点,为了缓解主从复制风暴(多个从节点同时复制主节点导致主节点压力过大),可以做如下架构,上一个Slave可以是下一个slave的Master,Slave同样可以接收其他 slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风
在这里插入图片描述

二,Redis的哨兵模式

​ 主从复制的好处是读写分离,性能扩展,容灾快速恢复,但是只有一个Master,也只有它能够写数据,当这个Master不能工作时,主从复制的集群就不能工作了,为了解决这个问题,redis引入了哨兵模式。

在这里插入图片描述

​ sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)

2.1 环境搭建

在/myredis目录下新建多个sentinel.conf文件:

vim /myredis/sentinel-26379.conf

添加如下内容:

port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "26379.log"
dir "./26379"
sentinel monitor mymaster 166.66.66.66 6379 2 
  • daemonize yes:daemonize守护线程,默认是NO、daemonize是用来指定redis是否要用守护线程的方式启动,可以查看redis.conf是如何配置的如果是NO,改为yes。
  • pidfile :使用该配置文件启动后,redis的线程id。
  • port: 使用该配置文件启动后,redis的端口。
  • logfile:使用该配置文件启动后,日志生成文件名称。
  • dir:使用该配置文件启动后,RDB和AOF数据持久化生成的文件路径。
  • sentinel monitor:表示当前redis是哨兵、mymaster是随便起的名字,136.66.66.66是监视的Master的ip,6379是监视的Master的port,2代表2位哨兵同意才可以。

启动sentinel哨兵实例

src/redis-sentinel sentinel-26379.conf 

同样的流程,可以自己再配置两个sentinel,端口26380和26381,只需要将上述配置文件名和文件内容里的对应数字都修改即可。

同样可以通过如下命令查看sentinel的info信息

> src/redis-cli -p 26379
127.0.0.1:26379>info replication

​ sentinel集群都启动完毕后,会将哨兵集群的元数据信息写入所有sentinel的配置文件里去(追加在文件的最下面) 我们查看下如下配置文件sentinel-26379.conf,如下所示:

sentinel known-replica mymaster 166.66.66.66 6380 #代表主节点的从节点信息
sentinel known-replica mymaster 166.66.66.66 6381 #代表主节点的从节点信息
sentinel known-sentinel mymaster 166.66.66.66 26380 52d0a5d70c1f9043c56935760f  #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 166.66.66.66 26381 e9f53ebb8e1686438ba8bd5ca6  #代表感知到的其它哨兵节点

​ 当redis主节点如果挂了,哨兵集群会重新选举出新的redis主节点,同时会修改所有sentinel节点配置文件的集群元数据信息,比如6379的redis如果挂了,假设选举出的新主节点是6380,则sentinel文件里的集群元数据信息会变成如下所示:

sentinel known-replica mymaster 166.66.66.66 6381 #代表主节点的从节点信息
sentinel known-sentinel mymaster 166.66.66.66 26380 52d0a5d70c1f9043c56935760f  #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 166.66.66.66 26381 e9f53ebb8e1686438ba8bd5ca6  #代表感知到的其它哨兵节点

同时还会修改sentinel文件里之前配置的mymaster对应的6379端口,改为6380

sentinel monitor mymaster 166.66.66.66 6380 2 

​ 原主机重启后会变为从机,当6379的redis实例再次启动时,哨兵集群根据集群元数据信息就可以将6379端口的redis节点作为从节点加入集群,则sentinel文件里的集群元数据信息会变成如下所示:

sentinel known-replica mymaster 166.66.66.66 6379 #代表主节点的从节点信息
sentinel known-replica mymaster 166.66.66.66 6381 #代表主节点的从节点信息
sentinel known-sentinel mymaster 166.66.66.66 26380 52d0a5d70c1f9043c56935760f  #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 166.66.66.66 26381 e9f53ebb8e1686438ba8bd5ca6  #代表感知到的其它哨兵节点
2.3 原理解析

​ 哨兵的leader选举流程:当一个master服务器被某哨兵视为下线状态后,该哨兵会与其他哨兵协商选出哨兵的leader进行故障转移工作。每个发现master服务器进入下线的哨兵都可以要求其他哨兵选自己成为哨兵的leader,选举是先到先得。同时每个哨兵每次选举都会自增配置纪元(选举周期),每个纪元中只会选择一个哨兵(包含自己)成为leader。如果所有超过一半的哨兵选举某哨兵作为leader,那么之后该哨兵负责进行故障转移操作,从存活的slave中选举出新的master,这个选举过程跟集群的master选举很类似。 哨兵集群只有一个哨兵节点,redis的主从也能正常运行以及选举master,如果master挂了,那唯一的那个哨兵节点就是哨兵leader了,可以正常选举新master。 不过为了高可用一般都推荐至少部署三个哨兵节点。

​ 至于为什么要部署三个哨兵节点:主要是为了满足超过半数的原则又能节约资源,假设有2个哨兵节点,当有一个节点挂了时候,就算另一个节点参加选举,选了自己,也没有超过1不可能成为哨兵leader。假设有4个哨兵节点,当有一个节点挂了时候,还有三个哨兵节点,都选择某一个哨兵有机会超过半数的2的,可以成为哨兵leader,但是这个时候用了4个哨兵节点有点浪费资源。

三,集群模式

​ 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异 常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现 一般,特别是在主从切换的瞬间存在访问瞬断的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持 很高的并发,且单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率。

在这里插入图片描述

redis集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需 要sentinel哨兵∙也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中 心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的 性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。

3.1 环境搭建
3.1.1 准备多台redis

将redis的配置文件redis.conf到/myredis文件夹中:

cp redis.conf /myredis/redis.conf

编辑拷贝后的redis.conf文件,查找bing 127.0.0.1配置有没有注释掉,没有的话,自己注释了

vi /myredis/redis.conf

在/myredis文件夹中,新建redis6379.conf,填写以下内容:

include /myredis/redis.conf
pidfile /var/run/redis_6379.pid
daemonize yes
port 6379
logfile "6379.log"
dir ./6379
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
# 如果要设置密码需要增加如下配置:
#设置redis访问密码
requirepass zyh
# 设置集群节点间访问密码,
masterauth zyh

解释:

  • daemonize yes:daemonize守护线程,默认是NO、daemonize是用来指定redis是否要用守护线程的方式启动,
  • include:表示引入redis.conf的配置。
  • pidfile :使用该配置文件启动后,redis的线程id。
  • port: 使用该配置文件启动后,redis的端口。
  • logfile:使用该配置文件启动后,日志生成文件名称。
  • dir:使用该配置文件启动后,RDB和AOF数据持久化生成的文件路径
  • cluster-enabled yes: 打开集群模式
  • cluster-config-file nodes-6379.conf: 设定节点配置文件名
  • cluster-node-timeout 15000: 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换

同样的流程,可以再新增几个端口6380,6381,6382,6383,6384等等,只需要将上述配置文件名和文件内容里的对应数字都修改即可,在vi命令行模式下使用%s/6379/6380命令替换更快 。

都准备好后,启动redis服务器在/myredis文件夹中,输入如下命令:

redis-server redis6379.conf 
redis-server redis6380.conf 
redis-server redis6381.conf 
redis-server redis6382.conf 
redis-server redis6383.conf 
redis-server redis6384.conf 

查看系统进程,看看服务器是否启动:

ps -ef | grep redis

到这就实现了,在一台服务器中启动多台redis。

3.1.2 构建集群

在前面我们已经启动了6台redis服务,现在我们要将这6台redis组成一个集群,redis5以前的版本集群是依靠ruby脚本redis‐trib.rb实现,这里我们使用的是redis5,可以直接使用 redis-cli命令就可以:

redis-cli --cluster create --cluster-replicas 1 166.66.66.66:6379 166.66.66.66:6380 166.66.66.66:6381 166.66.66.66:6382 166.66.66.66:6383 166.66.66.66:6384               

解析命令:

  • redis-cli --cluster create:表示构建集群。

  • --cluster-replicas 1:集群是由主从节点构成的,--cluster-replicas 1表示每个主从节点中,从节点的个数,例如上面的命令表示,一台主机,一台从机,正好三组主从节点。

  • 166.66.66.66:637*:表示参与构建集群的redis服务器。

验证集群是否构建成功:

连接任意一个客户端:

-- ‐a访问服务端密码,‐c表示集群模式,指定ip地址和端口号
./redis‐cli ‐c ‐h ‐p 

执行如下信息:

-- 查看集群信息
cluster info
-- 查看节点列表
cluster nodes
3.2 原理解析
3.2.1 插槽

​ 一个 Redis 集群包含 16384 个插槽(hash slot),数据库中的每个键都属于这16384个插槽的其中一个,当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不 一致的情况,还需要纠正机制来实现槽位信息的校验调整。

槽位定位算法:Cluster 默认会对 key 值使用 crc16 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位。 HASH_SLOT = CRC16(key) mod 16384

跳转重定位:因为槽位的信息可能会存在客户端与服务器不 一致的情况,当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令同时携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽 位映射表。例如:

166.66.66.66:6879> set name abc
-> Redirected to slot [5798] located at 166.66.66.66:6880 OK
166.66.66.66:6880>
3.2.2 通信

redis cluster节点间采取gossip协议进行通信,gossip协议包含多种消息,包括ping,pong,meet,fail等等。

  • meet:某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通 信;
  • ping:每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过 ping交换元数据(类似自己感知到的集群节点增加和移除,hash slot信息等);
  • pong: 对ping和meet消息的返回,包含自己的状态和其他信息,也可以用于信息广播和更新;
  • fail: 某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了。 gossip协议的优点在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力;缺点在于元数据更新有延时可能导致集群的一些操作会有一些滞后

gossip协议的优点在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上 去更新,有一定的延时,降低了压力;缺点在于元数据更新有延时可能导致集群的一些操作会有一些滞后。

​ 每个节点都有一个专门用于节点间gossip通信的端口,就是自己提供服务的端口号+10000,比如6379,那么用于节点间通信的就是16379端口。 每个节点每隔一段时间都会往另外几个节点发送ping消息,同时其他几点接收到ping消息之后返回pong消息。

网络抖动:真实世界的机房网络往往并不是风平浪静的,它们经常会发生各种各样的小问题。比如网络抖动就是非常常见 的一种现象,突然之间部分连接变得不可访问,然后很快又恢复正常。 为解决这种问题,Redis Cluster 提供了一种选项cluster-node-timeout,表示当某个节点持续 timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换 (数据的重新复制)

3.2.3 Redis集群选举原理分析

当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave,从而存在多个slave竞争成为master节点的过程, 其过程如下:

  • slave发现自己的master变为FAIL
  • 将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息
  • 其他节点收到该信息,只有master会响应,会判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个 epoch只发送一次ack
  • 尝试failover的slave收集master返回的FAILOVER_AUTH_ACK
  • slave收到超过半数master的ack后变成新Master
  • slave广播Pong消息通知其他集群节点

注意:从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待 FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票。延迟计算公式:DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms,SLAVE_RANK表示此slave已经从master复制数据的总量的rank。rank越小代表已复制的数据越新。这种方式下持有最新数据的slave将会首先发起选举(理论上)。

3.2.4 集群脑裂数据丢失问题

redis集群没有过半机制会有脑裂问题,网络波动导致新选出的master和以前由于网络波动以为死亡的master节点都能对外提供写服务,一旦网络恢复,其中一个主节点将变为从节点,但是,这个主节点也对外提供了写服务,如果变成从节点会有大量数据丢失。 规避方法可以在redis配置里加上参数

 # 写数据成功最少同步的slave数量,这个数量可以模仿大于半数机制配置,
 # 比如主从集群总共三个节点,那就可以配置1,这时只要一个slave节点同步了数据,加上master节点,超过了半数 
 min‐replicas‐to‐write 1

注意:

  • 这种方法不可能百分百避免数据丢失,因为虽然保证了由一半的slave节点同步了数据,但是并不能保证,master节点是从这一半的slave节点中选出的。
  • 这个配置在一定程度上会影响集群的可用性,比如slave要是少于1个,这个主从集群就算master正常也不能提供服务了,所以需要具体场景权衡选择。
3.2.5 集群是否完整才能对外提供服务

当redis.conf的配置cluster-require-full-coverage为no时,表示当负责一个插槽的主库下线且没有相应的从库进行故障恢复时,集群仍然可用(插槽值不落在故障插槽库可用),如果为yes则集群不可用,不管插槽值落不落在故障插槽库都不可用。

3.3.5 Redis集群对批量操作命令的支持

对于类似mset,mget这样的多个key的原生批量操作命令,redis集群只支持所有key落在同一slot的情况,如果有多个key一定要用mset命令在redis集群上操作,则可以在key的前面加上{XX},这样参数数据分片hash计算的只会是大括号里的值,这样能确保不同的key能落到同一slot里去,示例如下:

mset {user}:name zyh {user}:age 18 

假设{user}:name{user}:age计算的hash slot值不一样,但是这条命令在集群下执行,redis只会对大括号里的user做hash slot计算,所以算出来的slot值肯定相同,最后都能落在同一slot。

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

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

相关文章

Unity(第六部)向量的理解和算法

标量:只有大小的量。185 888 999 &#xff08;类似坐标&#xff09; 向量:既有大小&#xff0c;也有方向。&#xff08;类似以个体为主体的方向&#xff0c;前方一百米&#xff09; 向量的模:向量的大小。&#xff08;类似以个体为主体的方向&#xff0c;前方一百米、只取一百米…

计算机设计大赛 深度学习实现语义分割算法系统 - 机器视觉

文章目录 1 前言2 概念介绍2.1 什么是图像语义分割 3 条件随机场的深度学习模型3\. 1 多尺度特征融合 4 语义分割开发过程4.1 建立4.2 下载CamVid数据集4.3 加载CamVid图像4.4 加载CamVid像素标签图像 5 PyTorch 实现语义分割5.1 数据集准备5.2 训练基准模型5.3 损失函数5.4 归…

软件测试笔记(三):黑盒测试

1 黑盒测试概述 黑盒测试也叫功能测试&#xff0c;通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作是一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情况下&#xff0c;对程序接口进行测试&#xff0c;只检查程序功能是否按…

nginx实现http反向代理及负载均衡

目录 一、代理概述 1、代理概念 1.1 正向代理&#xff08;Forward Proxy&#xff09; 1.2 反向代理&#xff08;Reverse Proxy&#xff09; 1.3 正向代理与反向代理的区别 2、同构代理与异构代理 2.1 同构代理 2.2 异构代理 2.3 同构代理与异构代理的区别 二、四层代…

【Web安全靶场】sqli-labs-master 21-37 Advanced-Injection

sqli-labs-master 21-37 Advanced-Injection 第一关到第二十关请见专栏 文章目录 sqli-labs-master 21-37 Advanced-Injection第二十一关-Cookie注入第二十二关-Cookie注入第二十三关-注释符过滤的报错注入第二十四关-二次注入第二十五关-过滤OR、AND双写绕过第二十五a关-过滤…

【SpringCloudAlibaba系列--OpenFeign组件】OpenFeign的配置、使用与测试以及OpenFeign的负载均衡

步骤一 准备两个服务&#xff0c;provider和consumer 本文使用kotlin语言 provider是服务的提供者&#xff0c;由provider连接数据库 RestController RequiredArgsConstructor RequestMapping("/provider/depart") class DepartController(private val departServ…

常用对象的遍历方法

var obj [{name: 1111,account: {01: { name: 1.1 },02: { name: 1.2 },03: { name: 1.3 },04: { name: 1.4 },05: { name: 1.5 },}} ]var nowObj obj[0].account;1、for…in 任意顺序遍历对象所有的可枚举属性&#xff08;包括对象自身的和继承的可枚举属性&#xff0c;不含…

flutter 封装webview和使用本地网页

最先看到flutter_webview_plugin 用法特别简单 flutter_webview_plugin | Flutter PackagePlugin that allow Flutter to communicate with a native Webview.https://pub-web.flutter-io.cn/packages/flutter_webview_plugin缺点&#xff1a; 没有实现js sdk的功能 没有办法 …

力扣简单递归:左叶子之和

思路&#xff1a;重点在于每层都记录val的值以减少递归调用次数 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int sumOfLeftLeaves(struct TreeNode* root){ if(rootNULL) {re…

Mycat核心教程--ZooKeeper集群搭建【三】

Mycat核心教程--ZooKeeper集群搭建 八、 ZooKeeper集群搭建8.1.ZooKeeper简介8.2.数据复制的好处8.3.Zookeeper设计目的8.4.zookeeper集群包括3种角色8.4.1.Leader角色8.4.2.Follower 角色8.4.3.Observer 角色 8.5.zookeeper集群工作流程8.6.zookeeper集群节点数量为奇数&#…

高性能Server的基石:reactor反应堆模式

业务开发同学只关心业务处理流程。但是我们开发的程序都是运行服务端server上&#xff0c;服务端server接收到IO请求后&#xff0c;是如何处理请求并最终进入业务流程的呢&#xff1f;这里不得不提到reactor反应堆模型。reactor反应堆模型来源于大师Doug Lea在 《Sacalable io …

图形判断类型

笔画数 笔画数这一考点。在国考、省考以及事业单位、三支一扶等各种公务员考试当中&#xff0c;都作为一个重要考点的存在。但很多同学仍然对于这部分知识点不清晰&#xff0c;比如不知道如何数奇点&#xff0c;数不清奇点&#xff0c;或无法快速识别这类题型&#xff0c;以致…

抖音橱窗怎么关闭?

路径&#xff1a;【抖音APP-我-电商带货-全部工具-账号管理-权限与账户-关闭电商权限】关闭橱窗带货权限。 0保、原0粉达人关闭电商权限后&#xff0c;后续均需要满足页面提示要求才可以进行电商权限的开通&#xff0c;建议慎重操作。

从新手到专家:AutoCAD 完全指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 AutoCAD是一款广泛用于工程设计和绘图的…

终于支持中文,开源手绘风格画板工具 Revezone 推荐!

Excalidraw 是一款老牌的手绘风格画板工具&#xff0c;颜值高&#xff0c;操作简单&#xff0c;GitHub 上拥有 69k 的 Star &#x1f449; https://excalidraw.com/ 可惜的是&#xff0c;Excalidraw 只有网页版&#xff0c;也不支持中文字体&#xff1a; 最近发现了国内开发者…

【k8s 高级调度--污点和容忍】

1、调度概念 在 Kubernetes 中&#xff0c;调度&#xff08;scheduling&#xff09;指的是确保 Pod 匹配到合适的节点&#xff0c; 以便 kubelet 能够运行它们。 抢占&#xff08;Preemption&#xff09;指的是终止低优先级的 Pod 以便高优先级的 Pod 可以调度运行的过程。 驱逐…

Time Travel

题目链接 解题思路 由于所有边集中的边加起来的总和至多为&#xff0c;无向图即&#xff0c;可以存下所以直接对所有边集中的边进行建边&#xff0c;同时对于每条边&#xff0c;记录其所在边集号对于每个边集&#xff0c;由大到小维护其能通过的时间点然后从1号跑最短路到当前…

笔记整理(安全)

第八天 内容安全 攻击可能是一个点&#xff0c;但是防御需要全方面进行 IAE 引擎 DFI和DPI技术 深度检测技术 DPI 深度包检测技术 主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#xff09;&#xff0c;之后对数据包的内容进行识别&#xff08;应用…

python学习笔记-内置异常

概述 Python 中的异常&#xff08;Exception&#xff09;是指在程序执行过程中遇到的错误或异常情况。当程序出现异常时&#xff0c;解释器会停止当前代码的执行&#xff0c;并试图找到匹配的异常处理器来处理异常。如果没有找到合适的异常处理器&#xff0c;程序就会终止并打…

anaconda指定目录创建环境无效/环境无法创建到指定位置

已经设置目录到D盘 创建环境时还是分配到C盘 可能是指定位置没有开启读写权限&#xff0c;如我在这里安装到了anaconda文件夹&#xff0c;则打开该文件夹的属性->安全->编辑 allusers下的权限全都打勾