You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hyperledger Composer中如何规范化资源ID的编排?

实现ourAsset ID自动递增的方案

刚好之前在Hyperledger Fabric项目里处理过类似的自增ID需求,给你分享两种可行的实现方案,分别适用于不同场景:

方案一:直接读取资产注册表取最大ID(适合低并发、资产量不大的场景)

这个思路很直接:每次创建新资产时,读取整个ourAsset注册表,把所有资产按ID降序排序,取最大的那个ID加1作为新ID。如果注册表是空的,就从1开始。

示例交易代码

/**
 * 创建带自增ID的ourAsset
 * @param {org.biznet.CreateOurAsset} tx - 自定义的创建资产交易
 * @transaction
 */
async function createOurAsset(tx) {
    const factory = getFactory();
    // 获取ourAsset的资产注册表
    const assetRegistry = await getAssetRegistry('org.biznet.ourAsset');
    
    // 读取所有资产记录
    const allAssets = await assetRegistry.getAll();
    let newAssetId = 1; // 默认初始ID
    
    if (allAssets.length > 0) {
        // 按ID降序排序(注意要把字符串ID转成数字比较,避免字符串排序的问题)
        allAssets.sort((assetA, assetB) => parseInt(assetB.assetID) - parseInt(assetA.assetID));
        // 取排序后的第一条,也就是ID最大的资产
        const latestAsset = allAssets[0];
        newAssetId = parseInt(latestAsset.assetID) + 1;
    }
    
    // 创建新资产,用自增后的ID
    const newAsset = factory.newResource('org.biznet', 'ourAsset', newAssetId.toString());
    // 这里可以给资产设置其他属性,比如从交易参数里获取
    // newAsset.name = tx.assetName;
    // newAsset.owner = tx.assetOwner;
    
    // 将新资产添加到注册表
    await assetRegistry.add(newAsset);
}

注意点

  • 这种方式的问题在于并发场景下可能出现ID重复:如果两个交易同时读取注册表,拿到同一个最大ID,就会生成重复的新ID。所以只适合低并发的场景。
  • 如果资产数量很大,getAll()会拉取所有数据,性能会受影响。

方案二:使用独立计数器资产(适合高并发、资产量大的场景)

这个方案更可靠,核心是创建一个专门的Counter资产来存储当前ourAsset的最大ID,每次创建新资产时,先更新计数器的数值,再用这个数值作为新ID。利用Fabric的乐观锁机制来避免并发冲突。

第一步:定义Counter资产类型

首先在你的CTO模型文件里添加这个资产:

namespace org.biznet

asset Counter identified by counterId {
    o String counterId  // 计数器唯一标识,比如固定为"ourAssetCounter"
    o Integer currentValue  // 当前最大ID值
}

// 你的ourAsset资产定义
asset ourAsset identified by assetID {
    o String assetID
    // 其他属性...
}

// 创建资产的交易定义
transaction CreateOurAsset {
    // 可以添加需要传递的参数,比如资产名称、所有者等
    // o String assetName
    // o Participant owner
}

第二步:编写交易代码

/**
 * 创建带自增ID的ourAsset(基于计数器方案)
 * @param {org.biznet.CreateOurAsset} tx - 创建资产的交易
 * @transaction
 */
async function createOurAsset(tx) {
    const factory = getFactory();
    const counterRegistry = await getAssetRegistry('org.biznet.Counter');
    const assetRegistry = await getAssetRegistry('org.biznet.ourAsset');
    
    // 获取或初始化计数器
    let counter;
    try {
        counter = await counterRegistry.get('ourAssetCounter');
    } catch (err) {
        // 如果计数器不存在,初始化它,初始值设为0
        counter = factory.newResource('org.biznet', 'Counter', 'ourAssetCounter');
        counter.currentValue = 0;
        await counterRegistry.add(counter);
    }
    
    // 自增计数器的值
    counter.currentValue += 1;
    const newAssetId = counter.currentValue.toString();
    
    // 更新计数器(这一步会触发Fabric的乐观锁检查,如果有并发修改会抛出冲突异常)
    await counterRegistry.update(counter);
    
    // 创建新的ourAsset
    const newAsset = factory.newResource('org.biznet', 'ourAsset', newAssetId);
    // 设置资产的其他属性
    // newAsset.name = tx.assetName;
    // newAsset.owner = tx.owner;
    
    // 添加到资产注册表
    await assetRegistry.add(newAsset);
}

优势

  • 避免并发冲突:当两个交易同时修改计数器时,Fabric的乐观锁会检测到冲突,其中一个交易会抛出ConflictException,客户端可以捕获这个异常并重试交易,保证ID不会重复。
  • 性能更好:不需要拉取所有资产记录,只需要操作一个计数器资产,效率更高。

最后补充

如果你的场景并发不高,方案一足够简单好用;如果是生产环境高并发场景,强烈推荐方案二,它能更可靠地保证ID的唯一性。

内容的提问来源于stack exchange,提问作者tahaf10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:27:12