【Redis】高可用架构之Cluster集群和分⽚

news2024/11/15 12:22:52

高可用架构之Cluster集群和分⽚

  • 1. 前言
  • 2. Cluster 模式介绍
    • 2.1 什么是Cluster模式?
    • 2.2 为什么需要Cluster模式?
      • 2.2.1 垂直拓展(scale up)和水平拓展(scale out)
      • 2.2.2 Redis Cluster 提供的好处
      • 2.2.3 Redis Cluster 和 replication + sentinel 如何选择?
  • 3. Redis Cluster 环境搭建
  • 4. Redis Cluster 实现原理
    • 4.1 集群的组群过程
    • 4.2 集群数据分片原理
      • 4.2.1 哈希槽(slots)的划分
      • 4.2.2 哈希槽(slots)的映射
    • 4.3 数据复制过程和故障转移
      • 4.3.1 数据复制
      • 4.3.2 故障检测
      • 4.3.3 主从故障转移
    • 4.4客户端如何定位数据所在实例?
      • 4.4.1 定位数据所在节点
      • 4.4.2 重新分配哈希槽
        • (1)MOVED 错误
        • (2)ASK 错误
    • 4.5 ⽤表保存键值对和实例的关联关系可⾏么?
  • 5. 集群可以设置多⼤?
    • 5.1 Gossip 消息
    • 5.2 实例的通信频率

1. 前言

前面,我们一起学习了 Redis 高可用架构的两种模式:主从模式、哨兵模式。解决了:在Redis实例发生故障时,具备主从自动切换、故障转移的能力,最终保证服务的高可用

随着我们业务规模的不断扩展,用户量膨胀,并发量持续提升,原有的主从架构,已不足以支撑。

  • Redis 并发量 10万 / 每秒 ,但是有些业务需要 100万的 QPS

  • 数据量,我们普通机器 16~256g,而我们的业务需要500g

解决方案:

  • 并发量大了 -> 主从复制解决

  • 主从稳定性 -> 哨兵解决

  • 单节点的写能力、存储能力、动态扩容都很麻烦 -> 集群 Cluster 解决。

集群提供了以下关键的特性:

  • 可扩展性

  • 高可用性

  • 负载均衡

  • 错误恢复

下面,由一张思维导图来开始学习 Redis Cluster 模式:

在这里插入图片描述

2. Cluster 模式介绍

2.1 什么是Cluster模式?

Redis Cluster 是⼀种分布式数据库⽅案,集群通过分⽚(sharding)来进⾏数据管理(分治思想的⼀种实践),并提供复制和故障转移功能。

Redis Cluster 采用无中心结构,每个节点都可以保存数据和整个集群状态,每个节点都和其他所有节点连接。要让集群正常运作至少需要三个主节点,即 Cluster 至少为6个才能保证组成完整高可用的集群。

Redis Cluster 将数据划分为 16384 (2的14次方)个哈希槽(slots),每个实例节点管理⼀部分槽位,槽位的信息存储于每个节点中。以下图为例,该集群有3个 Redis 节点,每个节点负责集群中的一部分数据,数据量可以不均匀。比如性能好的实例节点可以多分担一些压力:

在这里插入图片描述
当 16384 个哈希槽都有节点进行管理的时候,集群处于 online 状态。同样的,如果有一个哈希槽没有被管理到,那么集群处于 offline 状态。集群之间的信息通过 Gossip协议 进行交互,每个节点记录其他节点的哈希槽(slots)的分配情况。

2.2 为什么需要Cluster模式?

2.2.1 垂直拓展(scale up)和水平拓展(scale out)

单机的吞吐无法承受持续扩增的流量的时候,最好的办法是从垂直拓展(scale up)和水平拓展(scale out)两方面进行扩展:

  • 垂直扩展(scale up):将单个实例的硬件资源做提升,比如 CPU核数量、内存容量、SSD容量。

  • 水平扩展(scale out):水平扩增 Redis 实例数,这样每个节点只负责一部分数据就可以,分担一下压力,典型的分治思维。

在这里插入图片描述

  • 垂直拓展(scale up)部署简单,但是当数据量⼤并且使⽤ RDB 实现持久化,会造成阻塞导致响应慢。另外受限于硬件和成本,拓展内存的成本太⼤,⽐如拓展到 1T 内存。

  • ⽔平拓展(scale out)便于拓展,同时不需要担⼼单个实例的硬件和成本的限制。但是,切⽚集群会涉及多个实例的分布式管理问题,需要解决如何将数据合理分布到不同实例,同时还要让客户端能正确访问到实例上的数据。

2.2.2 Redis Cluster 提供的好处

  • 将数据自动切分到多个节点的能力;

  • 当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力,拥有自动故障转移的能力。

2.2.3 Redis Cluster 和 replication + sentinel 如何选择?

  • Replication:一个 master,多个 slave,要几个 slave 跟你的要求的读吞吐量有关系,结合 sentinel 集群,去保证 Redis 主从架构的高可用就行了;

  • Redis Cluster:主要是针对海量数据 + 高并发 + 高可用的场景,海量数据,如果数据量很大,建议用 Redis Cluster。

3. Redis Cluster 环境搭建

这里不多赘述,附上网上的搭建方案:Redis 6.X Cluster 集群搭建。

4. Redis Cluster 实现原理

4.1 集群的组群过程

⼀个 Redis 集群通常由多个节点(node)组成,在刚开始的时候,每个节点都是隔离且毫无联系的。要组建⼀个真正可⼯作的集群,我们必须将各个独⽴的节点连接起来,构成⼀个包含多个节点的集群。

各个节点的联通是通过 CLUSTER MEET 命令完成的:CLUSTER MEET <ip> <port>

其中一个节点 node 向另⼀个节点 node (指定 ip 和 port)发送 CLUSTER MEET 命令,这样就可以让两个节点进⾏握⼿(handshake),当握⼿成功后,node 节点就会将指定 ip 和 port 的节点添加到 node 节点当前所在的集群中。就这样一步步的将需要聚集的节点都圈入同一个集群中:

在这里插入图片描述

4.2 集群数据分片原理

4.2.1 哈希槽(slots)的划分

整个 Redis 数据库被划分为16384个哈希槽,Redis 集群可能有 n 个实例节点,每个节点可以处理 0个 到至多 16384个 槽点,这些节点把 16384个槽位瓜分完成。

实际存储的 Redis 键值信息也必然归属于这 16384 个槽的其中一个。slots 与 Redis Key 的映射是通过以下两个步骤完成的:

  1. 使用 CRC16 算法计算键值对信息的 key,会得出一个 16 bit 的值。
  2. 将 16 bit 的值对 16384 执⾏取模,得到 0 ~ 16383 的数表示 key 对应的哈希槽。

Cluster 还允许⽤户强制某个 key 挂在特定的 slot 上面,也就是同一个实例节点上。这时候可以用 hash tag 能力,强制 key 所归属的槽位等于 tag 所在的槽位。

其实现方式为在 key 中加个 {},例如 test_key{1}。使用 hash tag 后客户端在计算 key 的CRC16 时,只计算 {} 中数据。如果没使用 hash tag,客户端会对整个 key 进行 CRC16 计算:

127.0.0.1:6379> cluster keyslot user:case{1}
(integer) 1024
127.0.0.1:6379> cluster keyslot user:favor
(integer) 1023
127.0.0.1:6379> cluster keyslot user:info{1}
(integer) 1024

如上,使用 hash tag 后会对应到同一个 hash slot:1024 中。

4.2.2 哈希槽(slots)的映射

哈希槽⼜是如何映射到 Redis 实例上呢?主要有两种方案:

  • 一种是初始化的时候均匀分配 ,使用 cluster create 创建,会将 16384 个 slots 平均分配在我们的集群实例上,比如你有n个节点,那每个节点的槽位就是 16384 / n 个了 。

  • 另一种是通过 CLUSTER MEET 命令将 node1、node2、ndoe3 三个节点联通成一个集群,刚联通的时候因为还没分配哈希槽,所以处于 offline 状态。可以使⽤ cluster addslots 命令,指定每个实例上的哈希槽个数。

为什么要通过 addslots 命令指定哈希槽范围?

加⼊集群中的 Redis 实例配置不⼀样、所处理的业务也不一样,可以通过 addslots 命令指定哈希槽范围,让性能好的实例节点可以多分担一些压力

比如下图中,我们哈希槽是这么分配的:实例 1 管理 0 ~ 7120 哈希槽,实例 2 管理 7121~9945 哈希槽,实例 3 管理 9946 ~ 13005 哈希槽,实例 4 管理 13006 ~ 16383 哈希槽:

redis-cli -h 192.168.0.1 –p 6379 cluster addslots 0,7120
redis-cli -h 192.168.0.2 –p 6379 cluster addslots 7121,9945
redis-cli -h 192.168.0.3 –p 6379 cluster addslots 9946,13005
redis-cli -h 192.168.0.4 –p 6379 cluster addslots 13006,16383

slots 和 Redis 实例之间的映射关系如下:

在这里插入图片描述
key testkey_1testkey_2 经过 CRC16 计算后再对 slots 的总个数 16384 取模,结果分别匹配到了 cache1 和 cache3 上。

4.3 数据复制过程和故障转移

4.3.1 数据复制

Cluster 是具备 Master 和 Slave 模式,Redis Cluster 中的每个 Master 实例节点分管了不同的槽位区间。而每个 Master 至少需要一个 Slave 节点,Slave 节点是通过《Redis 主从复制》方式同步主节点数据。

节点之间保持 TCP 通信,当 Master 下线, Redis Cluster 自动会将对应的 Slave 节点选为 Master 来继续提供服务。主从节点之间并没有读写分离, Slave 只⽤作 Master 宕机的⾼可⽤备份。

如果主节点没有从节点,那么一旦发生故障时,集群将完全处于不可用状态。 但也允许配置 cluster-require-full-coverage 参数:即使部分节点不可用,其他节点正常提供服务,这是为了避免全盘宕机。

主从切换之后,故障恢复的主节点,会转化成新主节点的从节点。这种自愈模式对提高可用性非常有帮助。

4.3.2 故障检测

通过《Redis 高可用架构之哨兵模式 - Sentinel》,我们知道:哨兵通过监控、⾃动切换主库、通知客户端实现故障⾃动切换, Cluster ⼜如何实现故障⾃动转移呢?

一个节点认为某个节点宕机不能说明这个节点真的挂了,无法提供服务了。只有占据多数的实例节点都认为某个节点挂了,这时候 cluster 才进行下线和主从切换的工作。

Redis 集群节点采用 Gossip 协议 来广播信息:

  • 每个节点都会定期向其他节点发送 PING 命令,如果接受 PING 消息的节点在指定时间内没有回复 PONG,则会认为该节点失联了(PFail),则发送 PING 的节点就把接受 PING 的节点标记为主观下线。

  • 如果集群半数以上的主节点都将主节点 xxx 标记为主观下线,则节点 xxx 将被标记为客观下线,然后向整个集群广播,让其它节点也知道该节点已经下线,并立即对下线的节点进行主从切换。

4.3.3 主从故障转移

当一个从节点发现自己正在复制的主节点进入了已下线,则开始对下线主节点进行故障转移,故障转移的步骤如下:

  1. 如果只有一个 slave 节点,则从节点会执行 SLAVEOF no one 命令,成为新的主节点。

  2. 如果是多个 slave 节点,则采用选举模式进行,竞选出新的 Master

    • 集群中设立一个自增计数器,初始值为 0 ,每次执行故障转移选举,计数就会 +1。

    • 检测到主节点下线的从节点向集群所有 master 广播一条CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 消息,所有收到消息、并具备投票权的主节点都向这个从节点投票。

    • 如果收到消息、并具备投票权的主节点未投票给其他从节点(只能投一票),则返回一条 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 消息,表示支持。

    • 参与选举的从节点都会接收 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 消息,如果收集到的选票大于等于 (n/2) + 1 支持,n 代表所有具备选举权的 master,那么这个从节点就被选举为新主节点。

    • 如果这一轮从节点都没能争取到足够多的票数,则发起再一轮选举(自增计数器+1),直至选出新的 master。

  3. 新的主节点会撤销所有对已下线主节点的 slots 指派,并将这些 slots 全部指派给自己。

  4. 新的主节点向集群广播一条 PONG 消息,这条 PONG 消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。

  5. 新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。

跟哨兵类似,两者都是基于 Raft 算法来实现的,流程如图所示:

在这里插入图片描述

4.4客户端如何定位数据所在实例?

4.4.1 定位数据所在节点

Redis 中的每个实例节点会将自己负责的哈希槽信息通过 Gossip协议 广播给集群中其他的实例,实现了slots 分配信息的扩散。这样的话,每个实例都知道整个集群的哈希槽分配情况以及映射信息。

客户端想要快捷的连接到服务端,并对某个 Redis 数据进行快捷访问,一般是经过以下步骤:

  1. 客户端连接集群的任一实例,获取到 slots 与实例节点的映射关系,并将该映射关系的信息缓存在本地;

  2. 将需要访问的 Redis 信息的 key,经过 CRC16 计算后,再对 16384 取模得到对应的 slot 索引,返回所有 slots 与实例的映射信息;

  3. 通过 slot 的位置进一步定位到具体所在的实例,再发送请求到对应的实例上

在这里插入图片描述

4.4.2 重新分配哈希槽

哈希槽与实例之间的映射关系由于新增实例或者负载均衡重新分配导致改变了怎么办?

集群中的实例通过 Gossip 协议互相传递消息获取最新的哈希槽分配信息,但是,客户端⽆法感知。

Redis Cluster 提供了重定向机制:客户端将请求发送到实例上,这个实例没有相应的数据,该 Redis 实例会告诉客户端将请求发送到其他的实例上。

Redis 如何告知客户端重定向访问新实例呢?

分为两种情况:MOVED 错误、ASK 错误。

(1)MOVED 错误

MOVED 错误(负载均衡,数据已经迁移到其他实例上):当客户端将⼀个键值对操作请求发送给某个实例,⽽这个键所在的槽并⾮由⾃⼰负责的时候,该实例会返回⼀个 MOVED 错误指引转向正在负责该槽的节点。

GET redis:pointer
(error) MOVED 16330 192.168.0.1:6379

该响应表示客户端请求的键值对所在的哈希槽 16330 迁移到了 192.168.0.1 这个实例上,端⼝是 6379。这样客户端就与 192.168.0.1:6379 建⽴连接,并发送 GET 请求。

同时,客户端还会更新本地缓存,将该 slot 与 Redis 实例对应关系更新正确。

在这里插入图片描述

(2)ASK 错误

如果某个 slot 的数据⽐较多,部分迁移到新实例,还有⼀部分没有迁移怎么办?

如果请求的 key 在当前节点找到就直接执⾏命令,否则时候就需要 ASK 错误响应,槽部分迁移未完成的情况下,如果需要访问的 key 所在 slot 正在从 实例1 迁移到 实例2,实例1 会返回客户端⼀条 ASK 报错信息:客户端请求的 key 所在的哈希槽正在迁移到 实例2 上,先给 实例2 发送⼀个 ASKING 命令,接着发送操作命令。

GET redis:pointer
(error) MOVED 16330 192.168.0.1:6379

⽐如客户端请求定位到 key = redis:pointer 的槽 16330 在实例 192.168.0.1 上,节点1 如果找得到就直接执⾏命令,否则响应 ASK 错误信息,并指引客户端转向正在迁移的⽬标节点 192.168.0.1。

在这里插入图片描述

注意:ASK 错误指令并不会更新客户端缓存的哈希槽分配信息。

所以客户端再次请求 slot 16330 的数据,还是会先给 192.168.0.1 实例发送请求,只不过节点会响应 ASK 命令让客户端给新实例发送⼀次请求。MOVED 指令则更新客户端本地缓存,让后续指令都发往新实例。

参考资料:https://redis.io/topics/cluster-spec、https://redis.io/commands/cluster-setslot、 https://github.com/go-redis/redis/blob/master/cluster.go。

4.5 ⽤表保存键值对和实例的关联关系可⾏么?

Redis Cluster ⽅案通过哈希槽的⽅式把键值对分配到不同的实例上,这个过程需要对键值对的 key 做 CRC 计算并对哈希槽总数取模映射到实例上。如果⽤⼀个表直接把键值对和实例的对应关系记录下来(例如键值对 1 在实例 2 上,键值对 2 在实例 1 上),这样就不⽤计算 key 和哈希槽的对应关系了,只⽤查表就⾏了,Redis 为什么不这么做呢?

使⽤⼀个全局表记录的话,假如键值对和实例之间的关系改变(重新分⽚、实例增减),需要修改表。如果是单线程操作,所有操作都要串⾏,性能太差。多线程的话,就涉及到加锁,另外,如果键值对数据量⾮常⼤,保存键值对与实例关系的表数据所需要的存储空间也会很⼤。

⽽哈希槽计算,虽然也要记录哈希槽与实例时间的关系,但是哈希槽的数量少得多,只有 16384 个,开销很⼩。

5. 集群可以设置多⼤?

Redis Cluster 可以⽆限⽔平拓展么?

答案是否定的,Redis 官⽅给的 Redis Cluster 的规模上线是 1000 个实例。

关键在于实例间的通信开销,Cluster 集群中的每个实例都保存所有哈希槽与实例对应关系信息(slot 映射到节点的表),以及⾃身的状态信息。

在集群之间每个实例通过 Gossip协议 传播节点的数据, Gossip协议 ⼯作原理⼤概如下:

  1. 从集群中随机选择⼀些实例按照⼀定的频率发送 PING 消息发送给挑选出来的实例,⽤于检测实例状态以及交换彼此的信息。 PING 消息中封装了发送者⾃身的状态信息、部分其他实例的状态信息、slot 与实例映射表信息;

  2. 实例接收到 PING 消息后,响应 PONG 消息,消息包含的信息跟 PING 消息⼀样。

集群之间通过 Gossip协议 可以在⼀段时间之后每个实例都能获取其他所有实例的状态信息。所以在有新节点加⼊,节点故障,slot 映射变更都可以通过 PING、PONG 的消息传播完成集群状态在每个实例的传播同步。

5.1 Gossip 消息

发送的消息结构是 clusterMsgDataGossip 结构体组成:

typedef struct {
	char nodename[CLUSTER_NAMELEN]; //40字节
	uint32_t ping_sent; //4字节
	uint32_t pong_received; //4字节
	char ip[NET_IP_STR_LEN]; //46字节
	uint16_t port; //2字节
	uint16_t cport; //2字节
	uint16_t flags; //2字节
	uint32_t notused1; //4字节
} clusterMsgDataGossip

所以每个实例发送⼀个 Gossip 消息,就需要发送 104 字节。如果集群是 1000 个实例,那么每个实例发送⼀个 PING 消息则会占⽤⼤约 10KB。

除此之外,实例间在传播 slot 映射表的时候,每个消息还包含了 ⼀个⻓度为 16384 bit 的 Bitmap。每⼀位对应⼀个 slot,如果值 = 1 则表示这个 slot 属于当前实例,这个 Bitmap 占⽤ 2KB,所以⼀个 PING 消息⼤约 12KB。

PONGPING 消息⼀样,⼀发⼀回两个消息加起来就是 24 KB。集群规模的增加,⼼跳消息越来越多就会占据集群的⽹络通信带宽,降低了集群吞吐量。

5.2 实例的通信频率

发送 PING 消息的频率会影响集群带宽么?

Redis Cluster 的实例启动后,默认会每秒从本地的实例列表中随机选出 5 个实例,再从这 5 个实例中找出⼀个最久没有收到 PING 消息的实例,把 PING 消息发送给该实例。

随机选择 5 个,但是⽆法保证选中的是整个集群最久没有收到 PING 通信的实例,有的实例可能⼀直没有收到消息,导致他们维护的集群信息早就过期了,该怎么办呢?

Redis Cluster 的实例每 100ms 就会扫描本地实例列表,当发现有实例最近⼀次收到 PONG 消息的时间 > cluster-node-timeout / 2 ,那么就⽴刻给这个实例发送 PING 消息,更新这个节点的集群状态信息。

当集群规模变⼤,就会进⼀步导致实例间⽹络通信延迟怎加。可能会引起更多的 PING 消息频繁发送。

如何降低实例间的通信开销?

  • 每个实例每秒发送⼀条 PING 消息,降低这个频率可能会导致集群每个实例的状态信息⽆法及时传播。

  • 每 100ms 检测实例 PONG 消息接收是否超过 cluster-node-timeout / 2 ,这个是 Redis 实例默认的周期性检测任务频率,不会轻易修改。

所以,只能修改 cluster-node-timeout 的值:集群中判断实例是否故障的⼼跳时间,默认 15s。为了避免过多的⼼跳消息占⽤集群宽带,将 cluster-node-timeout 调成 20s 或者 30s,这样 PONG 消息接收超时的情况就会缓解。

但是,也不能设置的太⼤。否则:一旦实例发⽣故障,就要等待 cluster-node-timeout 时⻓才能检测出这个故障,影响集群正常服务

参考资料:Cluster 集群能支撑的数据有多大?、深入分析Cluster 集群模式

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学术期刊《广西物理》简介及投稿要求

学术期刊《广西物理》简介及投稿要求 《广西物理》&#xff08;季刊&#xff09;创刊于1980年&#xff0c;是由广西师范大学&#xff1b;广西物理学会主办的物理杂志。本刊报道与物理有关的基础研究、应用研究以及与此有关的交叉学科研究领域的最新重要研究成果和发展趋势&…

编码与加密基础笔记

文章目录&#x1f449;1、ASCII 编码&#x1f449;2、了解Base64&#x1f449;3、MD5消息摘要算法&#x1f449;4、对称加密与 AES&#x1f449;5、非对称加密与 RSA参考书籍《Python 3 反爬虫原理与绕过实战》&#x1f449;1、ASCII 编码 ASCII编码实际上约定了字符串和二进制…

Python中使用matplotlib时显示中文乱码_(或更改字体)

一、问题描述 在使用matplotlib绘制可视化图表时&#xff0c;图表的中文显示乱码&#xff0c;只能正常显示英文内容&#xff0c;如下图所示&#xff1a; 二、问题分析 一般显示乱码是由于编码问题导致的&#xff0c;而matplotlib 默认使用ASCII 编码&#xff0c;但是当使用pypl…

全语言通用的ASCIL表讲解,这一篇就够了

目录 ASCII码诞生背景 ASCII码特性 可显示字符 大佬们可以看这个 小白们看这个更详细 对控制字符的解释 ASCII码诞生背景 在计算机中&#xff0c;所有的数据在存储和运算时都要使用二进制表示。例如&#xff0c;像a、b、c、d这样的52个字母&#xff08;包括大写&#xf…

Winnolin 绘制药时曲线图C-T

文章目录前言一、各受试者C-T图1.导入数据2.设置-运行2.查看结果&#xff0c;修改参数二、各制剂C-T图1.导入数据2.设置-运行2.查看结果&#xff0c;修改参数三、平均C-T图1.计算统计量2.设置统计量计算参数&#xff08;Set Up&#xff09;3.绘图XY Plot4.查看结果&#xff0c;…

Java多线程基础面试总结(三)

线程的生命周期和状态 Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态&#xff1a; NEW&#xff1a;初始状态&#xff0c;线程被创建出来&#xff0c;但是还没有调用start()方法。RUNABLE&#xff1a;运行中状态&#xff0c;调用了start()…

Java设计模式 11-代理模式

代理模式 一、 代理模式(Proxy) 1、代理模式的基本介绍 代理模式&#xff1a;为一个对象提供一个替身&#xff0c;以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是: 可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。被代理的对象…

时间序列的平稳性

如何检查时间序列是否平稳&#xff0c;如果它是非平稳的&#xff0c;我们可以怎么处理 当未来的数据与现在相似时&#xff0c;它更容易建模。平稳性描述了时间序列的统计特征不随时间变化的概念。因此一些时间序列预测模型&#xff0c;如自回归模型&#xff0c;依赖于时间序列…

IoC 之 Spring 统一资源加载策略【Spring源码】

《JavaPub源码》 文末是系列文章 IoC 之 Spring 统一资源加载策略 Spring 框架的核心是 IoC&#xff08;Inversion of Control&#xff09;&#xff0c;它将应用程序的对象依赖关系管理和控制反转到容器中。在 Spring IoC 容器中&#xff0c;组件的创建和配置是通过外部配置…

IDEA 运行启动 pulsar-manager项目

IDEA 运行 pulsar-manager项目&#xff08;gradle&#xff09; 1、下载pulsar-manager源码 giithub地址 smn-manager 2、将项目导入IDEA并初始化项目 问题&#xff1a;SSL peer shut down incorrectly 将https改成http之后又会出现 Server returned HTTP response code: …

服务(第四篇)Apache的网页优化

一、网页压缩 ①首先检查是否安装 mod_deflate 模块 ②如果没有安装mod_deflate 模块&#xff0c;重新编译安装 Apache 添加 mod_deflate 模块 yum -y install gcc gcc-c pcre pcre-devel zlib-devel cd /opt/httpd-2.4.29/ ./configure \ --prefix/usr/local/httpd \ --enabl…

HDFS学习笔记 【Namenode/DN管理】

说明 DN管理管理了什么&#xff1f; NN上如何表示DN DN存储和块的关系 梳理DatanodeManager存储类 DatanodeDescriptor DN的抽象&#xff0c;依次继承。每一层增加一点额外的信息。 DatanodeId 基本的DN信息&#xff0c;hostname&#xff0c;数据传输接口&#xff0c;info服…

QTableView 设置selection-background-color和border不同时生效问题记录

问题&#xff1a; qtableview在使用过程种设置qss样式&#xff0c;设置选中时的背景色&#xff0c;以及边框颜色&#xff0c;不能同时生效。 解决&#xff1a; 在qss中设置QTableView的样式时&#xff0c;对于item项&#xff0c;selection-background-color的参数设置应该分…

在将公司“一拆六”后,阿里巴巴未来将释放出哪些投资价值?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 阿里巴巴为何要将公司拆分为六大业务集团 3月28日&#xff0c;阿里巴巴集团董事会主席兼首席执行官张勇发布全员信&#xff0c;宣布启动“16N”组织变革&#xff0c;将公司拆分为六大业务集团和多家业务分公司。 在阿里巴巴…

关于FPGA(Vivado)后仿真相关问题的探讨

FPGA后仿真时&#xff0c;相比于功能仿真增加了门延时和布线延时&#xff0c;相对于门级仿真增加了布线延时&#xff0c;因此后仿真相比于功能仿真具有不同的特点。 下面所示的代码在功能仿真时是正确的的&#xff0c;但在后仿真时&#xff0c;似乎是有问题的。功能很简…

大数据项目组-月度考核汇报0102

目录 01-2023年02月-月度考核汇报 2月份完成项目情况 2月份学习情况 3月份学习计划 老师点评 02-2023年03月-月度考核汇报 项目完成情况 本月学习内容 下月学习计划 老师点评 01-2023年02月-月度考核汇报 2月份完成项目情况 MySQL数据同步到ElasticSearch任务进展&a…

linux shell 操作二进制文件(xxd、dd)

1&#xff0c;生成一个二进制文件 dd 工具 # 全零 二进制文件 dd if/dev/zero of1.bin bs1 count1024#全0xff tr \000 \377 < /dev/zero | dd ofall_0xff.bin bs1 count1024 > /dev/null xxd 工具&#xff1a;只能改单个地址 # echo "0x123" | xxd -r – xx…

【华为od2023-C++版】字符串重新排列、字符串重新排序

华为od机试题C2023个人练习使用 字符串重新排列、字符串重新排序 题目描述 给定一个字符串s&#xff0c;s包括以空格分隔的若干个单词&#xff0c;请对s进行如下处理后输出:1、单词内部调整:对每个单词字母重新按字典序排序Q 2、单词间顺序调整: 1)统计每个单词出现的次数&a…

算法刷题日志

今天是星期几就加上多少天在最后 public class Main {public static void main(String[] args) {System.out.println(Math.pow(20, 22) % 7 6);} }这题是判断左右回文&#xff0c;且要保持单调性&#xff0c;因为回文数左右对称所以只需要判断左边是否单调递增。 public class…

模拟信号隔离放大器变送器 导轨安装DIN11 IPO EM系列

概述&#xff1a; 导轨安装DIN11 IPO EM系列模拟信号隔离放大器是一种将输入信号隔离放大、转换成按比例输出的直流信号混合集成电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要电量隔离测控的行业。该模块内部嵌入了一个高效微功率的电源&#xff0…