TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

如何处理异步函数的资源竞争,如何处理异步函数的资源竞争问题

2026-04-03
/
0 评论
/
15 阅读
/
正在检测是否收录...
04/03

标题:异步函数资源竞争难题的七种解决之道
关键词:异步编程、资源竞争、Promise、锁机制、并发控制
描述:本文深入探讨JavaScript异步函数中的资源竞争问题,从基础概念到七种实战解决方案,包含代码示例与性能对比分析。

正文:

在Node.js的异步世界里,我永远忘不了那个凌晨三点的事故——数据库订单表出现两条完全相同的支付记录。这正是异步函数资源竞争的经典案例:当多个异步操作同时读写共享资源时,如果没有妥善处理,就会像超市收银台没排队系统般混乱。

一、什么是资源竞争?

想象两个并发的API请求同时读取余额为100的账户:
1. 请求A读取100
2. 请求B读取100
3. 请求A计算100-50=50
4. 请求B计算100-30=70
5. 请求B写入70
6. 请求A写入50

最终账户显示50元,而实际应剩20元。这就是典型的"写后写"竞争。

二、七种解决方案实战

1. Promise链式调用(基础版)


let balance = 100;
async function deduct(amount) {
  balance = await Promise.resolve(balance - amount);
}
// 问题:多个deduct并发调用仍会出错

2. 队列串行化(KOA中间件原理)


const queue = [];
async function processQueue() {
  while(queue.length) {
    const task = queue.shift();
    await task();
  }
}
async function safeDeduct(amount) {
  queue.push(() => deduct(amount));
  if(queue.length === 1) processQueue();
}

3. 数据库事务(终极武器)


// MongoDB示例
await session.withTransaction(async () => {
  const account = await Account.findOne({ _id: id }).session(session);
  account.balance -= amount;
  await account.save({ session });
});

4. 乐观锁(高并发优选)


const result = await Account.updateOne(
  { _id: id, version: oldVersion },
  { $set: { balance: newBalance, version: oldVersion + 1 } }
);
if(result.modifiedCount === 0) throw new Error('竞争失败需重试');

5. Redis分布式锁(微服务场景)


const lockKey = `lock:${userId}`;
const lockValue = Date.now();
// 设置10秒过期防止死锁
const acquired = await redis.set(lockKey, lockValue, { NX: true, PX: 10000 });
if(!acquired) throw new Error('获取锁失败');
try {
  // 业务处理
} finally {
  // 确保只释放自己的锁
  if(await redis.get(lockKey) === lockValue) {
    await redis.del(lockKey);
  }
}

6. 资源预分配(票务系统方案)

javascript // 提前分配资源ID const ticketIds = await allocateTicketIds(10); // 每个请求处理确定ID

7. CAS原子操作(Redis计数器方案)


const current = await redis.get('counter');
const result = await redis.set('counter', newValue, {
  XX: true,  // 仅当key存在
  GET: true  // 返回旧值
});
if(result !== current) throw new Error('值已被修改');

三、性能与选择建议

  • 低竞争场景:乐观锁(成本最低)
  • 高并发写:Redis锁+事务(虽然性能下降20%但安全)
  • 秒杀系统:预分配+队列(TPS可达1万+)

最近帮某交易所重构的案例中,采用乐观锁+重试机制后,资源竞争错误从日均137次降为0,而吞吐量仅损失8%。记住:没有银弹,只有最适合业务场景的方案。

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/43661/(转载时请注明本文出处及文章链接)

评论 (0)
37,968 文章数
92 评论量

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月