redis主从复制【面试必看】

在分布式系统中,希望使用多个服务器来部署redis,存在以下几种redis的部署方式

  1. 主从模式
  2. 主从+哨兵
  3. 集群模式

主从模式

在若干个redis节点中,有的是主节点,有的是从节点

假设有三个物理服务器(称为是三个节点)

分别部署了一个redis-server进程,此时就可以把其中的一个节点作为主节点,另外两个作为从节点,从节点的数据跟随主节点变化,从节点的数据要和主节点保持一致,如果改了从节点的数据,不可以把从节点的数据同步到主节点中

如果从节点挂了,没有什么影响,但如果是主节点挂了,有一定影响,因为从节点只能读取数据,如果要写数据就没有节点可以写了,如果我们设置多个主节点的话,数据同步会比较麻烦

操作

正常来说,每个redis服务器程序,应该是在一个单独的主机上,由于我没有多个服务器,我就在一个服务器运行多个redis-server进程,此时需要保证多个redis-server端口是不同的

redis启动时指定启动端口的方法:

  1. 启动的时候,通过命令行来指定端口,- -port选项
  2. 直接在配置文件中,设定端口

我们把/etc/redis/redis.conf拷贝到一个目录下,然后对这两个配置文件进行修改

在这里插入图片描述

把slave1.conf中的port改为6380,daemonize改为yes(后台运行),slave2.conf中的port改为6381,daemonize改为yes

启动redis

在这里插入图片描述

使用redis-cli -p 6380,redis-cli -p 6381还有redis-cli启动三个redis,这个时候在主节点(6379)端口set key 111,6380端口的redis并不能看到,所以这个时候还没有达成主从复制

建立复制

想要达成主从复制有三种方式:

  1. 在配置⽂件中加⼊ slaveof {masterHost} {masterPort} 随 Redis 启动⽣效。→永久生效
  2. 在 redis-server 启动命令时加⼊ --slaveof {masterHost} {masterPort} ⽣效。
  3. 直接使⽤ redis 命令(在客户端中):slaveof {masterHost} {masterPort} ⽣效。→重启后就按照配置文件中的方案走

这里我们采用第一种方案:vim salve1.conf和vim salve2.conf,在最后面添加,这里以6379为主节点

在这里插入图片描述

这时候重新启动三个redis服务器才可以完成主从复制,通过 redis-cli 可以连接主 Redis 实例,通过 redis-cli -p 6380 连接从 Redis。并且观察复制关系。

127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6380> get hello
"world"

从运⾏结果中看到复制已经⼯作了,针对主节点 6379 的任何修改都可以同步到从节点 6380 中,复制过程如图所示。

使用netstat -anp | grep redis-server查看redis进程

在这里插入图片描述

又上图可知,其实主从复制就是主节点和从节点创建TCP连接

1)主节点6379复制状态信息,用info replication查看

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=100,lag=0
master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:100
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:100

2)从节点 6380 复制状态信息

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:170
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:170
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:170

这里介绍几个选项的含义:

  1. offset:相当于是从节点和主节点之间,同步数据的进度,因为主节点上会收到源源不断的"修改数据”请求,从节点就需要从主节点这里同步这些修改请求,从节点和主节点之问的数据同步,不是瞬问完成的!!
  2. lag:延迟
  3. master_replid:主节点的身份标识
  4. master_replid2:如果master节点宕机了,slave节点成功切换为master后,会将之前master_replid记录的值存储到master_replid2中,自己生成一个新的随机字符,作为自己的master标识,存储在master_replid中
  5. master_repl_offset:主节点数据修改了多少
  6. repl_backlog_active/repl_backlog_size/repl_backlog_first_byte_offset/repl_backlog_histlen:积压缓冲区,支持部分同步机制的实现
  7. slave_priority:主节点挂了,选择从节点作为主节点的优先级
  8. slave_read_only:从节点是否只读
  9. connected_slaves:从节点下面也可以再有从节点,也可以用从节点去同步从节点

关于master_replid和master_replid2可以看这篇文章:replication中的两个master_replid

断开复制

slaveof 命令不但可以建⽴复制,还可以在从节点执⾏ slaveof no one(在客户端中输入)来断开与主节点复制关系。
例如在 6380 节点上执⾏ slaveof no one 来断开复制。
断开复制主要流程:
1)断开与主节点复制关系。
2)从节点晋升为主节点。
从节点断开复制后并不会抛弃原有数据,只是⽆法再获取主节点上的数据变化。

通过 slaveof 命令还可以实现切主操作,将当前从节点的数据源切换到另⼀个主节点。执⾏
slaveof {newMasterIp} {newMasterPort} 命令即可。
切主操作主要流程:
1)断开与旧主节点复制关系。
2)与新主节点建⽴复制关系。
3)删除从节点当前所有数据。
4)从新主节点进⾏复制操作。

安全性

对于数据⽐较重要的节点,主节点会通过设置 requirepass 参数进⾏密码验证,这时所有的客户
端访问必须使⽤ auth 命令实⾏校验。从节点与主节点的复制连接是通过⼀个特殊标识的客户端来完
成,因此需要配置从节点的masterauth 参数与主节点密码保持⼀致,这样从节点才可以正确地连接到主节点并发起复制流程。

只读

默认情况下,从节点使⽤ slave-read-only=yes 配置为只读模式。**由于复制只能从主节点到从节
点,对于从节点的任何修改主节点都⽆法感知,修改从节点会造成主从数据不⼀致。**所以建议线上不
要修改从节点的只读模式。

传输延迟

主节点和从节点之间通过网络来传输(TCP),TCP内部支持了nagle算法(默认开启)

开启:会增加tcp的传输延迟,节省了网络带宽

关闭:会减少网络延迟,增加了网络带宽

这个nagle算法和捎带应答目的是一样的,针对较小的数据包进行合并,减少了包的个数

redis中repl-disable-tcp-nodelay选项用于在主从同步通信过程中,关闭tcp 的nagle 算法,从节点更快速的和主节点进行同步

拓扑结构

一主一从结构

⼀主⼀从结构是最简单的复制拓扑结构,⽤于主节点出现宕机时从节点提供故障转移⽀持,如图
所示。当应⽤写命令并发量较⾼且需要持久化时,可以只在从节点上开启 AOF,这样既可以保证数据安全性同时也避免了持久化对主节点的性能⼲扰。但需要注意的是,当主节点关闭持久化功能时,如果主节点宕机要避免⾃动重启操作。(如果自动重启,此时没有AOF文件,就会丢失数据,进一步的主从同步,会把从节点的数据也删除掉)

在这里插入图片描述

一主多从

⼀主多从结构(星形结构)使得应⽤端可以利⽤多个从节点实现读写分离。对于读⽐重较⼤的场景,可以把读命令负载均衡到不同的从节点上来分担压⼒。同时⼀些耗时的读命令可以指定⼀台专⻔的从节点执⾏,避免破坏整体的稳定性。对于写并发量较⾼的场景,多个从节点会导致主节点写命令的多次发送从⽽加重主节点的负载。(主节点上数据的修改,就会把改变的数据同步到从节点)

在这里插入图片描述

树形主从结构

树形主从结构(分层结构)使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主
节点继续向下层复制。通过引⼊复制中间层,可以有效降低住系欸按负载和需要传送给从节点的数据
量数据写⼊节点 A 之后会同步给 B 和 C 节点,B 节点进⼀步把数据同步给 D 和 E 节点。当主节点需要挂载等多个从节点时为了避免对主节点的性能⼲扰,可以采⽤这种拓扑结构。

在这里插入图片描述

原理

如图所示,下⾯详细介绍建⽴复制的完整流程。从图中可以看出复制过程⼤致分为 6 个过程:
主从节点建⽴复制流程图

在这里插入图片描述

1)保存主节点(master)的信息。

开始配置主从同步关系之后,从节点只保存主节点的地址信息,此时建⽴复制流程还没有开始,

在从节点 6380 执⾏ info replication 可以看到如下信息:

master_host: 127.0.0.1
master_port: 6379
master_link_status: down

从统计信息可以看出,主节点的 ip 和 port 被保存下来,但是主节点的连接状态(master_link_status)是下线状态。

2)从节点(slave)内部通过每秒运⾏的定时任务维护复制相关逻辑,当定时任务发现存在新的主节

点后,会尝试与主节点建⽴基于 TCP 的⽹络连接。如果从节点⽆法建⽴连接,定时任务会⽆限重试直到连接成功或者⽤户停⽌主从复制。(TCP三次握手验证通信双方是否能正确读取数据,系统层面)

3)发送 ping 命令。连接建⽴成功之后,从节点通过 ping 命令确认主节点在应⽤层上是⼯作良好的。如果 ping 命令的结果 pong 回复超时,从节点会断开 TCP 连接,等待定时任务下次重新建⽴连接。

4)权限验证。如果主节点设置了 requirepass 参数,则需要密码验证,从节点通过配置 masterauth

参数来设置密码。如果验证失败,则从节点的复制将会停⽌。

5)同步数据集。对于⾸次建⽴复制的场景,主节点会把当前持有的所有数据全部发送给从节点,这步操作基本是耗时最⻓的,所以⼜划分称两种情况:全量同步和部分同步,下⼀节重点介绍。

6)命令持续复制。当从节点复制了主节点的所有数据之后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执⾏修改命令,保证主从数据的⼀致性。

数据同步

Redis 使⽤ psync 命令完成主从数据同步,同步过程分为:全量复制和部分复制。

  • 全量复制:⼀般⽤于初次复制场景,Redis 早期⽀持的复制功能只有全量复制,它会把主节点全部数据⼀次性发送给从节点,当数据量较⼤时,会对主从节点和⽹络造成很⼤的开销。
  • 部分复制:⽤于处理在主从复制中因⽹络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。因为补发的数据远⼩于全量数据,可以有效避免全量复制的过⾼开销。
  • 实时复制:从节点,已经和主节点,同步好了数据了(从节点这一时刻已经和主节点数据一致了)但是之后,主节点这边会源源不断的收到新的修改数据的请求,主节点上的数据就会随之改变,也需要能够同步给从节点

从节点使⽤ psync 命令完成部分复制和全量复制功能,命令格式:psync {replicationId} {offset},参数含义:replicationId 是从节点所复制的主节点的运⾏ ID、offset 是当前从节点已复制的数据偏移量。

全量复制

在这里插入图片描述

1)从节点发送 psync 命令给主节点,replicationId 和 offset 的默认值分别是 ? 和 -1。
2)主节点根据 psync 参数和⾃⾝数据情况决定响应结果:

  • 如果回复 +FULLRESYNC replicationId offset,则从节点需要进⾏全量复制流程。
  • 如果回复 +CONTINEU,从节点进⾏部分复制流程。
  • 如果回复 -ERR,说明 Redis 主节点版本过低,不⽀持 psync 命令。从节点可以使⽤ sync 命令进⾏全量复制。

psync 并不需要咱们⼿动执⾏,Redis 会在主从复制模式下⾃动调⽤执⾏。

在这里插入图片描述

1)从节点发送 psync 命令给主节点进⾏数据同步,由于是第⼀次进⾏复制,从节点没有主节点的运⾏ ID 和复制偏移量,所以发送 psync ? -1。
2)主节点根据命令,解析出要进⾏全量复制,回复 +FULLRESYNC 响应。
3)从节点接收主节点的运⾏信息进⾏保存。
4)主节点执⾏ bgsave 进⾏ RDB ⽂件的持久化。
5)主节点发送 RDB ⽂件给从节点,从节点保存 RDB 数据到本地。
6)主节点将从⽣成 RDB 到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点加载完 RDB ⽂件后,主节点再将缓冲区内的数据补发给从节点,保持主从⼀致性。
7)从节点清空⾃⾝原有旧数据。
8)从节点加载 RDB ⽂件得到与主节点⼀致的数据。
9)如果从节点加载 RDB 完成之后,并且开启了 AOF 持久化功能,它会进⾏ bgrewrite 操作,得到最近的 AOF ⽂件。

由于当前收到的是大批量的数据,此时产生的 aof 日志,整体来说,可能会存在一定的冗余信息,因此针对 aof 日志进行整理,也是必要的过程

Redis Bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。
即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

无硬盘模式:主节点生成的rdb二进制数据,不直接保存到文件中了,而是直接进行网络传输(节省了一系列的读硬盘和写硬盘的操作),从节点,直接把收到的数据进行加载

部分复制

部分复制主要是 Redis 针对全量复制的过⾼开销做出的⼀种优化措施,使⽤ psync replicationId offset 命令实现。当从节点正在复制主节点时,如果出现⽹络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,如果主节点的复制积压缓冲区存在数据则直接发送给从节点,这样就可以保持主从节点复制的⼀致性。补发的这部分数据⼀般远远⼩于全量数据,所以开销很⼩。整体流程如图所示。

在这里插入图片描述

1)当主从节点之间出现⽹络中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并终端 复制连接。
2)主从连接中断期间主节点依然响应命令,但这些复制命令都因⽹络中断⽆法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
3)当主从节点⽹络恢复后,从节点再次连上主节点。
4)从节点将之前保存的replicationId 和 复制偏移量作为 psync 的参数发送给主节点,请求进⾏部分复制。
5)主节点接到 psync 请求后,进⾏必要的验证。随后根据 offset 去复制积压缓冲区查找合适的数据,并响应 +CONTINUE 给从节点。
6)主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性。

积压缓冲区:

在这里插入图片描述

就是一个内存中的简单的队列,会记录最近一段时间修改的数据,总量有限,随着时间的推移,就会把之前的,旧的数据逐渐删掉。

replicationid 其实就是在描述"数据的来源",offset 描述"数据的复制的进度"
如果 replicationld 不一样,需要全量复制一下。
如果 replicationld 一样,offset 再判定。
offset 表示 从节点之前同步数据的进度是如何,主节点就看这个进度是否在当前的积压缓冲区之内
如果确实是在积压缓冲区之内,此时就可以直接进行部分复制,就只把最近这段时间的数据给复制过去即可,如果当前从节点的进度已经超出积压缓冲区的范围了,需要全量复制。

实时复制

从节点和主节点之间会建立 TCP 的长连接,然后主节点把自己收到的修改数据的请求,通过上述 连接,发给从节点从节点再根据这些修改请求,修改内存中的数据,这个过程也需要时间,正常来说延迟比较小,主从节点在建⽴复制连接后,它们之间需要维护⻓连接并彼此发送⼼跳命令。

1)主从节点彼此都有⼼跳检测机制,各⾃模拟成对⽅的客户端进⾏通信。
2)主节点默认每隔 10 秒对从节点发送 ping命令,判断从节点的存活性和连接状态。
3)从节点默认每隔 1 秒向主节点发送 replconf ack {offset} 命令,给主节点上报⾃⾝当前的复制偏移量。
如果主节点发现从节点通信延迟超过 repl-timeout 配置的值(默认 60 秒),则判定从节点下线,断开复制客户端连接。从节点恢复连接后,⼼跳机制继续进⾏

replication id/runid

多数资料对这两个的区分有所问题,一个redis服务器上,replication id和run id都是存在的

主节点:info replication

在这里插入图片描述

info server

在这里插入图片描述

从节点:info replication

在这里插入图片描述

info server

在这里插入图片描述

官方文档中psync replicationid offset而不是runid

runid主要是用在支持实现redis哨兵的功能的

主从复制总结

主从复制的特点:

  1. Redis 通过复制功能实现主节点的多个副本。
  2. 主节点⽤来写, 从节点⽤来读. 这样做可以降低主节点的访问压⼒.
  3. 复制⽀持多种拓扑结构,可以在适当的场景选择合适的拓扑结构。
  4. 复制分为全量复制和部分复制。
  5. 主从节点之间通过⼼跳机制保证主从节点通信正常和数据⼀致性。

主从复制的缺点:

  1. 从机多了, 复制数据的延时⾮常明显.
  2. 主机挂了, 从机不会升级成主机. 只能通过⼈⼯⼲预的⽅式恢复.

redis主节点无法重启

从节点和主节点断开连接有两种情况:

  1. 从节点主动和主节点断开连接:slaveof no one,这个时候从节点晋升为主节点
  2. 主节点挂了:从节点不会晋升为主节点,必须通过人工干预的方法,恢复主节点

这里有aof文件,这个文件是redis服务器重启的时候,需要加载的

在这里插入图片描述

在上文介绍中,我们三个redis服务器共用的是一个aof文件,这是错误的从节点是通过手动启动的方式运行的。 此时 root 用户下启动redis 服务器,于是生成的 aof 文件也就是root用户的文件。

通过service redis-server start启动的redis服务器,是通过redis这样的用户来启动的,redis server 需要按照可读可写的方式打开这个 aof 文件,而这个文件对于 root 之外的用户只有读权限,因此 service redis-server start 启动的redis 服务器无法打开这个文件,就启动失败了。

解决方法:

  1. 把三个不同的redis服务器生成的文件区分开
  2. 把三个redis服务器的工作目录区分开(修改配置文件中的dir选项)

这里采用第二种方案演示:

  1. 停止所有redis服务器
  2. 删除之前工作目录下已经生成的aof文件,或者chown更改权限

在这里插入图片描述

  1. 给从节点创建出新的目录,用来作为从节点的工作目录

在这里插入图片描述

vim slave1.conf和slave2.conf修改dir选项为/root/redis-conf

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

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

相关文章

Rust测试字符串的移动,Move

代码创建了一个结构体,结构体有test1 字符串,还有指向字符串的指针。一共创建了两个。 然后我们使用swap 函数 交换两个结构体内存的内容。 最后如上图。相同的地址,变成了另外结构体的内容。注意看指针部分,还是指向原来的地址…

CSS 绝对定位问题和粘性定位介绍

目录 1,绝对定位问题1,绝对定位元素的特性2,初始包含块问题 2,粘性定位注意点: 1,绝对定位问题 1,绝对定位元素的特性 display 默认为 block。所以行内元素设置绝对定位后可直接设置宽高。脱离…

ATECLOUD电源自动测试系统打破传统 助力新能源汽车电源测试

随着新能源汽车市场的逐步扩大,技术不断完善提升,新能源汽车测试变得越来越复杂,测试要求也越来越严格。作为新能源汽车的关键部件之一,电源为各个器件和整个电路提供稳定的电源,满足需求,确保新能源汽车的…

Ubuntu中编译出Windows的可执行程序(.exe)

1、前言 在嵌入式开发中,交叉编译是很常见的情况,如果你把Windows电脑也看做一块高性能的开发板,那在Ubuntu中编译出Windows上运行的可执行程序也是很好理解的行为。 2、安装mingw64环境 sudo apt-get install mingw-w64 3、测试编译链是否安…

来自bioBakery Lab的宏基因组学微生物群落的代谢功能分析工具-HUMAnN 3.0的安装配置及分析使用方法-安装填坑

HUMAnN 3.0 简介: HUMAnN 3.0 是一个用于宏基因组数据分析的工具,能够从宏基因组测序数据中推断出微生物群落的代谢功能信息。它可以识别微生物群落中存在的代谢途径,并定量这些通路的丰度。HUMAnN 3.0 依赖于多个工具和数据库来实现这些功能…

C++新经典模板与泛型编程:策略类模板

策略类模板 在前面的博文中,策略类SumPolicy和MinPolicy都是普通的类,其中包含的是一个静态成员函数模板algorithm(),该函数模板包含两个类型模板参数。其实,也可以把SumPolicy和MinPolicy类写成类模板—直接把algorithm()中的两…

Python 网络爬虫(三):XPath 基础知识

《Python入门核心技术》专栏总目录・点这里 文章目录 1. XPath简介2. XPath语法2.1 选择节点2.2 路径分隔符2.3 谓语2.4 节点关系2.5 运算符3. 节点3.1 元素节点(Element Node)3.2 属性节点(Attribute Node)

获取类class对象的方式

一、什么是class对象 Class类位于java核心包lang包中,它是反射的源头。Class对象用于记录每个类的运行时数据结构,或者说是在内存中访问类的静态数据的接口,每个类都有一个唯一的Class对象。Class对象不能直接通过new来获取,因为…

【ArcGIS Pro微课1000例】0051:创建数据最小几何边界范围(点、线、面数据均可)

本实例为专栏系统文章:创建点数据最小几何边界(范围),配套案例数据,持续同步更新! 文章目录 一、工具介绍二、实战演练三、注意事项一、工具介绍 创建包含若干面的要素类,用以表示封闭单个输入要素或成组的输入要素指定的最小边界几何。 工具界面及参数如下所示: 核心…

CSS——sticky定位

1. 大白话解释sticky定位 粘性定位通俗来说,它就是相对定位relative和固定定位fixed的结合体,它的触发过程分为三个阶段 在最近可滚动容器没有触发滑动之前,sticky盒子的表现为相对定位relative【第一阶段】, 但当最近可滚动容…

FacetWP Relevanssi Integration相关性集成插件

点击阅读FacetWP Relevanssi Integration相关性集成插件原文 FacetWP Relevanssi Integration相关性集成插件是FacetWP与用于高级搜索的 Relevanssi 插件的集成显着增强了您网站的搜索功能。这个强大的工具使您的用户能够轻松找到他们寻求的特定内容,无论他们的查询…

联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023

联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023 随着移动智能设备的普及和人工智能技术的发展,越来越多的分布式数据在终端被产生与收集,并以多接入边缘计算(MEC)的形式进行处理和分析。但是由于用户的行为模式与服务需求的多样,不同设备上的数据分布…

Android 幸运转盘实现逻辑

一、前言 幸运转盘在很多app中都有,也有很多现实的例子,不过这个难度并不是如何让转盘转起来,真正的难度是如何统一个方向转动,且转到指定的目标区域(中奖概率从来不是随机的),当然还不能太假&…

C语言数组(下)

我希望各位可以在思考之后去看本期练习,并且在观看之后独立编写一遍,以加深理解,巩固知识点。 练习一:编写代码,演⽰多个字符从两端移动,向中间汇聚 我们依旧先上代码 //编写代码,演⽰多个字…

UE小:UE5性能分析

开始录制性能追踪 要开始录制性能追踪,您可以简单地点击界面上的“开始录制”按钮。 查看追踪数据 录制完成后,点击“Trace”菜单中的“UnrealInsights”选项来查看追踪数据。 使用命令行进行追踪 如果点击录制按钮没有反应,您可以通过命令…

Leetcode—901.股票价格跨度【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—901.股票价格跨度 算法思想 实现代码 class StockSpanner { public:stack<pair<int, int>> st;int curday -1;StockSpanner() {st.emplace(-1, INT_MAX);}int next(int price) {while(price > st.top(…

【LeetCode】28. 找出字符串中第一个匹配项的下标 【字符串单模匹配:KMP算法】

题目链接 Python3 直觉解法 class Solution:def strStr(self, haystack: str, needle: str) -> int:pn, ph 0, 0n len(needle) h len(haystack)while ph < h:if haystack[ph] needle[pn]:if pn n-1: # 1234 123return ph - len(needle) 1else: pn 1ph 1else:…

53. Protocol buffer 的Go使用

文章目录 一、介绍二、安装三、protoc3语法1、 protoc3 与 protoc2区别2、proto3生成go代码包Message内嵌Message字段单一标量字段单一message字段可重复字段slicemap字段枚举 一、介绍 Protobuf是Google旗下的一款平台无关&#xff0c;语言无关&#xff0c;可扩展的序列化结构…

苹果IOS在Safari浏览器中将网页添加到主屏幕做伪Web App,自定义图标,启动动画,自定义名称,全屏应用pwa

在ios中我们可以使用Safari浏览自带的将网页添加到主屏幕上&#xff0c;让我们的web页面看起来像一个本地应用程序一样&#xff0c;通过桌面APP图标一打开&#xff0c;直接全屏展示&#xff0c;就像在APP中效果一样&#xff0c;完全体会不到你是在浏览器中。 1.网站添加样式 在…

一加 12 Pop-up快闪活动来袭,十城联动火爆开启

12 月 9 日&#xff0c;一加 12 Pop-up 快闪活动在北京、深圳、上海、广州等十城联动开启&#xff0c;各地加油欢聚快闪现场&#xff0c;抢先体验与购买一加 12。作为一加十年超越之作&#xff0c;一加 12 全球首发拥有医疗级护眼方案和行业第一 4500nit 峰值亮度的 2K 东方屏、…