Pulsar官方文档学习笔记——消息机制
pulsar
基于3.x最新官方文档学习记录
概念与架构
典型的推送订阅模式。生产者发送消息,消费者订阅topic消费信息并回应ACK。订阅创建后,Pulsar会保留所有消息。仅消息被所有订阅 成功消费了才会丢弃(可以配置消息保留机制保留一定量) 而且还可以重新给broker投递重新消费
消息
消息是pulsar传递的基本单元。有如下元素组成
组成成分 | 描述 |
---|---|
value/data payload | 消息携带的数据 |
key | 消息的键或分区键。消息可以用键标记,对于topic压缩有用 |
properties | 消息属性。key-value对的map组成 |
producer name | 生产者名 |
topic name | topic名称 |
schema version | 生产消息所用的schema版本 |
sequence ID | 每个消息在自己的topic里都有一个有序的序列id,由生产者赋值。ID可以用于去重。如果brokerDeduplicationEnabled设置为true。那么每个消息的sequencee id在主题里是唯一的 |
message id | bookies赋值的,持久化的消息id。在pulsar集群中是唯一的 |
publish time | 消息发布时间戳,生产者自动赋值的 |
event time | 一个应用程序附加到消息的可选时间戳信息。(业务一半也很少用,自己在消息里用一个字段就完了) |
消息有默认大小5MB。可以通过配置修改
-
In the
broker.conf
file.# The max size of a message (in bytes). maxMessageSize=5242880
-
In the
bookkeeper.conf
file.# The max size of the netty frame (in bytes). Any messages received larger than this value are rejected. The default value is 5 MB. nettyMaxFrameSizeBytes=5253120
响应
当应用消费并处理完消息后应该回复一个ack代表改消息消费成功。消息会在所有订阅消费完后删除。当然可以配置消息保留策略保留一定量的消息。对于批量的信息,也可以批量ACK
ack方式
- 单独确认
仅确认选择的消息
consumer.acknowledge(msg);
-
累计确认
确认后,该消息之前的消息不会再消费到。但是注意 这个不能用再shared和key_shared 订阅类型。因为这种订阅类型下有多个消费者
consumer.acknowledgeCumulative(msg);
NACK
NACK机制,消费者可以通知broker自己没有处理该消息,需要重新消费。broker会将该消息重新投递给consumer消费
- 在独占和故障转移订阅下,只能nack最近一条消息
- 在share和key_shared下可以选择nack某一条消息
对有序订阅类型的订阅(独占,key_shared) nack会导致乱序
可以设置重新投递次数以及投递延迟
例如配置延时在1s~60s
Consumer<byte[]> consumer = pulsarClient.newConsumer().topic(topic).subscriptionName("sub-negative-ack").subscriptionInitialPosition(SubscriptionInitialPosition.Earliest).negativeAckRedeliveryBackoff(MultiplierRedeliveryBackoff.builder().minDelayMs(1000).maxDelayMs(60 * 1000).multiplier(2) // 重试延迟乘数.build()).subscribe();
消息重新投递和投递延迟如下
Redelivery count | Redelivery delay |
---|---|
1 | 1 seconds |
2 | 2 seconds |
3 | 4 seconds |
4 | 8 seconds |
5 | 16 seconds |
6 | 32 seconds |
7 | 60 seconds |
8 | 60 seconds |
如果启用了批处理,那么一批数据都会重新投递
ack timeout
默认关闭。超时机制,设置客户端跟踪 消费的时间,如果超过时间限制,会给broker回nack触发重新 投递
可以配合重新投递的设置使用
consumer.ackTimeout(10, TimeUnit.SECOND).ackTimeoutRedeliveryBackoff(MultiplierRedeliveryBackoff.builder().minDelayMs(1000).maxDelayMs(60 * 1000).multiplier(2).build());
The message redelivery behavior should be as follows.
Redelivery count | Redelivery delay |
---|---|
1 | 10 + 1 seconds |
2 | 10 + 2 seconds |
3 | 10 + 4 seconds |
4 | 10 + 8 seconds |
5 | 10 + 16 seconds |
6 | 10 + 32 seconds |
7 | 10 + 60 seconds |
8 | 10 + 60 seconds |
注意:
-
如果启用批处理,那么一批数据都会重新投递
-
自己单独NACK比超时NACK更可取。超时值不好设置,容易重复消费不需要的消息
Retry letter topic
重试队列 用来存储消费失败的消息,并且稍后重试消费。用户可以自定义重试延迟时间。重试队列重试次数超过阈值后,消息就回到死信队列了。
重试队列消息有一些特殊proerties
REAL_TOPIC = persistent://public/default/my-topic # 源topic
ORIGIN_MESSAGE_ID = 1:0:-1:0 # 原始Message ID
RECONSUMETIMES = 6 # 重试次数
DELAY_TIME = 3000 # 重试间隔
重试队列与延迟投递目的是不一样的,重试队列主要是为了处理失败的消息。延迟投递则是想要在指定时间消费消息
重试队列默认名字<subscriptionname>-RETRY
,官方不推荐用。因为如果同一命名空间下的topicx消费有多相同订阅名,那么不同topic他的重试队列名字会是一样的。会导致互相消费
重试队列操作
Map<String, String> customProperties = new HashMap<String, String>();
customProperties.put("custom-key-1", "custom-value-1");
customProperties.put("custom-key-2", "custom-value-2");
consumer.reconsumeLater(msg, customProperties, 3, TimeUnit.SECONDS);
比起nack。重试队列更适合大量重新消费的场景 。重试丢列的消费会持久化到bookie,而nack只会缓存到客户端
dead letter topic
死信队列里一般存储了消费失败的消息。客户可以自定义如何处理这些失败的消息。例如存储到ES里供后面查询,指标监控等
Consumer<byte[]> consumer = pulsarClient.newConsumer(Schema.BYTES).topic("my-topic").subscriptionName("my-subscription").subscriptionType(SubscriptionType.Shared).deadLetterPolicy(DeadLetterPolicy.builder().maxRedeliverCount(maxRedeliveryCount).deadLetterTopic("my-dead-letter-topic-name").build()).subscribe();
死信队列默认格式为<subscriptionname>-DLQ
与重试队列一样,建议是自定义topic名字
压缩
pulsar支持消息压缩。lz4 zlib zstd snappy都行。比较推荐启用
batching
批处理开启后,生产者会累计发送 。此时backlog siez 代表该批次总数而不是消息总数。批次也会作为一个单元进行存储。
一般来说,该批次所有消息被确认成功则该批次 确认成功,否则认为失败进行重新投。但pulsar 2.6后就有批量确认。可以将当前索引之前的消息 都Ack了。
chunking
分块,Pulsar可以通过分块来处理大消息。当消息分块启用(对持久化topic才生效),当消息超过指定大小 maxMessageSize
消息将会被如下处理。消息结尾默认为OFF
- 将源消息拆分,并将他们与分块元数据(chunked metadata)按顺序发送
- broker会将分块的消息存储在一个ledgere中。并用chunkedMessageRate参数来记录该主题分块消息速率。
- 消费者会缓存所有消息的分块并聚合到接收队列中
- 从接受队列消费消息
注意:
分块和批处理不能同时开启
消费示例
单个消费者消费连续 分块的消息
单个消费者消费乱序分块的消息
Topic
pulsar主题是将数据组织成流的单元。名称为一个特定结构的url
{persistent|non-persistent}://tenant/namespace/topic
Topic name component | Description |
---|---|
persistent / non-persistent | 标识主题类型,pulsar支持两种主题,持久化的和非持久化的。默认是持久化的 |
tenant | 租户名,pulsar多租户概念 |
namespace | 命名空间,每个租户都有多个命名空间 |
topic | topic名字,没什么别的含义 |
pulsar客户端如果生产或消费一个不存在的topic。pulsar会尝试建立。 但一般不推荐,Pulsar会变得不好维护。最好是部署脚本啥的提前键好,方便统计维护topic
namespace
命名空间是租户下对topic的逻辑分组
Subscriptions
订阅名。每个消费者去订阅topic的时候都需要有个订阅名(如果没有puslar也会默认创建一个)
订阅类型
-
独占exclusive
默认的消费方式。消费者独占该订阅名的消费
-
共享shared
多个消费者可以使用一个订阅名消费该topic。适合需要动态扩容的消费业务
-
灾备failover
主消费者断开后,消息的消费会交给队列中下一个消费者。对于分区的topic。新消费者可能会消费乱序
对于分区的topic.broker会按照优先级和消费者name字典序进行排序。代理尝试将分区平均分给具有最高优先级的消费者。
如果分区数小于消费者数,有如下情况。例如2个分区四个消费者。那么每个分区都会有一个激活的消费者消费和三个待消费的消费者
如果分区数大于消费者数。例如九个分区三个消费者。如下图,A负责P0 P3 P6 那么BC就是P0 P3 P6 候选消费的消费者。其余同理
对于未分区的topic。
topic比消费者少
topic比消费者多。例如 A消费 topic1和topic4 那么B就是topic1和topic4的候选
-
key共享key_shared
几个消费者共享消费,但是根据哈希key(可以自己指定,有几种)分流。相同key或ordering key只会 投递给同一个消费者无论如何重新投递。那么当有新消费者加入时,pulsar会记录当前已经读取的消息位置,只有当该位置前的消息都被ack了,才会给新消费者投递消息。那万一其他消费者卡住了怎么办,可以开启allowOutOfOrderDelivery放松下条件,只会有短暂的不符合key_shared的消费情况
key_shared 形势下得批处理。如果启用key_shared,要么关闭批处理,要么shengchanzhe 需要启用 key-based batching .起始就是给批次打key。给单条消息打key没啥用,默认得处理方法可能没办法将相同Key的数据打包到相同批次。而消费者消费时,会将第一条数据的key当作该批数据的key从而导致上下文错误
大致消费形式总结如下
订阅模式
按游标是否是持久型来划分
Subscription mode | Description | Note |
---|---|---|
Durable | 持久型游标,订阅重启,broker重启后会从最近消费的消息消费 | 默认的订阅模式 |
NonDurable | 非持久型游标,broker重启后游标会丢失 | 读者的订阅模式本质上是非持久的,因为他无法阻止topic数据的删除 |
多topic订阅
- 正则形式
persistent://public/default/finance-.*
- 列表形式
topic分区
单分区的topic只会被一个broker持有,这限制了该topic的吞吐量。 分区可以将topic分布给多个broker。从而提高吞吐量
topic分区会均匀分布在集群broker上。分区topic(只能由admin api创建。分区数需要在创建topic时指定)和普通topic工作方式没啥区别。
路由方式
当推送消息给分区的topic时,必须指定路由模式,这决定了该消息推给哪个分区
当前有三种消息路由方式
Mode | Description |
---|---|
RoundRobinPartition | 如果没有提供key,那么生产者以轮询 的方式在分区上发布消息。但这个轮询不是指针对单个消息。而是设置成一个相同 的批处理延迟边界,一批一批的发给不同分区,确保批处理有效。如果消息有key,那么就会按key散列给不同分区 |
SinglePartition | 如果消息没key,那么就随机一个分区发送。如果指定key,那么就会散列到特定分区 |
CustomPartition | 自定义路由分区,通过重写客户端接口实现(java的话是MessageRouter) |
顺序保证
消息的顺序和路由方式以及msg的key有关,通常情况下,用户希望每个分区保持顺序
如果msg有key,那么 在使用RoundRobin和single模式时候,消息 都会根据哈希(JavaStringHash, murmur3_32Hash,推荐是用后者)路由到特定分区
消息顺序
rdering guarantee | Description | Routing Mode and Key |
---|---|---|
Per-key-partition | 所有 相同key的消息 会在一个分区按顺序排列 | 使用RoundRobin和single模式并提供key |
Per-producer | 从同一个生产者出来的消息会按序排列 | 需要使用single模式并且消息不附加key |
非持久topic
默认情况下,Pulsar会持久化所有没ack的消息。消息 会交给BookKeeper bookies存储。 但pulsar也提供非持久化的 topic。一旦broker挂了或者订阅挂了,期间的消息都找不回来
格式
*non-persistent*://tenant/namespace/topic
非持久化topic一系列行为都只基于内存。非持久化的topic也不会持久化到zk,意味着该元数据zk是不知道的。如果对应broker挂了,非持久化的topic不会分给新的broker。解决方案是将allowAUtoTopicCreation
设置为true,allowAutoTOpicCreationTYpe
设置为non-partitioned
性能
因为持久化topic需要存磁盘,存状态等操作,总之会比非持久化的topic性能差一些
client api
PulsarClient client = PulsarClient.builder().serviceUrl("pulsar://localhost:6650").build();
String npTopic = "non-persistent://public/default/my-topic";
String subscriptionName = "my-subscription-name";Consumer<byte[]> consumer = client.newConsumer().topic(npTopic).subscriptionName(subscriptionName).subscribe();
system topic
system topic 主要用于实现某些功能并消除对第三方组件的依赖。例如心跳检测,事务,主题策略,资源组服务等。以心跳检测为例子 ,系统主题进行健康检查 ,可以让生产者,消费者生产/读取heartberat ns下的消息来探测服务是否存活
Namespace | TopicName | Domain | Count | Usage |
---|---|---|---|---|
pulsar/system | transaction_coordinator_assign_${id} | Persistent | Default 16 | 事务协调 |
pulsar/system | __transaction_log_${tc_id} | Persistent | Default 16 | 事务日志 |
pulsar/system | resource-usage | Non-persistent | Default 4 | 资源组服务 |
host/port | heartbeat | Persistent | 1 | 心跳检测 |
User-defined-ns | __change_events | Persistent | Default 4 | topic相关事件 |
User-defined-ns | __transaction_buffer_snapshot | Persistent | One per namespace | 事务缓存快照 |
User-defined-ns | ${topicName}__transaction_pending_ack | Persistent | 每个订阅有事务的都会有一个 | 事务ack管理 |
消息重新投递
看前面ack、nack、ack timeout 和重试队列
消息保留和过期
默认情况情况下会立即删除消费者已确认过的消息,并将未确认的消息持久化在消息积压中。不过puslar可以设置更改这种行为。pulsar中的消息保留有两种定义,一种用于非积压消息的持久化。一种用于积压的消息
在puslar中 ,可以设置两种 方式进行消息保留(命名空间级)
- 进行消息的持久化存储,可以存储 已经ack的消息(针对已ack数据,保留X小时Y大小的数据)
- 设置消息TTL,过期数据丢弃(针对未ack的数据,ACK)
消息保留策略
看这两张图就知道了 。深蓝色是还在保留范围内的数据。浅蓝是不在保留范围内的数据,可以删除的 。白色是 未ack积压的数据
开启消息保留 的时候,必须设置默认的大小限制(defaultRetentionSizeInMB)和时间限制(defaultRetentionTimeInMinutes)
Time limit | Size limit | Message retention |
---|---|---|
-1 | -1 | 无限制 保留 |
-1 | >0 | 在范围内保留 |
>0 | -1 | 在范围内保留 |
0 | 0 | 不开启消息保留(默认 ) |
0 | >0 | Invalid |
>0 | 0 | Invalid |
>0 | >0 | 超过一个就丢 |
当然也可以手动设置 topic下消息的保留期限和大小
int retentionTime = 10; // 10 minutes
int retentionSize = 500; // 500 megabytes
RetentionPolicies policies = new RetentionPolicies(retentionTime, retentionSize);
admin.namespaces().setRetention(namespace, policies);
积压配额
backlogs是用来存未ACK数据的。pulsar默认会存储所有 未ACK数据。你也可以控制存储数据的大小和时间。pulsar用配额来限制backlog
该图展示了pulsar如何限制backlog的数据。超过backlog配额的会启用一定消息保留策略。策略如下
Policy | Action |
---|---|
producer_request_hold | 超出配额时生产者会保留消息重试直到超出客户端配置的sendTimeoutMs |
producer_exception | 发消息时抛异常,告知已经超出配额 |
consumer_backlog_eviction | 超出配额时broker开始丢弃积压数据 |
设置积压配额
admin.namespaces().setBacklogQuota(namespace, BacklogQuota.builder().retentionPolicy(RetentionPolicy.producer_request_hold).limitSize(2147483648L).limitTime(60 * 60).build());
TTL
默认情况下,puslar会持久化所有未ack的数据。但可以设置TTL来决定什么时候丢弃未ack的数据
pulsar-admin namespaces set-message-ttl my-tenant/my-ns \
--messageTTL 120 # TTL of 2 minutes
admin.namespaces().setNamespaceMessageTTL(namespace, ttlInSeconds);
消息去重
当消息被持久化多次时会进行去重。确保消息在磁盘只存一次,即使该消息被生产者重复发送。
前两个图是没开启去重,后两个图是开启去重。消息去重有broker层级,ns层级和topic层级
该功能默认是关闭的。如果启用,建议生产者无限尝试发送消息。将sendTImeout配置为0
生产者幂等性
该方式也是消息去重的一种。意味着每条消息仅生成一次。缺点是会将重复数据删除的工作推到应用程序。
重复数据删除和effectively-once语义
消息 重复数据删除使pulsar成为理想的消息传递系统,可以与流处理引擎和其他要提供一次有效处理语义的系统结合使用
消息延迟传递
消息延迟传递可以让消费者延迟一定时间 再消费到消息 。在这个机制中 ,消息存在bookkeeper中,消息发到broker后,DelayedDeliveryTracker在内存中维护时间索引。(timemessageId) 一旦指定延迟结束,消息就会传递给消费者(只能在shared可key-shared订阅使用)。该机制默认启用
注意:
- 在消息保留机制下,pulsar会 删除 topic前面的ledger(可以理解为一个存储单元), 但不会删除中间的ledgere。意味着如果你发了一条延迟很长的消息。即使该消息后面的消息都被消费了(到期被消费)。由于这条消息卡在中间,那么后面的消息对应的ledger都不会被删除
- 在启用积压配额的机制下,如果超过配额依旧会触发对应的消息保留策略
- 在启用TTL机制下,消息到期时,即使是延迟消息也会被删除
相关文章:

Pulsar官方文档学习笔记——消息机制
pulsar 基于3.x最新官方文档学习记录 概念与架构 典型的推送订阅模式。生产者发送消息,消费者订阅topic消费信息并回应ACK。订阅创建后,Pulsar会保留所有消息。仅消息被所有订阅 成功消费了才会丢弃(可以配置消息保留机制保留一定量&#…...

PyTorch--残差网络(ResNet)在CIFAR-10数据集进行图像分类
完整代码 import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms# Device configuration device torch.device(cuda if torch.cuda.is_available() else cpu)# Hyper-parameters num_epochs 80 batch_size 100 learning_rate…...

ETAS工具链自动化实战指南<一>
----自动化不仅是一种技术,更是一种思维方式,它将帮助我们在快节奏的工作环境中保持领先! 目录 往期推荐 场景一:SWC 之间 port自动连接 命令示例 参数说明 场景二:SWC与ECU 自动映射 命令示例 参数说明 场景三&…...

疫情期间我面试了13家企业软件测试岗位,一些面试题整理
项目的测试流程 拿到需求文档后,写测试用例 审核测试用例 等待开发包 部署测试环境 冒烟测试(网页架构图) 页面初始化测试(查看数据库中的数据内容和页面展示的内容是否一致,并且是否按照某些顺序排列)…...

PINCE——Linux 原生游戏内存修改器,一款替代 Cheat Engine 的强大游戏修改器,Linux 游戏玩家必备神器!
PINCE——Linux 原生游戏内存修改器,一款替代 Cheat Engine 的强大游戏修改器,Linux 游戏玩家必备神器! PINCE 是 GNU Project Debugger(GDB) 的前端/反向工程工具,常用作程序调试器,主要用于游戏领域,修改…...

为IntelliJ IDEA安装插件
安装插件 插件是开发工具的扩展程序,通常由第三方提供,当安装了插件后,原开发工作的菜单、按钮等开发环境可能会发生变化,例如出现了新的菜单项,或出现了新的按钮,甚至一些全新的编码方式,通常…...

ES6 Promise
ES6 Promise 对象 一、概述 是异步编程的一种解决方案。 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 Promise 状态 状态的特点 Promise 异步操作有三种状态:pending(进行中)、fulfilled(…...

html+css 实现hover 凹陷按钮
前言:哈喽,大家好,今天给大家分享html+css 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、原理解析💡1.这是一个,hover时凹陷的效果。每个按钮是一个button…...

什么是负载均衡?负载均衡器如何运作?
往期文章 负载均衡器:LVS、Nginx、HAproxy如何选择? 目录 往期文章什么是负载均衡?为什么需要负载均衡?负载均衡工作原理?静态负载均衡算法动态负载均衡算法 参考 什么是负载均衡? 负载均衡是一种网络技术…...

(Arxiv-2023)潜在一致性模型:通过少步推理合成高分辨率图像
潜在一致性模型:通过少步推理合成高分辨率图像 Paper Title: Latent Consistency Models: Synthesizing High-Resolution Images with Few-Step Inference Paper是清华发表在Arxiv 2023的工作 Paper地址 Code地址 ABSTRACT 潜在扩散模型 (LDM) 在合成高分辨率图像方…...

Unity与UE,哪种游戏引擎适合你?
PlayStation vs Xbox,Mario vs Sonic,Unreal vs Unity?无论是游戏主机、角色还是游戏引擎,人们总是热衷于捍卫他们在游戏行业中的偏爱。 专注于游戏引擎,Unity和Unreal Engine(简称UE4)是目前市…...

这五本大模型书籍,把大模型讲的非常详细,收藏我这一篇就够了
当然可以。在当前的大模型时代,随着自然语言处理(NLP)技术的迅速发展,出现了许多优秀的书籍来帮助读者理解这些复杂的技术。以下是几本值得推荐的大模型书籍,它们涵盖了从基础理论到高级实践的内容,可以帮助…...

伊朗通过 ChatGPT 试图影响美国大选, OpenAI 封禁多个账户|TodayAI
OpenAI 近日宣布,他们已经封禁了一系列与伊朗影响行动有关的 ChatGPT 账户,这些账户涉嫌利用该 AI 工具生成并传播与美国总统选举、以色列 – 哈马斯战争以及奥运会等相关的内容。 OpenAI 表示,这些账户与一个名为 “Storm-2035” 的秘密伊朗…...

windows系统如何走后面之windows系统隐藏账户
系统隐藏账户是一种最为简单有效的权限维持方式,其做法就是让攻击者创建一个新的具有管理员权限的隐藏账户,因为是隐藏账户,所以防守方是无法通过控制面板或命令行看到这个账户的。 自然我们需要一些前提条件,比如说有一个网站&am…...
Elasticsearch(ES)(版本7.x)数据更新后刷新策略RefreshPolicy
Elasticsearch(ES)(版本7.x)数据更新后刷新策略RefreshPolicy 介绍 ES数据写入后,默认1s后才会被搜索到(refresh_interval为1); 这样可能是考虑到性能问题,毕竟实时IO 消耗较多资源 造成的问题 例如一个索引现在有…...

【运维】从一个git库迁移到另一个库
工作目录: /home/java/hosts 10.60.100.194 脚本 hosts / hostsShell GitLab (gbcom.com.cn) 核心代码...

and design vue表格列宽度拖拽,vue-draggable-resizable插件使用
and design vue2版的table表格不能拖拽列的宽度,通过vue-draggable-resizable插件实现 我用的是and design 1.7.8的版本,先下插件 yarn add vue-draggable-resizable2.1.0我这版本的and design用最新3.0.0以上的插件会有问题,实现不了效果&a…...
使用hexo搭建个人博客
很早之前使用hexo和github建了个人博客。搭建的流程一直没有梳理,中间换过几次机器,每次都得重新配置一遍,需要重新学些。最近电脑坏了,原始的数据没有导出来,先把以前文章写个文件占个位置,后面慢慢补吧&a…...
java geotool构建地理点线面
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互…...
C# 中 Grpc服务端调用客户端方法
在 gRPC 中,服务端通常不直接调用客户端的方法,因为 gRPC 的设计模型是服务端提供服务,客户端调用服务。通常情况下,服务端和客户端之间是解耦的,服务端只提供服务端点,客户端通过这些端点发起请求。 不过…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...