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

Trc-20转账监听最优算法咨询:批量地址HTTP监控适配Tron高并发

问题

需要监听大量地址的TRC-20代币转入交易,当交易涉及目标地址时,将交易信息存入数据库。当前无法使用WebSocket监听,只能通过HTTP请求实现。现有代码如下:

const trc20ContractAddress = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";

let contract = await tronWeb.contract().at(trc20ContractAddress);
    
let result = await tronGrid.contract.getEvents(trc20ContractAddress, {
            only_confirmed: false,
            event_name: "Transfer",
            limit: 200,
            min_timestamp: timestamp,
            order_by: "timestamp,asc"
        })
console.log(result)

已知Tron网络每秒可处理2000笔交易,单请求最大返回条数为200,同时需考虑请求延迟且无法监听全区块,求最优监听算法。

最优监听算法设计

核心思路

基于时间窗口动态调整+增量拉取+内存过滤去重+并发控制的组合策略,平衡请求效率、数据完整性和系统负载。


1. 动态时间窗口适配交易密度

  • 初始设置1秒基础时间窗口,根据每次请求返回的事件数量实时调整:
    • 若单次请求返回200条(达上限),说明当前窗口交易密集,将窗口缩小至0.3秒(Tron每秒2000笔,0.3秒约600笔,3次请求可覆盖);
    • 若连续3次请求返回条数低于50,说明交易稀疏,将窗口扩大至5秒,减少无效请求;
  • 窗口范围锁死在0.3秒-5秒之间,避免过小导致请求过于频繁,或过大导致单次拉取数据过载。

2. 增量拉取+断点续传

  • 维护全局lastProcessedTimestamp变量,初始设为当前时间往前推10分钟(避免漏过服务启动前的交易),每次请求的min_timestamp直接用该值;
  • 每次请求完成后,将lastProcessedTimestamp更新为返回结果中最后一条事件的时间戳;
  • 请求失败时采用指数退避重试(第一次等1秒,第二次2秒,最多重试5次),重试时保持原时间戳不变,防止数据丢失。

3. 高效过滤与去重

  • 把所有目标地址存入内存Set集合,拉取到Transfer事件后,直接判断to字段是否在集合中,O(1)复杂度完成过滤;
  • 用transaction_id + log_index作为交易唯一标识,数据库端给该字段加唯一索引,同时在内存中维护最近1小时的交易ID缓存,双重避免重复入库;
  • 业务允许的话,设置only_confirmed: true,只处理已确认交易,减少无效写入。

4. 分页拉取与并发控制

  • 每次请求后检查返回结果的has_more标识,若为真,立即发起下一页请求(递增offset参数),直到拉完当前窗口的所有数据;
  • 限制并发请求数不超过3个,避免触发TronGrid的API频率限制,同时保证拉取速度。

5. 异常监控与自适应调整

  • 记录每次请求的耗时、返回条数、失败次数,若请求延迟超过当前窗口的1/3,临时缩小窗口,避免数据堆积;
  • 连续5次请求都返回满200条时触发告警,提示交易流量远超预期,需人工介入调整。

优化后代码示例

const trc20ContractAddress = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
const targetAddresses = new Set(["目标地址1", "目标地址2", "..."]); // 内存哈希集合
let lastProcessedTimestamp = Date.now() - 10 * 60 * 1000; // 初始时间:10分钟前
let timeWindow = 1000; // 初始窗口1秒
let consecutiveLowVolume = 0;

async function pollTransferEvents() {
    try {
        let hasMore = true;
        let offset = 0;
        const currentEndTimestamp = Date.now();
        
        // 拉取当前时间窗口内所有事件
        while (hasMore) {
            const result = await tronGrid.contract.getEvents(trc20ContractAddress, {
                only_confirmed: true,
                event_name: "Transfer",
                limit: 200,
                min_timestamp: lastProcessedTimestamp,
                max_timestamp: currentEndTimestamp,
                order_by: "timestamp,asc",
                offset: offset
            });

            // 过滤目标地址交易并入库
            const validEvents = result.data.filter(event => 
                targetAddresses.has(event.result.to)
            );
            await saveToDatabase(validEvents); // 需实现带唯一索引的入库逻辑

            // 更新断点与分页状态
            if (result.data.length > 0) {
                lastProcessedTimestamp = result.data[result.data.length - 1].timestamp;
            }
            hasMore = result.has_more || false;
            offset += 200;

            // 动态调整时间窗口
            if (result.data.length === 200) {
                consecutiveLowVolume = 0;
                if (timeWindow > 300) {
                    timeWindow = Math.floor(timeWindow * 0.8);
                }
            } else {
                consecutiveLowVolume++;
                if (consecutiveLowVolume >= 3 && timeWindow < 5000) {
                    timeWindow = Math.floor(timeWindow * 1.5);
                }
            }
        }

        // 计算下一次请求等待时间,避免频繁请求
        const waitTime = Math.max(0, timeWindow - (Date.now() - currentEndTimestamp));
        setTimeout(pollTransferEvents, waitTime);
    } catch (error) {
        console.error("拉取事件失败:", error);
        // 指数退避重试
        const retryDelay = Math.min(2 ** (consecutiveLowVolume + 1) * 1000, 30000);
        setTimeout(pollTransferEvents, retryDelay);
    }
}

// 启动监听
pollTransferEvents();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:53:25