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

Flask生产环境下如何避免高并发导致的重复数据处理问题

解决高并发下MongoDB重复插入问题(无需唯一索引)

你的问题根源是竞态条件:多个请求同时执行find_one检查,此时都未找到对应u_id的文档,随后同时进入插入逻辑,最终导致重复数据。下面给出两种无需依赖唯一索引的可行方案:

方案一:使用MongoDB原子操作find_one_and_update

利用MongoDB的原子操作将"检查+插入"合并为一步,从根本上避免竞态。通过$setOnInsert确保仅在文档不存在时才插入字段,upsert=True控制不存在则创建:

@app.route('/process_data/<u_id>')
def process_dt_(u_id):
    # 原子执行:仅当u_id不存在时插入新文档,存在则不做修改
    result = db_collection.find_one_and_update(
        {'u_id': u_id},
        {'$setOnInsert': {'key': 'value'}},
        upsert=True,
        return_document=True
    )
    
    # 通过upserted_id判断是否是新插入的文档
    if hasattr(result, 'upserted_id') and result.upserted_id is not None:
        return 'OK'
    else:
        return 'has already been processed', 403

优势:无需额外依赖组件,性能高,完全由MongoDB保证操作原子性,是最推荐的方案。

方案二:分布式锁(基于Redis)

如果业务逻辑更复杂,无法用单一MongoDB原子操作覆盖,可以引入分布式锁,保证同一u_id的请求串行处理:

import redis
from flask import Flask

app = Flask(__name__)
# 初始化Redis客户端(根据你的配置调整参数)
redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

def acquire_lock(u_id, lock_timeout=10):
    # 尝试获取锁,nx=True表示仅当key不存在时设置,ex设置锁过期时间防止死锁
    return redis_client.set(f"lock:{u_id}", "locked", ex=lock_timeout, nx=True)

def release_lock(u_id):
    redis_client.delete(f"lock:{u_id}")

@app.route('/process_data/<u_id>')
def process_dt_(u_id):
    # 无法获取锁时,直接返回冲突
    if not acquire_lock(u_id):
        return 'processing or already processed', 403
    
    try:
        # 原有逻辑现在是串行执行,不会出现竞态
        check_exists = db_collection.find_one({'u_id': u_id})
        if not check_exists:
            db_collection.insert_one({
                'u_id': u_id,
                'key': 'value'
            })
            return 'OK'
        else:
            return 'has already been processed', 403
    finally:
        # 无论成功失败都释放锁
        release_lock(u_id)

注意事项:

  • 锁的过期时间要设置合理,避免业务执行时间超过锁有效期导致的锁提前释放。
  • 可以考虑引入锁续约机制,防止长耗时任务的锁过期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:20:25