news 2026/9/23 6:48:36

多源数据写入协议:如何让AI Agent并发写数据不“互相踩脚”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多源数据写入协议:如何让AI Agent并发写数据不“互相踩脚”

同一个业务系统里同时跑着好几个Agent,有的负责从邮件抽取订单,有的在同步客户资料,还有的定时从旧系统迁移数据。单看每个Agent都很正常,一旦它们开始同时往同一张表、同一个文件、同一个对象里写数据,问题就来了:A刚写入的记录被B用旧版本覆盖,C读到的数据一半新一半旧,D的重试逻辑又把已经提交的结果又写了一遍。这种“互相踩脚”的现象在真实项目里出现得太频繁了,以至于我后来形成条件反射——接到Agent协作需求的第一件事,不是看模型选型,不是调Prompt,而是先搞清楚:这些Agent到底怎么共享写入权限

这篇内容想聊的就是多源数据写入协议,简单说就是一套让多个AI Agent在写同一份数据时,能有序、不冲突、可追溯的规则。它适合正在做Agent平台、多Agent系统,或者准备把Agent接入现有业务系统的开发者、架构师。我会从冲突的根源讲起,到协议怎么设计,再到落地时容易踩的坑,尽量把“不互相踩脚”这件事讲透。

1. Agent 并发写数据的冲突,为什么普通方案扛不住

先说一个很多人容易忽略的事实:Agent和普通程序并发有一个本质区别。普通程序写数据,逻辑是确定的,开发者能提前推演每一步;但Agent的行为是模型推理出来的,同样的输入,今天跑和明天跑,可能走了完全不同的分支。这意味着Agent的写入意图本身就带有不确定性,再加上多Agent并行,冲突概率远高于传统后端服务的并发写入。

1.1 三种最常见的“踩脚”形态

我在项目里整理了实际发生过的冲突,基本能归成三类。读者可以对照自己遇到的场景看是哪种。

第一种是覆盖型冲突。两个Agent基于不同时间点的快照修改同一条记录,后提交的覆盖先提交的。听起来和数据库的丢失更新一样,但Agent场景下更隐蔽——Agent通常会在工具调用前先把上下文整理成一段自然语言,再调用写入接口,这个“思考+调用”的周期可能长达几秒甚至几十秒。如果两个Agent都在处理同一个工单,A把状态改为“处理中”,B基于更早的快照把状态改回“待分配”,用户看到的就是工单状态莫名其妙地回退了。

第二种是部分写入冲突。Agent A要更新订单的收货地址,Agent B同时更新同一个订单的配送时间,如果它们各自带着整行数据提交,最终结果取决于谁后落库,必然有一方的更新丢失。更麻烦的是,有些Agent写的是JSON字段或者文档型数据,A往配置里追加了一个节点,B基于旧版本覆盖了整个配置,A的追加结果被无声无息地吞掉。

第三种是重复写入冲突。Agent任务重试时,由于上游超时导致Agent不确定上一次到底有没有提交成功,于是又执行了一次写入。如果接口没有幂等设计,同一条记录就被插入了两次,后续的统计、同步、展示全部错乱。这个问题在Agent场景里尤其突出,因为Agent调用外部工具时经常遇到超时,而模型为了完成任务,很自然地会选择“再试一次”。

1.2 数据库事务和分布式锁为什么不够用

很多人第一反应是给写入加锁或者开事务。这个思路没错,但落到Agent场景,直接用会遇到几个实际困难。

先说分布式锁。传统服务里锁的粒度可以定得很细,比如“订单ID为123的记录的更新”,但Agent的写入目标经常是动态发现的。Agent在对话过程中才决定要写哪个字段,甚至在调用工具前一刻才生成参数,你很难提前给所有可能的写入路径预设好用锁方案。更现实的一个问题是,Agent调用外部写入工具后,如果模型在后续步骤中自己判断“刚才的调用失败了”,它可能会立即重试,而锁的持有时间、释放时机根本不受你控制。

再说数据库事务。事务适合短平快的数据修改,但Agent的一个完整任务,比如“整理客户信息并写入CRM”,中间可能包含多次模型推理、多次工具调用。如果让事务横跨整个Agent任务,锁的持有时间太长,系统并发能力直接被拖垮。如果只给单次写入开事务,又解决不了跨多步操作的一致性问题。

所以问题本质上是:Agent的执行模式是长周期、不确定、分布式的,而传统并发控制假设执行是短周期、确定、集中的。我们需要在更高的层面设计规则,也就是写入协议,而不是依赖单机数据库能力。

2. 写入协议的核心设计:先定规则,再谈效率

多源数据写入协议,说白了就是一套约定:谁在什么条件下可以写什么数据,写入时携带哪些信息,遇到冲突时按照什么规则处理。它不是某一项技术,而是一个协议层设计。下面拆解我实际使用下来最核心的几个部分。

2.1 写入元数据是协议的基石

所有协议设计的第一步,是让每次写入都带上足够的元数据,否则后面一切规则都无从谈起。我在设计协议时,规定了每次写入必须携带以下信息:

  • agent_id:来源Agent标识,用于追踪是哪个Agent发起的写入。
  • task_id:任务标识,Agent的每一次完整任务生成一个全局唯一ID,重试时沿用同一个task_id。
  • write_seq:写入序号,Agent在同一个任务内的多次写入递增,用于记录写入顺序。
  • target_ref:目标引用,指向要写入的主体,比如订单ID、配置路径或对象ID。
  • basis_version:基础版本号,Agent在读取数据时拿到的版本号,提交时原样带回。
  • source:来源标识,如email_parseretl_jobmanual_api,方便做来源分析和冲突策略分流。

这组元数据中,basis_version是冲突检测的关键,task_id是幂等去重的关键,write_seq是恢复写入顺序的关键。缺少任何一个,协议都会出现漏洞。

从工程实现上看,这些元数据并不难加。如果是通过API写入,就在HTTP头部或请求体的固定字段里传;如果是直接写数据库表,就为每张需要被Agent写入的表增加对应的协议列。我见过不少团队一开始嫌这些字段多余,等到排查线上数据错乱时,才后悔当初没有设计这些基础信息。

2.2 核心写入流程:唯一写入者判定

有了元数据,接下来就是协议的核心——写入判定。我最常用的方案是在数据接入层加一个统一的写入仲裁器,所有Agent写入请求先经过仲裁器,而不是直连存储。

一次标准写入流程是这样的。Agent把写入请求和元数据发给仲裁器,仲裁器根据目标引用去找当前主数据的版本号,再校验请求中的basis_version和当前主数据版本是否一致。如果一致,正常写入,并把主数据版本号加一。如果不一致,仲裁器不直接拒绝,而是根据协议配置执行冲突策略,比如返回冲突结果让Agent自行处理,或由仲裁器执行预设合并策略。写入成功后,仲裁器记录一条完整的写入事件日志,包含从哪来、写到哪、基于什么版本、结果是什么,供审计和追溯。

这种设计有两点值得强调。第一,仲裁器是唯一写入入口,任何Agent都不能绕过它直连数据库,否则协议就形同虚设。第二,版本号的更新必须和写入本身在同一个原子操作里,最稳妥的是利用数据库的行锁或CAS(Compare-and-Swap)能力,而不要用独立服务去管理版本号,否则一旦版本服务出问题,写入链路就断了。

2.3 冲突策略组合:不是所有冲突都该拒绝

协议中最被人低估的部分,其实是冲突策略的选择。“发现冲突就拒绝”是最省事的,但它不总是最优的,甚至会引发Agent死亡循环——Agent不断重试,不断冲突,任务一直完不成。

我在实际项目中把冲突策略设计成可按数据维度配置的组合,常见的几类如下。

  • 拒绝并返回冲突详情:适合状态变更类操作,比如工单状态、审批流状态,这类数据不能乱合并,必须让Agent知道当前真实状态,重新推理。
  • 按字段合并:适合属性更新类操作,比如Agent A改了地址,Agent B改了配送时间,两个字段合并即可。具体做法是仲裁器对每个字段记录独立的版本,或让Agent携带增量更新结构,而不是整行数据。
  • 源优先级覆盖:适合来源等级明确的数据,比如手动API写入的优先级高于自动抓取,低优先级来源写入遇到冲突时,直接覆盖。
  • 追加式写入:适合日志、操作记录、事件流这类只增不改的数据,不覆盖旧数据,只追加新内容。

这里有个经验:给不同数据配置不同策略,要像配置权限一样仔细。不要试图用一个统一策略解决所有冲突,因为Agent写入的场景太杂,策略一旦定死,后面你会发现总有数据需要特殊处理。把这些策略外置为可配置项,比写在代码里灵活得多。

2.4 幂等和去重:防止重试造成二次写入

前面提到Agent重试导致重复写入,这是多Agent系统里最容易被忽略又最致命的问题之一。协议设计的另外一条主线就是幂等控制。

我在仲裁器中维护了一张task_write_log表,记录每个task_idwrite_seq的操作结果。当一个携带相同task_idwrite_seq的写入请求到达时,仲裁器不是直接执行,而是先去查这个表。如果发现已经处理过,就直接返回上一次的执行结果,不再重复写入。整个过程类似HTTP的幂等键(Idempotency-Key)机制,但以Agent任务维度来设计,而不是以请求维度。

这个表还需要设置合理的保留时间。任务和任务之间通常相隔几小时到几天,建议至少保留7天以上。一旦任务重试发生在数据已被清理之后,就需要靠业务层的唯一键约束兜底,比如在用户表上建唯一索引。

3. 从单体写入到多写协议:一条迁移路径

协议说清楚之后,很多人还会问一个问题:我们已经有Agent在写数据了,现在想引入这套协议,该怎么迁移?这里分享一个从单体写入平滑升级到多写协议的路径,适合已有存量系统的项目。

3.1 第一步:把Agent的直连写入改为API调用

这是最关键的第一步。不管Agent用的是MCP工具、Spring AI的Tool还是LangChain的Function Calling,都不要让它直接拿数据库连接池去执行SQL,而是把所有写入动作封装成统一的API接口。这样做有两个直接好处:一是你能在API层集中做元数据校验、版本检测和幂等处理,二是Agent生态里的工具只需要对接一组稳定的接口,不用关心底下存储怎么变化。

在实际操作中,这一步往往比想象中阻力更大,因为不少Agent已运行的代码中直接封装了JDBC或ORM调用。但从长期看,这一层抽象是协议落地的基础设施。改造完成的标准是:没有一个Agent能绕过API直连存储。这个标准听起来简单,真正执行时要检查代码仓库里的所有Agent实现,包括那些部署在流程引擎里的旧任务。

3.2 第二步:为存量数据补充元数据和版本信息

存量系统通常没有basis_version这类字段,简单粗暴地要求Agent在几天内全部兼容新协议并不现实。这里有一个过渡方案:在仲裁器的数据模型里增加一张data_version表,专门记录每条主数据的当前版本号。

这张表的键是目标引用,值就是版本号。每次成功写入时,仲裁器不仅更新主数据,也更新data_version的版本值。对于存量数据,可以写一个一次性迁移脚本,把已有主数据的版本号统一初始化为0,这样所有存量数据都相当于只有一个历史版本。之后Agent的每次写入,只要basis_version不是0,一律视为有冲突,必须走冲突策略流程。

这个迁移路径能做到业务不中断,因为新协议对存量数据并不要求Agent立即改变行为,而是一旦涉及存量数据,仲裁器有权拒绝或合并,逼迫Agent通过API来查询最新版本后再写。经过一段时间,自然会有越来越多的Agent养成先查再写的习惯。

3.3 第三步:按数据域逐步开启冲突策略

不是所有数据都需要立刻开启严格的冲突协议。建议先把协议部署为核心业务数据域,比如订单、用户、配置;对日志类、报表类数据,可以先放宽到“追加式”策略,不影响Agent主线任务的推进。

分阶段开启还有一个额外的好处:可以验证仲裁器本身的可靠性。仲裁器是核心链路,一旦它有问题,所有Agent写数据都会失败。先用低风险的数据域做灰度,确认稳定后再推全量,比一口气改完要稳妥得多。

4. 落地中的关键环节:仲裁器、版本冲突处理与可观测性

当协议层面的设计真正进入编码和上线阶段时,有几个环节特别容易出问题,这里单独展开说,也算是我自己踩坑后的总结。

4.1 仲裁器的实现选型与避坑

仲裁器到底该怎么实现?我见过两种主流路径。一种是自研独立服务,把仲裁器做成一个带REST接口或gRPC接口的中间层,优点是策略完全可控,适合定制化需求强的团队;另一种是基于已有的API网关或BFF层做增强,把版本校验、幂等逻辑写在网关的过滤器中,优点是复用基础设施,减少一个维护单元,缺点是网关层通常不具备很强的事务能力,复杂的冲突策略写起来受限。

对于大多数团队,我更推荐自研一个轻量的仲裁服务,而不是把逻辑堆在网关上。实际项目里仲裁器的核心依赖是数据库的事务能力和行锁语义,把它独立出来,部署边界清晰,排查问题时职责也明确。

实现时有个坑必须注意:版本校验和实际写入必须在一个数据库事务内完成。很多团队第一版把版本校验放在应用层,先查版本,再拼装SQL执行更新,中间隔了几毫秒。这期间另一个Agent完成了写入,版本就变了,当前请求又会基于旧版本提交,于是冲突检测形同虚设。正确做法是用类似UPDATE ... WHERE version = ?的乐观锁方式,通过数据库影响行数来判断是否冲突,或者用事务内SELECT FOR UPDATE锁行来保证判断和写入的原子性。

另外,仲裁器的写入路径不建议引入消息队列来异步执行。早期的设计里我们曾经想把写入丢进MQ,让仲裁器异步消费,结果导致Agent拿到成功的返回时,数据其实还没落库。对于靠结果驱动后续决策的Agent来说,这种异步延迟是致命的。如果一定要异步,必须提供同步确认的机制,比如等MQ消费完成后再返回成功。

4.2 版本冲突处理流程:返回什么信息给Agent

当仲裁器检测到版本冲突时,返回给Agent的信息质量直接决定后续链路是否顺畅。

最差的返回是一个纯错误码,比如“409 Conflict”,Agent拿到之后只能泛泛地理解成“写失败了”,它可能选择重试,也可能放弃任务。比较好的做法是返回结构化冲突详情,至少包含当前主数据的最新版本号、当前状态、当前值快照、可能的原因(比如“版本不匹配,基础版本为3,当前版本为5”)、以及建议动作(比如“请重新读取记录后再修改”)。

如果Agent用了ReAct模式的Function Calling,它可以直接把这段冲突信息作为工具调用的反馈丢回给模型,模型根据反馈重新生成下一步决策。很多教程只讲Function Calling怎么定义参数,却忽略了工具返回值的质量同样决定Agent的成败。冲突反馈就是典型例子——它既是一个错误提示,也是模型下一次决策的重要上下文。

4.3 写入审计日志与链路追踪

多源数据写入协议真正上线之后,你会发现“能查出来是谁改的”和“能查出来为什么改的”同样重要。

我强烈建议仲裁器把每次写入的完整事件落盘到独立的日志系统,字段就是前面讲的协议元数据再加时间戳、写入前后版本号、执行结果。这样无论是备份回滚、安全审计,还是排查Agent行为异常,都有据可查。

与之配套的是链路追踪。Agent的一个任务往往跨多个工具调用,中间还嵌着模型推理。当写入出问题时,要从日志倒推是哪个Agent、在哪个环节发起的写入。这时候task_id就要和Agent的请求追踪ID做关联。最简单的做法是把追踪ID传入Agent执行上下文,在工具调用时透传,再写到仲裁器日志里。

4.4 关闭自动重试,改为协商式恢复

Agent天生喜欢重试,而重试在这套协议里却是一把双刃剑。没有协议时,重试是重复写入的元凶;有协议以后,盲目重试还可能反复触发冲突策略,消耗算力和接口资源。

我在协议设计里增加了一条建议:对Agent的自动重试加以限制。当仲裁器拒绝写入并返回冲突详情后,Agent不应无条件重试,而应先执行一次“查询-决策-再写入”的循环,也就是带上下文的恢复流程。具体到工程上,就是要控制Agent的ReAct循环中“工具调用失败”分支的处理逻辑,不能让模型一看到错误就随便重试。

这点对纯调API的Agent比较难完全约束,但至少可以在API层做限流,或者在Agent开发框架里对冲突类错误设置特殊处理分支。跨Agent协作时,一个Agent发现自己写入冲突了,可以先把冲突信息广播给协作方,协作方同步更新本地快照,避免后续操作继续基于旧数据。

5. 跨Agent与MCP/工具生态的集成设计

很多读者留言问,这套协议能不能和现在流行的MCP、Spring AI这类工具链结合起来。这里聊聊集成层面的设计。

5.1 把写入协议封装成标准工具

最直接的方式,是把仲裁器的写入能力封装成一个MCP工具或Agent原生工具,比如提供write_with_protocol,参数包含目标、写入内容、basis_version等。Agent调用这个工具时,工具的返回值就是仲裁器处理后的结构化结果。这个方案改动最小,Agent的既有运行框架不需要做太多调整,只需要更换工具实现。

以MCP为例,工具定义里可以不只声明普通参数,还可以在工具描述中明确说明“版本冲突时返回当前数据快照”,让模型在没有代码级约束的情况下,也能依据自然语言描述去理解冲突场景。模型对这种结构化反馈的利用效果,通常比预期要好——本质上,这是用上下文工程来弥补Agent对协议不感知的问题。

5.2 用并发令牌保证跨Agent协作的写入安全

在跨Agent场景里,仲裁器虽然能保证每个写入请求不冲突,但一些问题还是需要更高层的协调。比如两个Agent协作完成同一个订单的落地页配置,一个负责价格,一个负责文案,它们不是共享数据,但都写同一个配置对象的不同字段。仲裁器的按字段合并能够解决一部分问题,可如果AgentA还想先读-再算-再写,AgentB也同时读-再算-再写,合并后谁先谁后,依然不好控制。

这时候可以在写入API中增加一个可选的“并发令牌”机制。以目标引用为粒度,提供acquire_token接口,某个Agent拿到令牌后,只允许这个Agent在有效期内对目标进行写入。令牌有效期建议设置得很短,比如10到30秒。这种方案本质上是用“短租约”替代长事务,适合那些必须互斥操作的场景。

但也要注意,并发令牌不应该作为所有写入的默认要求。如果每个Agent写数据前都要抢令牌,系统的吞吐量会直线下降,也会把延迟拖高。令牌只用于那些实测确实会产生读写竞争的高频冲突目标,比如共享的配置文件、热门的资源对象。

5.3 协议与数据源的解码:从写协议到读协议的配合

既然谈写入,就绕不开读取。多源数据写入协议最后还有一个非常关键的配套部分:读协议

Agent写数据时带入了basis_version,但是Agent的读取接口如果不是从仲裁器读取,而是从缓存、从只读副本、甚至从搜索引擎里读,那么读到的版本可能滞后。也就是说,写入不冲突不代表读取一致。要真正做到“不互相踩脚”,读取也需要遵循一套读协议。

最简单的读协议约束:Agent的关键决策性读取必须从主数据源或读己一致的数据源获取,并且返回数据中携带版本号。不要把读操作分散到多个不同步的数据源,否则Agent基于旧数据生成的新写入,依然会引发冲突。实践中,我在Agent平台的配置中心里加了一个数据源列表,每个数据源标明“读已提交”还是“读可能滞后”,这样Agent开发人员根据业务需求选择读取源,减少团队内部因为读错数据源而导致的冲突。

5.4 测试多Agent并发写入的模拟环境

协议有没有效,不能光靠逻辑推演。我建议在测试环境里搭建一个模拟的“多Agent踩脚演练场”。用Gatling或JMeter可以模拟大量并发写入,但更关键的是模拟Agent的行为模式——不是简单地并发请求,而是带决策间隔的慢请求。

也就是说,造一批Agent线程,每个线程先读取数据,然后随机等几秒,再写入。如果测试方案设计成全部线程同时写,那只是测了仲裁器的并发能力;模拟Agent场景,必须把“读取后延迟写入”这段空隙造出来,才能真正验证版本校验是否能拦截并发覆盖。实际测试中,至少要覆盖四种场景:正常串行写入、两个Agent并发改同一记录、同一Agent重试写入、部分字段并发更新。

6. 从协议看多Agent系统的长期演进

协议这个东西,设计好了能解决眼前的踩脚问题,但它的价值远不止此。多Agent系统发展得越深,你会越发现,真正制约系统的往往不是模型的智能程度,而是协作的秩序程度。写入协议就像交通规则,Agent就像路上的车,规则越明确,车流量越大也不至于堵死。

6.1 协议沉淀下来的数据是系统的宝贵资产

每个写入事件都被记录,每条冲突都被标记,每次合并策略被执行,这些日志和数据是理解整个系统行为的窗口。分析这些数据,你能知道哪些数据源之间经常发生冲突,哪些Agent的任务链路最长、最容易产生重复操作,哪些时间段系统的并发写入压力最大。这个反馈链路可以反过来指导Agent任务分配、调度策略甚至模型Prompt的优化。

我见过一个团队,在写入协议稳定运行半年后,光是通过分析冲突日志就发现了两个高频冲突场景,进而把对应的两个Agent的调度时间错开,线上冲突率直接降了一个数量级。这类优化在协议没有落地前,几乎无从谈起。

6.2 协议让Agent具备可治理性

很多时候,多Agent系统的可治理性比性能更重要。业务方会问“这个数据是谁改的”“为什么改完又回滚了”,这时候,如果系统中没有协议层在做统一治理,排查这类问题会非常痛苦。而有了协议,这些问题的答案就在写入日志里。

更进一步,协议还能支撑权限控制。仲裁器在接收写入请求时,不只做版本校验,还可以校验来源Agent是否有权限写入目标数据域。这种权限控制粒度比数据库账号授权更适合Agent场景,因为Agent可以动态拓展,你不可能给每个Agent都开一套数据库账号,但在仲裁器里配置Agent与数据域的映射关系,改起来成本低得多。

6.3 从“写入协议”向“协作协议”延伸的思考

当我提到“多源数据写入协议”的时候,其实已经在接近一个更大的话题——Agent之间的协作协议。写入只是协作的一种表现形态,更完整的协作协议还应该覆盖:任务如何交接、上下文如何共享、状态如何同步、失败如何仲裁。但所有这些组件,有一个共同的基础:必须有一个明确的、可记录的、可验证的数据写入秩序。

把这件事想明白之后,你会理解为什么一个看起来只是“并发控制”的问题,值得上升到“协议”层面来设计。因为真正要解决的,从来都只是数据怎么落库,而是如何让一群“不确定的、自主的、动态出现和消失”的写作者,在共享的事实上合作而不互相破坏。框架会变,模型会升级,但基于规则和秩序的协作方式,会是多Agent系统长期有效的底层能力之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 6:47:54

HTML动态背景实战:Canvas、CSS与SVG性能调优指南

简介:一套专为网页前端设计的多风格动态背景源码包,适合需要快速美化页面、营造沉浸式视觉体验的开发者。其中收录图片轮动、星空流星、动态美女、屋雨、街道、夜幕等酷炫背景效果,每种效果均包含独立网页页面及配套样式表与脚本控制逻辑&…

作者头像 李华
网站建设 2026/9/23 6:47:18

图解原理:3个gujian常见坑,告别StackTrace报错

图解原理:3个gujian常见坑,告别StackTrace报错 刚接手一个老项目,运行 npm run dev 后终端瞬间被红屏覆盖,满屏的 Uncaught TypeError: Cannot read properties of undefined (reading 'gujian') 。这种…

作者头像 李华
网站建设 2026/9/23 6:47:14

5分钟搞懂belong是什么意思:附完整示例与避坑指南

5分钟搞懂belong是什么意思:附完整示例与避坑指南 学会语法却不知怎么搭项目,这是很多开发者从入门到进阶时最大的拦路虎。特别是遇到像 belong 这种既像动词又像介词的概念时,查字典说它是“属于”,但在代码里怎么实现“属于”关系?怎么在数据库里落地?怎么在 API 里校验权限?…

作者头像 李华
网站建设 2026/9/23 6:47:02

5个实战技巧图解mult源码原理,解决项目搭建难题

5个实战技巧图解mult源码原理,解决项目搭建难题 刚学会 Python 语法,想写个多线程爬虫,结果 multiprocessing 模块里的 Pool 和 Process 用混了,进程死锁、内存泄漏频发。这种“懂语法却不会搭项目”的困境,在并发编程中太常见了。很多新手卡在 mult…

作者头像 李华
网站建设 2026/9/23 6:46:59

使用 Johnny-Five 的 Led.Digits 打造七段数码管数字时钟

使用 Johnny-Five 的 Led.Digits 打造七段数码管数字时钟 【免费下载链接】johnny-five JavaScript Robotics and IoT programming framework, developed at Bocoup. 项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five 导读 本文围绕 Johnny-Five(J…

作者头像 李华