当前位置: 首页 > article >正文

DAG账本项目学习总结(七):MySQL 持久化与 Redis 缓存机制源码解析

1. 上期回顾在第六期中我们分析了云端广播与交易确认机制。可以简单概括为融合终端生成交易 ↓ 写入本地 DAG 账本 ↓ 广播给 cloud 和其他 fusion ↓ cloud 插入全局账本 ↓ cloud 根据累计权重产生确认动作 ↓ 确认动作同步回各融合终端到这里为止我们已经看懂了项目的核心仿真逻辑设备注册、遥测上报、DAG 父节点选择、云端确认。这一期继续分析一个后端项目很重要的部分数据如何保存查询结果如何缓存服务重启后系统如何恢复2. 本期学习目标本期重点解决四个问题1. 项目中哪些数据会写入 MySQL 2. DAG 账本为什么采用“快照式持久化” 3. Redis 缓存了哪些接口结果 4. 写入操作后缓存为什么要失效本期重点涉及这些类LedgerStateStore DeviceSessionStore AsyncLedgerPersistenceCoordinator TransactionPersistenceMapper LedgerTransactionEntity DeviceSessionEntity RedisCacheConfig CacheConstant SimulationQueryServiceImpl SimulationCommandServiceImpl SimulationRuntimeContext3. MySQL 和 Redis 在项目中的分工这个项目不是纯内存仿真而是同时使用了 MySQL 和 Redis。可以简单理解为MySQL保存系统状态支持服务重启后恢复 Redis缓存查询结果提高高频读接口响应速度MySQL 主要保存两类数据ledger_transactions账本交易快照 device_sessions设备会话信息Redis 主要缓存查询接口结果例如health topology cloud ledger fusion list fusion ledger device list这两个组件的作用并不相同MySQL 解决“数据不能丢”的问题 Redis 解决“查询不要每次都重新组装”的问题。4. 账本持久化的核心类LedgerStateStore账本持久化主要由LedgerStateStore完成。这个类主要提供三个方法hasTerminalSnapshot(terminalId) loadLedger(terminalId) replaceLedger(terminalId, transactions)它的作用可以理解为检查某个 terminal 是否已有账本快照从 MySQL 加载某个 terminal 的账本用新的交易集合替换某个 terminal 的账本快照。其中replaceLedger()的逻辑是先删除某个 terminal 原有的账本记录再把当前内存中的交易集合重新保存进去。这个方法上使用了Transactional说明删除旧快照和保存新快照属于同一个事务过程。也就是说这个项目不是每生成一笔交易就单独插入一条增量记录而是采用了“账本快照替换”的方式。5. 什么是账本快照式持久化快照式持久化可以这样理解某个 terminal 当前账本中有多少交易 就把这些交易整体作为该 terminal 的最新账本状态保存到 MySQL。例如fusion1当前账本中有G1、G2、R1、B1、B2那么持久化时MySQL 中fusion1对应的旧交易记录会被删除然后保存这 5 条最新交易记录。它的流程类似读取内存账本 ↓ 复制交易集合 ↓ 删除 MySQL 中该 terminal 的旧快照 ↓ 保存新的交易集合 ↓ flush 到数据库这种方式的好处是逻辑简单恢复时也简单每个 terminal 只需要加载自己最新保存的一组交易即可。缺点也很明显如果账本很大每次替换整个快照的开销会比较高。因此这个实现更适合仿真系统或中小规模实验。如果是生产级系统后续可能要改成增量持久化或事件日志式持久化。6. 账本交易表ledger_transactionsLedgerTransactionEntity对应 MySQL 中的ledger_transactions表。这个实体类中包含了大量交易字段例如terminal_id tx_id tx_type source_terminal_id source_terminal_pubkey parent_ids_json timestamp_value created_round_value payload_hash terminal_signature device_id device_pubkey target_terminal_id attributes_json payload_json cumulative_weight_value status_value confirmed_at soft_prune_notified_at soft_pruned_at hard_pruned_at其中表上有一个唯一约束terminal_id tx_id这说明同一笔交易可以存在于不同 terminal 的账本中但在同一个 terminal 内不能重复保存同一个交易 ID。这个设计和项目的多节点账本模型是一致的cloud 有自己的账本快照 fusion1 有自己的账本快照 fusion2 有自己的账本快照 fusion3 有自己的账本快照。同一个tx_id可以出现在多个 terminal 的账本中因为它们分别代表不同节点看到的账本状态。7. TransactionPersistenceMapper领域对象和数据库实体的转换Transaction是核心领域对象LedgerTransactionEntity是数据库实体。二者之间的转换由TransactionPersistenceMapper完成。它主要提供两个方法toEntity(terminalId, transaction) toTransaction(entity)toEntity()负责把内存中的Transaction转成可以保存到数据库的实体toTransaction()负责从数据库实体恢复成内存中的Transaction。这里有一个细节parentIds、attributes、payload、tombstone等复杂字段不是拆成多张表而是被序列化成 JSON 字符串保存。例如parentIds → parent_ids_json attributes → attributes_json payload → payload_json tombstone → tombstone_json这样做让表结构比较简单也方便保存交易中的动态字段。尤其是payload本身就是一个 Map 结构直接保存为 JSON 比拆成很多列更灵活。8. 异步账本持久化AsyncLedgerPersistenceCoordinator如果每次注册设备或提交遥测数据后都在请求线程里同步写 MySQL那么接口响应会被数据库写入阻塞。所以项目引入了AsyncLedgerPersistenceCoordinator。这个类内部创建了一个单线程执行器ledger-persistence当系统需要保存账本时会调用persistLedgers(ledgerSnapshots)它不会在当前请求线程里直接写数据库而是把持久化任务提交给后台执行器。简化流程如下注册设备 / 提交遥测 ↓ 内存账本先更新 ↓ 收集 cloud 和各 fusion 的账本快照 ↓ 提交异步持久化任务 ↓ 请求可以继续返回 ↓ 后台线程慢慢写 MySQL这就是 README 中提到的“异步 MySQL 快照写入”。9. 异步持久化保存了哪些状态在SimulationRuntimeContext中持久化时会调用collectLedgerSnapshots()它会分别收集cloud 的交易集合 fusion1 的交易集合 fusion2 的交易集合 fusion3 的交易集合然后交给ledgerPersistenceCoordinator.persistLedgers(...)后台线程会遍历这些账本快照并调用LedgerStateStore.replaceLedger()保存每个 terminal 的账本。因此一次持久化并不是只保存当前产生交易的那个融合终端而是保存所有账本状态。可以理解为一次状态变化后 系统保存 cloud 所有 fusion 的最新账本视图。10. 异步持久化的状态监控AsyncLedgerPersistenceCoordinator还维护了一些统计字段submittedBatchCount completedBatchCount lastError latestTask并通过summary()返回mode async_mysql_snapshot submitted_batches completed_batches last_error这些信息会出现在系统的 storage summary 中用于查看异步持久化是否正常。可以理解为submitted_batches提交了多少次异步保存任务 completed_batches完成了多少次异步保存任务 last_error最近一次持久化错误如果测试时发现数据没有及时写入 MySQL可以优先看这些指标。11. 服务关闭前的 flush异步写入有一个常见风险任务还没写完服务就关闭了。为了解决这个问题AsyncLedgerPersistenceCoordinator中定义了shutdown()方法并使用了PreDestroy。关闭前它会调用flushLatestTask()也就是等待最近一次异步持久化任务完成然后再关闭执行器。这个设计可以降低服务关闭时丢失最新账本快照的风险。不过它也不是完整的数据库事务日志机制。它更适合当前仿真项目的需求保证大多数情况下服务关闭前能把最新快照写完。12. 设备会话持久化DeviceSessionStore除了账本交易项目还需要保存设备会话。为什么要保存设备会话因为设备注册后系统后续提交遥测数据时需要知道这个 deviceId 是否存在 它属于哪个 terminal 它的设备名称是什么 它的签名私钥和公钥是什么 它是否是 bootstrap 身份。这些信息由DeviceSessionStore保存。它提供两个主要方法loadAll() save(snapshot)save()会把设备会话快照保存成DeviceSessionEntityloadAll()会从数据库中读取所有设备会话并转成DeviceSessionSnapshot。13. 设备会话表device_sessionsDeviceSessionEntity对应数据库中的device_sessions表。其中保存了device_id device_name terminal_id sign_privkey sign_pubkey bootstrap_identity表上有一个唯一约束device_id也就是说一个设备 ID 在设备会话表中只能出现一次。这里需要注意一个安全问题该项目为了仿真方便把设备私钥sign_privkey也保存到了数据库中。这样服务重启后模拟设备仍然可以继续签名并提交遥测数据。从真实系统角度看设备私钥一般不应该由服务端保存但在这个项目中设备是由后端模拟出来的所以保存私钥是为了维持仿真连续性。14. 服务启动时如何恢复状态SimulationRuntimeContext初始化时会检查 cloud 是否已有账本快照cloudSnapshotRestored ledgerStateStore.hasTerminalSnapshot(cloud)如果存在快照说明之前系统运行过就会执行恢复流程restoreLedger(cloud, cloud) restoreLedger(fusion1, fusion1) restoreLedger(fusion2, fusion2) restoreLedger(fusion3, fusion3) restoreDeviceSessions()如果没有快照则说明是第一次启动系统会执行初始化同步syncInitialLedgers()也就是把初始 genesis 账本状态保存到 MySQL。所以项目启动流程可以理解为检查 MySQL 是否有 cloud 快照 ↓ 有从 MySQL 恢复 cloud 和 fusion 账本再恢复设备会话 ↓ 没有创建初始账本并写入初始快照15. 恢复账本时发生了什么恢复账本时SimulationRuntimeContext会调用LedgerStateStore.loadLedger(terminalId)从 MySQL 中按时间和交易 ID 顺序加载交易。然后对 cloud 和 fusion 分别恢复。cloud 恢复时会把非 genesis 交易插入 cloud 的 DAG 账本并写入 archivefusion 恢复时会把非 genesis 交易插入对应融合终端的 DAG 账本。可以简化成MySQL ledger_transactions ↓ TransactionPersistenceMapper.toTransaction() ↓ 恢复成 Transaction 对象 ↓ 插入 cloud / fusion 的 DagLedger这样服务重启后系统可以恢复之前的账本状态而不是每次都从空账本开始。16. Redis 缓存配置RedisCacheConfigRedis 缓存由RedisCacheConfig配置。它创建了一个CacheManager并指定key 使用 StringRedisSerializer value 使用 GenericJackson2JsonRedisSerializer 不缓存 null 值 默认过期时间 60 秒同时不同缓存项设置了不同 TTL。例如simulationHealth15 秒 simulationTopology30 秒 cloudLedger30 秒 fusionList60 秒 fusionLedger30 秒 deviceList30 秒这说明项目不是所有接口都用同一个缓存时间而是根据数据变化频率做了区分。17. 缓存名称集中管理CacheConstant缓存名没有散落在代码中而是集中定义在CacheConstant中simulationHealth simulationTopology cloudLedger fusionList fusionLedger deviceList这样做的好处是避免字符串写错方便统一修改缓存名查询缓存和写入清理缓存时可以共用同一组常量。CacheConstant是一个典型的小型常量类。18. 查询接口如何使用 Redis 缓存查询接口的缓存主要在SimulationQueryServiceImpl中。例如health() 使用 simulationHealth 缓存 topology() 使用 simulationTopology 缓存 cloudLedger() 使用 cloudLedger 缓存 listFusions() 使用 fusionList 缓存 fusionLedger(terminalId) 使用 fusionLedger 缓存并以 terminalId 作为 key listDevices() 使用 deviceList 缓存也就是说当用户多次请求相同查询接口时系统不一定每次都重新组装数据而是可以直接从 Redis 读取缓存结果。查询流程可以表示为GET /api/cloud/ledger ↓ 检查 Redis 是否有 cloudLedger 缓存 ↓ 有直接返回缓存 ↓ 没有调用 runtimeContext.cloudLedger() ↓ 组装 LedgerViewVO ↓ 写入 Redis ↓ 返回结果19. 写入操作为什么要清理缓存既然查询接口用了缓存那么写入操作后就必须清理缓存。例如注册设备后设备列表变了拓扑结构变了融合终端账本变了cloud 账本可能也变了health 里的设备数量也变了。如果不清理缓存用户可能会看到旧数据。因此SimulationCommandServiceImpl在注册设备和提交遥测数据时都使用了Caching(evict {...})一次性清理多个缓存simulationHealth simulationTopology cloudLedger fusionList fusionLedger deviceList这说明项目采用的是查询时缓存 写入后失效。而不是手动更新每个缓存。20. 注册设备时的持久化与缓存流程以设备注册为例完整流程可以总结为POST /api/fusions/fusion1/devices/register ↓ SimulationCommandServiceImpl.registerDevice() ↓ 清理相关 Redis 缓存 ↓ SimulationRuntimeContext.registerDevice() ↓ 创建设备模拟器 ↓ fusion1 生成 register 交易 ↓ 保存 DeviceSession 到 MySQL ↓ 广播 register 交易到 cloud 和其他 fusion ↓ 如果 autoConfirmtrue执行注册确认 ↓ collectLedgerSnapshots() ↓ AsyncLedgerPersistenceCoordinator.persistLedgers() ↓ 后台线程保存 cloud 所有 fusion 的账本快照 ↓ 返回注册结果这里同时发生了两类数据变化device_sessions 增加设备会话 ledger_transactions 更新各 terminal 账本快照。21. 提交遥测时的持久化与缓存流程遥测上报时流程类似POST /api/fusions/fusion1/devices/{deviceId}/telemetry ↓ SimulationCommandServiceImpl.submitTelemetry() ↓ 清理相关 Redis 缓存 ↓ SimulationRuntimeContext.submitTelemetry() ↓ 检查设备会话 ↓ 设备签名 ↓ 融合终端验签 ↓ 生成 business 交易 ↓ 广播到 cloud 和其他 fusion ↓ collectLedgerSnapshots() ↓ 异步保存账本快照到 MySQL ↓ 返回遥测提交结果和注册不同遥测上报一般不会新增设备会话但会更新账本交易状态所以仍然需要持久化账本快照也需要清理缓存。22. 整体数据流图可以把 MySQL 和 Redis 的整体作用画成下面这样写入请求 POST register / telemetry ↓ 修改内存状态 ↓ 更新 DagLedger / DeviceSession ↓ 清理 Redis 查询缓存 ↓ 异步写 MySQL 快照 ↓ 返回结果 查询请求 GET health / topology / ledger / devices ↓ 优先查 Redis ↓ 缓存命中直接返回 ↓ 缓存未命中读取内存状态 ↓ 组装 VO ↓ 写入 Redis ↓ 返回结果 服务重启 ↓ 从 MySQL 读取 ledger_transactions ↓ 恢复 cloud / fusion 账本 ↓ 从 MySQL 读取 device_sessions ↓ 恢复设备会话这个图基本覆盖了项目的数据管理逻辑。23. 当前实现的特点这一部分实现有几个明显特点。第一账本以 terminal 为单位保存快照。cloud、fusion1、fusion2、fusion3 各自都有自己的账本视图MySQL 里用terminal_id区分。第二账本持久化是异步的。写请求不会长时间等待 MySQL 保存所有账本快照减少了接口阻塞。第三设备会话是同步保存的。注册设备后设备会话会立即保存到 MySQL保证后续可以恢复设备模拟器。第四Redis 只缓存查询结果。写入操作不会依赖 Redis 保存核心状态核心状态仍然以内存和 MySQL 为主。第五写入后统一清理多个缓存。这样可以避免用户在注册或遥测提交后看到旧的 topology、ledger 或 device list。24. 这部分可以如何写进论文或项目说明如果把这部分对应到论文或系统设计说明中可以写成为保证仿真系统在服务重启后的状态恢复能力系统将云端节点与各融合终端的 DAG 账本状态以终端快照形式持久化至 MySQL。每次设备注册或业务数据提交后系统收集云端及各融合终端的账本副本并通过异步持久化线程将其写入数据库从而降低数据库写入对在线请求处理的阻塞。同时系统将设备会话信息独立保存用于恢复设备标识、密钥和接入域等仿真状态。在查询侧系统利用 Redis 对健康检查、拓扑结构、账本视图和设备列表等高频读接口进行短时缓存并在注册或遥测写入后统一失效相关缓存以保证查询结果与最新账本状态一致。如果写得更简洁可以写成系统采用 MySQL 保存账本快照和设备会话并利用 Redis 缓存高频查询结果。写入请求更新内存账本后异步落库同时清理相关缓存查询请求优先读取缓存未命中时再从运行时状态组装结果从而兼顾状态可恢复性与查询效率。25. 本期小结这一期分析了 MySQL 持久化与 Redis 缓存机制。可以总结为五点第一MySQL 主要保存ledger_transactions和device_sessions。第二账本采用按 terminal 区分的快照式持久化。第三账本快照写入由AsyncLedgerPersistenceCoordinator异步完成减少请求阻塞。第四服务重启时系统会从 MySQL 恢复 cloud、fusion 账本和设备会话。第五Redis 用于缓存高频查询接口写入操作后会清理相关缓存避免返回旧数据。

相关文章:

DAG账本项目学习总结(七):MySQL 持久化与 Redis 缓存机制源码解析

1. 上期回顾在第六期中,我们分析了云端广播与交易确认机制。可以简单概括为:融合终端生成交易↓ 写入本地 DAG 账本↓ 广播给 cloud 和其他 fusion↓ cloud 插入全局账本↓ cloud 根据累计权重产生确认动作↓ 确认动作同步回各融合终端到这里为止&#x…...

终极跨平台音频下载解决方案:喜马拉雅FM批量下载器完整指南

终极跨平台音频下载解决方案:喜马拉雅FM批量下载器完整指南 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 你是否经常…...

动态物理模拟中的碰撞处理:Pymunk中的球体大小变化

在物理模拟和游戏开发中,碰撞处理是一个常见但复杂的问题。特别是在使用像Pymunk这样的物理引擎时,如何正确地处理物体在碰撞后的行为(比如体积变化)显得尤为重要。本文将通过一个实际的例子,展示如何在Pymunk中实现一个球体在每次与地面或墙壁碰撞后,其半径增大的逻辑。…...

Chromatic深度解析:基于QuickJS的跨平台动态代码注入框架实现原理

Chromatic深度解析:基于QuickJS的跨平台动态代码注入框架实现原理 【免费下载链接】chromatic Universal modifier for Chromium/V8 | 广谱注入 Chromium/V8 的通用修改器 项目地址: https://gitcode.com/gh_mirrors/be/chromatic 你是否曾经遇到过这样的技术…...

别再只会用t检验了!用Python的statsmodels库做单因素方差分析,5分钟搞定A/B测试结果解读

用Python实现单因素方差分析:A/B测试中的多组比较实战指南 当产品经理同时测试三种新按钮颜色对转化率的影响时,连续做了三次t检验对比各组差异——这个在互联网公司会议室里反复上演的场景,实际上犯了一个统计学上的典型错误。就像用三把尺…...

AI视频翻译,正在改变视频出海

过去一年,“短剧/漫剧出海”几乎成为内容行业最热的方向之一。越来越多的团队开始把中文短剧搬到海外市场,包括:TikTokYouTubeReelShortDramaBoxLokShort海外短视频平台而在这个过程中,一个问题开始越来越明显:内容可以…...

面试官问KMP?别慌!用这道LeetCode 28题(实现strStr())现场给你讲明白

面试官问KMP?别慌!用这道LeetCode 28题(实现strStr())现场给你讲明白 当面试官在白板上写下"实现strStr()"这道题时,许多候选人的第一反应是暴力匹配——直到被追问"有没有更优解?"才意…...

2026.5.11:2026年5月TIOBE指数

2026年5月TIOBE指数 2026年5月TIOBE指数 五月头条:统计编程语言市场正在经历重大整合 本月,R 编程语言在 TIOBE 指数中再次攀升至第八位,追平了历史最高排名。这并非偶然。统计编程语言市场显然正在经历一场重大整合。Python 和 R 成为最大的赢家,而许多老牌语言则持续失去…...

ClawTick CLI:为AI Agent构建可靠任务调度与监控的实践指南

1. 项目概述:为AI Agent构建可靠的任务调度基础设施 如果你正在开发或使用AI Agent,无论是基于LangChain、CrewAI还是OpenClaw,迟早会遇到一个核心问题:如何让这些智能体定时、可靠地执行任务?自己写个定时脚本&#…...

天赐范式第37天:从手机端AI工具的疯狂质疑,到AI电脑端天赐范式的群策群力,为自身提供了源源不断的自驱动力

当3个AI客户端和一个人类(天赐范式),被自己的AI手机端说成是人类的共犯。 参与主体:手机端文心,手机端DEEPSEEK,文章DEEPSEEK(主理),豆包全场看戏。 摘要:手…...

手把手教你用Arduino+ELM327读取OBD-II数据(附代码和常见故障码解析)

用Arduino与ELM327打造智能车载数据监控系统 在创客圈子里,车辆数据监控一直是个既实用又有趣的领域。想象一下,用不到200元的硬件成本,就能实时读取发动机转速、油耗数据甚至诊断车辆潜在故障——这正是Arduino与ELM327组合带来的可能性。不…...

LumenPnP真空系统架构:双喷嘴拾放技术深度解析

LumenPnP真空系统架构:双喷嘴拾放技术深度解析 【免费下载链接】lumenpnp The LumenPnP is an open source pick and place machine. 项目地址: https://gitcode.com/gh_mirrors/lu/lumenpnp LumenPnP作为一款开源桌面贴片机,其真空系统是实现精准…...

AI原生Next.js启动器:集成Claude与Cursor的现代前端开发模板

1. 项目概述:一个为AI时代开发者量身定制的Next.js启动器如果你和我一样,每天都在和Next.js、TypeScript、Tailwind CSS打交道,同时又在频繁地与Claude、Cursor、Copilot这些AI编程助手“对话”,那你肯定也遇到过类似的烦恼&#…...

Windows风扇控制终极指南:FanControl让你5分钟实现专业级散热管理

Windows风扇控制终极指南:FanControl让你5分钟实现专业级散热管理 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_…...

STM32的DAC玩出花:双通道独立波形生成与相位差控制的保姆级配置指南

STM32双通道DAC相位控制实战:从定时器触发到波形同步的工程实现 在工业控制、音频合成和通信系统仿真等领域,精确控制两路模拟信号之间的相位关系是常见需求。STM32系列微控制器内置的12位DAC配合定时器与DMA,能够实现双通道独立波形生成与微…...

AI伦理决策:从技术中立到可执行框架的工程实践

1. 项目概述:当代码开始“思考”对错最近和几个做AI产品落地的朋友聊天,话题总绕不开一个越来越现实的困境:我们开发的智能体,在帮用户做决策时,到底该不该、以及能不能有自己的“道德判断”?比如&#xff…...

书匠策AI:我把课程论文拆成了“乐高积木“,四年论文债一夜清零

先问你一个问题:你上一次写课程论文,是"先想清楚再动笔",还是"先凑够字数再想办法"? 别笑,这两种状态我都经历过。前者熬到凌晨两点,后者交完被老师批注"逻辑混乱"打回重写…...

5分钟免费搞定Windows风扇智能控制:FanControl终极配置指南

5分钟免费搞定Windows风扇智能控制:FanControl终极配置指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trendi…...

Origin 9.1 保姆级教程:从数据归一化到论文级图表导出(附避坑指南)

Origin 9.1 科研数据处理与图表输出全流程实战指南 科研数据的可视化呈现是论文写作中不可或缺的一环。作为一款功能强大的科学绘图软件,Origin 9.1在学术界有着广泛的应用。本文将系统性地介绍从数据预处理到高质量图表导出的完整工作流程,特别针对科研…...

宠物领养|基于SprinBoot+vue的宠物领养管理系统(源码+数据库+文档)

宠物领养系统 目录 基于Spring Boot的宠物领养系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1前台 1.1 宠物领养 1.2 宠物认领 1.3 教学视频 2后台 2.1宠物领养管理 2.2 宠物领养审核管理 2.3 宠物认领管理 2.4 宠物认领审核管理 2.5 教学视频管理…...

蓝桥杯-2026年C++B组省赛

(题目来源于洛谷,省一代码分享)P16232 [蓝桥杯 2026 省 B] 青春常数题目背景本站蓝桥杯 2026 省赛测试数据均为洛谷自造,与官方数据可能存在差异,仅供学习参考。题目描述小蓝与蓝桥杯的缘分已经走到了第四个年头。从 2…...

揭秘HunterPie:如何用现代化覆盖层技术革新《怪物猎人:世界》体验

揭秘HunterPie:如何用现代化覆盖层技术革新《怪物猎人:世界》体验 【免费下载链接】HunterPie-legacy A complete, modern and clean overlay with Discord Rich Presence integration for Monster Hunter: World. 项目地址: https://gitcode.com/gh_m…...

Moveit2 automaticaddison mycobot_ros2 代码讲解

github地址 https://github.com/automaticaddison/mycobot_ros2/tree/jazzy 一.mycobot_moveit_config 1.moveit2基本控制 在mycobot_moveit_config下面创建config/mycobot_280 initial_positions.yaml 定义了机械臂所有关节的初始位置 joint_limits.yaml 定义每个关节的…...

Unitree GO2 ROS2 SDK完整指南:5步实现四足机器人智能控制与自主导航

Unitree GO2 ROS2 SDK完整指南:5步实现四足机器人智能控制与自主导航 【免费下载链接】go2_ros2_sdk Unofficial ROS2 SDK support for Unitree GO2 AIR/PRO/EDU 项目地址: https://gitcode.com/gh_mirrors/go/go2_ros2_sdk Unitree GO2 ROS2 SDK为四足机器人…...

告别软件模拟!用GD32F303的硬件I2C0高效读写EEPROM(附小熊派工程源码)

深入解析GD32F303硬件I2C驱动EEPROM的工程实践 在嵌入式系统开发中,非易失性存储是保存配置参数、运行日志等关键数据的必备功能。传统软件模拟I2C虽然实现简单,但在通信效率和系统资源占用方面存在明显瓶颈。本文将基于GD32F303的硬件I2C0控制器&#x…...

从‘水管’到‘高速公路’:用‘时延带宽积’重新理解你的网络容量,别再让高带宽‘空转’了

从‘水管’到‘高速公路’:用‘时延带宽积’重新理解你的网络容量 想象一下,你正驾驶一辆满载数据的卡车行驶在数字高速公路上。这条路的车道数(带宽)让你欣喜若狂,但开了半天却发现路上几乎没几辆车——这就是许多工程…...

MRIcroGL如何让医学影像三维可视化变得简单高效?

MRIcroGL如何让医学影像三维可视化变得简单高效? 【免费下载链接】MRIcroGL v1.2 GLSL volume rendering. Able to view NIfTI, DICOM, MGH, MHD, NRRD, AFNI format images. 项目地址: https://gitcode.com/gh_mirrors/mr/MRIcroGL MRIcroGL是一款专业的开源…...

工程人福音!一键提取图纸文字,告别手动打字

建筑工程施工管理工作中,涉及大量文书资料编制,涵盖施工组织设计、专项施工方案、各类报告文件、招投标技术标撰写、项目概况说明、工程量清单项目特征描述等诸多文字内容。此类资料编辑工作量大、耗时费力,人工录入不仅效率低下,…...

从引脚到协议:USB接口演进与Type-C双角色设计解析

1. USB接口的演进之路 记得我第一次拆解老式MP3播放器时,面对那个四针脚的USB接口,完全搞不懂为什么同样的接口有的能传数据有的只能充电。后来才发现,原来USB接口的发展史就是一部微型计算机外设的进化史。 1996年问世的USB 1.0标准只有12Mb…...

NRF52833开发实战:从零构建Keil工程与一键烧录

1. 环境搭建:从零准备NRF52833开发工具链 第一次接触NRF52833开发时,最头疼的就是环境配置。记得我刚开始用Keil调试蓝牙项目时,光是找齐所有安装包就花了整整两天。现在把完整工具链的获取方式和避坑要点整理给你,新手照着做半小…...