【数据库】Redis主从复制、哨兵模式、集群

目录

一、Redis的主从复制

1.1 主从复制的架构

1.2 主从复制的作用

1.3 注意事项

 1.4 主从复制用到的命令

1.5 主从复制流程

 1.6 主从复制实现

1.7 结束主从复制

1.8 主从复制优化配置

二、哨兵模式

2.1 哨兵模式原理

2.2 哨兵的三个定时任务

2.3 哨兵的结构

2.4 哨兵模式的实现 

三、Redis集群cluster

3.1 cluster作用

3.2 cluster特点

3.3 cluster架构

3.4 cluster的部署


一、Redis的主从复制

1.1 主从复制的架构

主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点

1.2 主从复制的作用

  • 数据备份和容灾:通过主从复制可以将主数据库的数据实时同步到从数据库,以实现数据备份和容灾。如果主数据库发生故障,可以快速切换到从数据库,保障数据的可用性。
  • 负载均衡:通过主从复制可以将读操作分摊到多个从数据库上,从而降低主数据库的负载,实现读写分离,提高系统的整体性能和并发能力。
  • 数据分发:通过主从复制可以将数据分发到不同的地理位置或数据中心,以提高数据访问的速度和稳定性。

1.3 注意事项

导致主从服务器数据全部丢失的操作

1.假设节点A为主服务器,并且关闭了持久化。然后节点B和节点C从节点A复制数据
2.节点A崩溃,然后由自动拉起服务重启了节点A。由于节点A的持久化被关闭了,所以重启之后没有任何数据
3.节点B和节点C将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除。

 措施:

无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动启动

 1.4 主从复制用到的命令

命令解释
info replication查看主从状态
repliacaof 或者 ( slaveof )添加主从配置 例子: repliacaof 192.168.91.100 6379
CONFIG SET masterauth 123456临时设置密码
repliacaof masterip masterport临时添加主设置
REPLICAOF no one取消 主从配置

1.5 主从复制流程

  1. 连接建立:从数据库连接到主数据库,发送 SYNC 命令请求全量复制或 PSYNC 命令请求部分复制。

  2. 数据同步:主数据库收到同步请求后,将当前的数据快照发送给从数据库,或者根据 PSYNC 命令发送从指定的复制偏移量开始的数据。

  3. 命令传播:主数据库接收到写命令后,会这些写操作的命令记录到内存的命令缓冲区中,同时将这些命令同步到所有从数据库,从数据库接收到命令后按顺序执行相同的写操作,保持数据一致性。

  4. 重新连接:如果从数据库和主数据库之间的连接断开,从数据库会尝试重新连接主数据库,并从断开的位置继续复制数据,以保持同步。

总结:

第一次全同步

1)从服务器连接主服务器,发送[P]SYNC(同步)命令
2)主服务器接收到[P]SYNC命令后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令
3)主服务器BGSAVE执行完后,向所有从服务器发送RDB快照文件,并在发送期间继续记录被执行的写命令
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照至内存
5)主服务器快照发送完毕后,开始向从服务器发送内存缓冲区中的写命令
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令

后期部分同步
7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步

 1.6 主从复制实现

环境部署:

版本:Redis-6.2.6

主节点Master:192.168.254.10

从节点Slave1:192.168.254.20

从节点Slave2:192.168.254.30

实验配置:

###############主从服务器##################
systemctl stop firewalld
setenforce 0

###############主服务器##################
vim /apps/redis/etc/redis.conf 

#将监听端口改为任意端口
bind 0.0.0.0
#设置密码
requirepass  123456
#指定日志文件目录
logfile /apps/redis/log/redis.log
#指定PID文件位置
pidfile /apps/redis/run/
#指定工作目录(rdb、aof文件存放位置)
dir /apps/redis/data/
#开启AOF持久化功能
appendonly yes


###############从服务器1##################
vim /apps/redis/etc/redis.conf 
#将监听端口改为任意端口
bind 0.0.0.0
#设置密码
requirepass  123456
#设置主从配置,连接主服务器的密码
masterauth 123456
#指定日志文件目录
logfile /apps/redis/log/redis.log
#指定PID文件位置
pidfile /apps/redis/run/
#指定工作目录(rdb、aof文件存放位置)
dir /apps/redis/data/
#开启AOF持久化功能
appendonly yes
#开启主从复制,主的IP和端口
replicaof 192.168.254.10 6379

###############从服务器2##################
vim /apps/redis/etc/redis.conf 
#将监听端口改为任意端口
bind 0.0.0.0
#设置密码
requirepass  123456
#设置主从配置,连接主服务器的密码
masterauth 123456
#指定日志文件目录
logfile /apps/redis/log/redis.log
#指定PID文件位置
pidfile /apps/redis/run/
#指定工作目录(rdb、aof文件存放位置)
dir /apps/redis/data/
#开启AOF持久化功能
appendonly yes
#开启主从复制,主的IP和端口
replicaof 192.168.254.10 6379

1.7 结束主从复制

在从节点执行 REPLIATOF NO ONE 指令可以取消主从复制

REPLICAOF no one
#取消复制,在slave上执行REPLIATOF NO ONE,会断开和master的连接不再主从复制, 但不会清除slave上已有的数据

1.8 主从复制优化配置

1. 复制缓冲区(环形队列)配置参数:

#复制缓冲区大小,建议要设置足够大
repl-backlog-size 1mb 


#Redis同时也提供了当没有slave需要同步的时候,多久可以释放环形队列:  
repl-backlog-ttl   3600   #最长保持时间  3600秒

该缓冲区即为在主从复制时,主服务器在发送快照的同时,新的写操作存入内存缓冲区的缓冲区大小,需要设置足够大,否则超过的部分会覆盖掉未发送的数据。

 2. 避免全量复制,避免复制风暴

  • 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量

  • 节点运行ID不匹配:主节点重启会导致RUNID变化,可能会触发全量复制,可以利用故障转移,例如哨兵或集群,而从节点重启动,不会导致全量复制

  • 复制积压缓冲区不足: 当主节点生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全量复制.解决方法将repl-backlog-size 调大

  • 单主节点复制风暴,当主节点重启,多从节点复制

    可以采用级联复制,将一台slave服务器设为其他slave服务器的主

 3. 性能相关配置

repl-diskless-sync no # 是否使用无盘同步RDB文件,默认为no,no为不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes为支持无盘,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave

repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间

repl-ping-slave-period 10 #slave端向server端发送ping的时间间隔,默认为10秒

repl-timeout 60 #设置主从ping连接超时时间,超过此值无法连接,master_link_status显示为down,并记录错误日志

repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽, 但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,yes关注网络性能,no关注redis服务中的数据一致性



repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如master每秒最大写入64mb,最大允许60秒,那么就要设置为64mb*60秒=3840MB(3.8G),建议此值是设置的足够大

repl-backlog-ttl 3600 #3600秒   如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则 表示永远不释放这部份内存。

slave-priority 100 #slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择。

min-replicas-to-write 1 #设置一个master的可用slave不能少于多少个,否则master无法执行写

min-slaves-max-lag 20 #设置至少有上面数量的slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)

二、哨兵模式

哨兵模式是在主从复制的基础上,增加了主节点的故障移除功能。

一个被哨兵故障移除的主节点,在恢复后会变为新的主节点的从节点。

2.1 哨兵模式原理

哨兵(sentinel)是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的Master,并将所有Slave 连接到新的Master。所以整个运行哨兵的集群的数量不得少于3个节点。

2.2 哨兵的三个定时任务

  • 每10秒每个sentinel对master和slave执行info,发现slave节点,确认主从关系

  • 每2秒每个sentinel通过master节点的channel交换信息(pub/sub),通过sentinel__:hello频道交互,交互对节点的“看法”和自身信息

  • 每1秒每个sentinel对其他sentinel和redis执行ping

2.3 哨兵的结构

哨兵结构往往由两部分组成:哨兵节点数据节点

  • 数据节点:即主从数据库,用于写入和存储数据的节点
  • 哨兵节点:游离于数据节点,哨兵节点不会存储数据,它只负责监控数据节点是否正常

哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的Redis工作节点是否正常,当Master出现问题的时候,因为其他节点与主节点失去联系,因此会投票投票过半认为这个 Master 的确出现问题,然后会通知哨兵间,然后从Slaves中选取一个作为新的 Master

2.4 哨兵模式的实现 

环境配置:

三台数据节点,需要三台哨兵节点,为了节省服务器,直接在每台节点上配置哨兵节点

主数据库Master:192.168.254.10        哨兵节点1

从数据库Slave1:192.168.254.20        哨兵节点2

从数据库Slave2:192.168.254.30        哨兵节点3

配置前提:

!!!基于主从配置已经完成的情况下!!!

配置实现:

################所有主从服务器##################
echo 'requirepass "123456"' >> /apps/redis/etc/redis.conf
echo 'masterauth "123456"' >> /apps/redis/etc/redis.conf
systemctl stop firewalld
setenforce 0
systemctl restart redis



#################所有节点Sentinel配置##################
#编译安装时,源码包中有sentinel.conf配置文件
cp /data/redis-6.2.6/sentinel.conf /apps/redis/etc/
#给予权限
chown -R redis.redis /apps/redis

#编写配置
vim /apps/redis/etc/redis-sentinel.conf 

bind 0.0.0.0   #修改监听端口 
port 26379     #不用修改默认
daemonize no  # 不用修改systemd启动模式, 修改为yes后systemd启动不了
pidfile "/apps/resdis/run/redis-sentinel.pid"  #指定pid文件
logfile "/apps/redis/log/sentinel_26379.log"  # 指定日志文件
dir "/tmp"  #工作目录不用修改
sentinel monitor mymaster 192.168.254.10 6379 2
#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口
#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据
sentinel auth-pass mymaster 123456
#mymaster集群中master的密码,注意此行要在上面行的下面
sentinel down-after-milliseconds mymaster 3000
#(SDOWN)判断mymaster集群中所有节点的主观下线的时间,单位:毫秒,建议3000(3秒)否则等待时间过长
sentinel parallel-syncs mymaster 1
#发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力
sentinel failover-timeout mymaster 18000
#所有slaves指向新的master所需的超时时间,单位:毫秒

 准备service文件,开启服务先开启主的再开从的

#################所有节点##################
cat  >> /lib/systemd/system/redis-sentinel.service  <<eof
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
eof

systemctl daemon-reload

#################主节点###################
systemctl start redis-sentinel.service
#先开启主的

#################从节点###################
systemctl start redis-sentinel.service

验证:

##############所有节点###############
tail -f /apps/redis/log/sentinel.log


###############主节点##################
systemctl stop redis
#关闭主节点,观察日志变化

三、Redis集群cluster

3.1 cluster作用

哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。

3.2 cluster特点

  1. 所有Redis节点使用(PING机制)互联

  2. 集群中某个节点的是否失效,是由整个集群中超过半数的节点监测都失效,才能算真正的失效

  3. 客户端不需要proxy即可直接连接redis,应用程序中需要配置有全部的redis服务器IP

  4. redis cluster把所有的redis node 平均映射到 0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis 并发扩展了多少倍,每个redis node 承担16384/N个槽位

  5. Redis cluster预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) 取模 16384之后的值,决定将key写入值哪一个槽位从而决定写入哪一个Redis节点上,从而有效解决单机瓶颈

3.3 cluster架构

假如三个主节点分别是:M1,M2,M3 三个节点,采用哈希槽 (hash slot)的方式来分配16384个slot 的话它们三个节点分别承担的slot 区间可以是:

节点M1覆盖 0-5460                从节点S1

当M1损坏,S1会接替,M1和S1都坏了则0-5460槽位不可用
节点M2覆盖 5461-10922        从节点S2

当M2损坏,S2会接替,M2和S2都坏了则5461-10922槽位不可用
节点M3覆盖 10923-16383      从节点S3

当M3损坏,S3会接替,M3和S3都坏了则10923-16383槽位不可用

3.4 cluster的部署

环境配置:

一般cluster集群最起码需要6台服务器,3个主节点,3个从节点

方便起见,这里使用一台服务器分出6个实例来完成

节点1:192.168.254.10:6001

节点2:192.168.254.10:6002

节点3:192.168.254.10:6003

节点4:192.168.254.10:6004

节点5:192.168.254.10:6005

节点6:192.168.254.10:6006

配置演示:

#进入redis目录
cd /apps/redis
#创建集群文件目录
mkdir -p redis-cluster/redis600{1..6}

#准备执行文件到每个实例文件
for i in {1..6}
do
cp /data/redis-6.2.6/redis.conf /apps/redis/redis-cluster/redis600$i
cp /data/redis-6.2.6/src/redis-cli /data/redis-6.2.6/src/redis-server /apps/redis/redis-cluster/redis600$i
done

chown -R redis.redis /apps/redis

#进入6001端口实例配置文件
cd /apps/redis/redis-cluster/redis6001/
vim redis.conf

#bind 127.0.0.1							#69行,注释掉bind 项,默认监听所有网卡
protected-mode no						#88行,修改,关闭保护模式
port 6001								#92行,修改,redis监听端口,
daemonize yes							#136行,开启守护进程,以独立进程启动  如果是systemd 启动不需要修改,这里修改为yes,不使用systemd启动
cluster-enabled yes						#832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf		#840行,取消注释,群集名称文件设置
cluster-node-timeout 15000				#846行,取消注释群集超时时间设置
appendonly yes							#700行,修改,开启AOF持久化

#将此配置文件复制给每个实例下
for i in {2..6}
do
\cp -f  ./redis.conf   /apps/redis/redis-cluster/redis600${i}
done

#############################分隔符########################################

#这里提供一个快捷更改实例中配置的sed命令参考,进入不同实例目录中修改
cd /apps/redis/redis-cluster/redis6002
sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6002/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6002.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' redis.conf

#6003、6004、6005、6006如上,只需要修改端口即可

#############################分隔符########################################


#先暂停redis服务
systemctl stop redis

#进入实例文件夹,执行命令
for d in {1..6}
do
cd /apps/redis/redis-cluster/redis600$d
redis-server redis.conf
done

#检查进程是否全部开启
ss -natp |grep "\b600[1-6]\b"
#若看见6001~6006进程全部开启则成功


#开启集群
redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
#六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。
#--replicas 1 表示每个主节点有1个从节点。
#下面交互的时候 需要输入 yes 才可以创建。

#注意,要是您使用了六台服务器进行操作,这里的127.0.0.1需要改为各自服务器的IP

#看到OK后即为成功

 验证:

#加-c参数,节点之间就可以互相跳转
redis-cli -p 6001  -c
127.0.0.1:6001> cluster slots    #查看节点的哈希槽编号范围
1) 1) (integer) 5461
   2) (integer) 10922									#哈希槽编号范围
   3) 1) "127.0.0.1"
      2) (integer) 6003									#主节点IP和端口号
      3) "fdca661922216dd69a63a7c9d3c4540cd6baef44"
   4) 1) "127.0.0.1"
      2) (integer) 6004									#从节点IP和端口号
      3) "a2c0c32aff0f38980accd2b63d6d952812e44740"
2) 1) (integer) 0
   2) (integer) 5460
   3) 1) "127.0.0.1"
      2) (integer) 6001
      3) "0e5873747a2e26bdc935bc76c2bafb19d0a54b11"
   4) 1) "127.0.0.1"
      2) (integer) 6006
      3) "8842ef5584a85005e135fd0ee59e5a0d67b0cf8e"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 6002
      3) "816ddaa3d1469540b2ffbcaaf9aa867646846b30"
   4) 1) "127.0.0.1"
      2) (integer) 6005
      3) "f847077bfe6722466e96178ae8cbb09dc8b4d5eb"


127.0.0.1:6001>set name zzh
# 对name这个键进行算法 得出值为5789  跳到对应的主节点存储,并且从节点也会复制
-> Redirected to slot [5798] located at 127.0.0.1:6002
OK
127.0.0.1:6002>get name
"zzh"

#查看name键的槽编号
cluster keyslot name    #查看name键的槽编号

#查看节点信息
cluster nodes

#遍历关闭cluster
for i in {1..6}
do
kill -9 $(ss -natp | grep 600$i | tr -s " " | cut -d= -f2 | cut -d, -f1 | uniq)
done

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

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

相关文章

校园外卖系统带万字文档在线外卖管理系统java项目java课程设计java毕业设计

文章目录 校园外卖系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 校园外卖系统 一、项目演示 校园外卖服务系统 二、项目介绍 语言&#xff1a;java 数据库&…

ARM功耗管理标准接口之ACPI

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理有哪些标准接口&#xff1f;ACPI&PSCI&SCMI&#xff1f; Advanced Configuration and Power Interface Power State Coordination Interface System Control and Management Interface ACPI可以被理解为一…

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

前言 最近博主正在和队友准备九月的数学建模,在做往年的题目&#xff0c;博主主要是负责数据处理&#xff0c;运算以及可视化&#xff0c;这里分享一下自己部分的工作,相关题目以及下面所涉及的代码后续我会作为资源上传 问题求解 第一题 第一题的思路主要如下&#xff1a;…

单链表--续(C语言详细版)

2.6 在指定位置之前插入数据 // 在指定位置之前插入数据 void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); 分为两种情况&#xff1a;1. 插入的数据在链表中间&#xff1b;2. 插入的数据在链表的前面。 // 在指定位置之前插入数据 void SLTInsert(SLTNode** …

TISAX认证是什么?

TISAX认证是一种针对汽车行业数据安全和隐私保护的评估认证&#xff0c;其全称在不同资料中有所差异&#xff0c;但普遍认可的是它作为汽车行业信息安全评估体系的重要性。以下是对TISAX认证的详细解读&#xff1a; 一、背景和目的 随着汽车技术的不断发展&#xff0c;汽车数…

MySQL—统计函数和数学函数以及GROUP BY配合HAVING

合计/统计函数 count -- 演示 mysql 的统计函数的使用 -- 统计一个班级共有多少学生&#xff1f; SELECT COUNT(*) FROM student -- 统计数学成绩大于 90 的学生有多少个&#xff1f; SELECT COUNT(*) FROM student WHERE math > 90 -- 统计总分大于 250 的人数有多少&…

git-工作场景

1. 远程分支为准 强制切换到远程分支并忽略本地未提交的修改 git fetch origin # 获取最新的远程分支信息 git reset --hard origin/feature_server_env_debug_20240604 # 强制切换到远程分支&#xff0c;并忽略本地修改 2. 切换分支 1. **查看所有分支&#xff1a;**…

NewStarCTF2023-Misc

目录 week1 CyberChefs Secret 机密图片 流量&#xff01;鲨鱼&#xff01; 压缩包们 空白格 隐秘的眼睛 week2 新建Word文档 永不消逝的电波 1-序章 base! WebShell的利用 Jvav week3 阳光开朗大男孩 大怨种 2-分析 键盘侠 滴滴滴 week4 通大残 Nmap 依…

buuctf被嗅探的流量

下载出来是一个流量分析题 因为题目说了是联网状态下 嗅探到 所以一定有http协议 这里设置过滤器 一个一个去找吧 目前感觉wireshark的题都是http,太难的也不会

最后纪元Last Epoch可以通过什么搬砖 游戏搬砖教程

来喽来喽&#xff0c;最后纪元&#xff0c;一款《最后纪元》是一款以获得战利品为基础的暗黑风格动作RPG游戏&#xff0c;玩家将从2281年的毁灭时代追溯到由女神Eterra创造的世界&#xff0c;通过多个时代与黑暗的命运对抗&#xff0c;找到拯救世界的方式。游戏有五种职业&…

二叉平衡树(左单旋,右单旋,左右双旋、右左双旋)

一、AVL树&#xff08;二叉平衡树&#xff1a;高度平衡的二叉搜索树&#xff09; 0、二叉平衡树 左右子树高度差不超过1的二叉搜索树。 public class AVLTree{static class AVLTreeNode {public TreeNode left null; // 节点的左孩子public TreeNode right null; // 节点的…

【Unity2D 2022:NPC】制作NPC

一、创建NPC角色 1. 创建JambiNPC并同时创建Jambi站立动画 &#xff08;1&#xff09;点击第一张图片&#xff0c;按住shift不松&#xff0c;再选中后两张图片&#xff0c;拖到层级面板中 &#xff08;2&#xff09;将动画资源文件保存到Animation Clips文件夹中 &#xff08;…

三维引擎实践 - OSG渲染线程创建过程(未完待续)

一&#xff1a;概述 一个3D应用程序&#xff0c;在创建好图形窗口之后&#xff0c;就要使用该窗口的OpenGL上下文进行渲染相关工作了&#xff0c;本节分析下OSG源码中渲染线程的建立过程。 二&#xff1a;OSG渲染线程用到了哪些类&#xff1f; 1. GraphicsThread 类&#xff0c…

政安晨:【Keras机器学习示例演绎】(五十二)—— 使用门控残差和变量选择网络进行分类

目录 简介 数据集 安装准备 数据准备 定义数据集元数据 创建用于训练和评估的 tf.data.Dataset 创建模型输入 对输入特征进行编码 实施门控线性单元 实施门控余留网络 实施变量选择网络 创建门控残差和变量选择网络模型 编译、训练和评估模型 政安晨的个人主页&am…

怎么判断自己是否适合学习PMP?

判断自己是否适合学习PMP项目管理专业人士认证&#xff0c;可以从以下几个方面进行考量&#xff1a; 1、职业发展需求&#xff1a; 如果您在项目管理领域工作&#xff0c;或计划未来从事相关工作&#xff0c;PMP认证能显著提升您的竞争力。 对于项目经理、产品经理、技术领导…

什么是边缘计算?创造一个更快、更智慧、更互联的世界

前言 如今&#xff0c;数十亿物联网传感器广泛部署在零售商店、城市街道、仓库和医院等各种场所&#xff0c;正在生成大量数据。从这些数据中更快地获得洞察&#xff0c;意味着可以改善服务、简化运营&#xff0c;甚至挽救生命。但要做到这一点&#xff0c;企业需要实时做出决策…

【ESP32】打造全网最强esp-idf基础教程——16.SmartConfig一键配网

SmartConfig一键配网 一、SmartConfig知识扫盲 在讲STA课程的时候&#xff0c;我们用的是代码里面固定的SSID和密码去连接热点&#xff0c;但实际应用中不可能这么弄&#xff0c;我们得有办法把家里的WiFi SSID和密码输入到设备里面去&#xff0c;对于带屏带输入设备还…

15.x86游戏实战-汇编指令jmp call ret

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

【服务器】在Linux查看运行的Python程序,并找到特定的Python程序

在Linux查看运行的Python程序并找到特定的Python程序 写在最前面1. 使用ps命令查看所有Python进程查看详细信息 2. 使用pgrep命令查找Python进程ID 3. 使用top或htop命令使用top命令使用htop命令 4. 使用lsof命令查找Python进程打开的文件 5. 使用nvidia-smi命令查看GPU使用情况…

Cancer Cell | 卞修武院士/时雨/平轶芳团队揭示胶质瘤巨噬细胞研究全新视角

胶质母细胞瘤&#xff08;glioblastoma&#xff0c;GBM&#xff09;作为最常见的恶性脑肿瘤之一&#xff0c;其肿瘤微环境高度复杂且侵袭性极强。肿瘤相关巨噬细胞&#xff08;TAMs&#xff09;在胶质瘤发展和免疫抑制中扮演着关键角色&#xff0c;尽管靶向TAMs的治疗策略已经取…