如何在多用户场景下使用单个.json文件并解决并发访问问题
问题解答
并发场景下现有代码的问题
你的代码在多用户并发访问时一定会出现数据异常问题,不止是跨用户读取数据,还可能出现数据丢失、JSON文件损坏无法解析的情况,核心问题有两个:
- 竞态条件导致数据覆盖/损坏
多个用户同时触发写操作时,可能出现两个用户先后读取了同一个版本的JSON文件,各自追加内容后写回,最后只有后写入的用户数据生效,先提交的用户数据直接丢失。如果某个用户的写操作执行到一半时,另一个用户触发读操作,还会读到不完整的JSON结构,直接抛出解析异常。 - 无用户隔离导致跨用户读取
当前所有用户的提交数据都存在同一个questions数组里,没有任何用户标识区分,读的时候默认读取全部数据,天然就会出现用户B读到用户A提交内容的问题。
具体规避方案
1. 解决并发读写冲突
如果继续使用JSON文件作为存储介质,优先通过以下方式避免竞态:
- 加文件锁保证读写原子性:读写操作前先获取锁,读操作加共享锁(允许多个读同时进行,阻塞写操作),写操作加排他锁(阻塞所有其他读写操作)。推荐使用跨平台的
filelock库实现,示例代码如下:from filelock import FileLock import os, json # 写操作示例 lock = FileLock("my_data_loop.json.lock") with lock: # 先获取锁再操作文件 # 先读最新数据 with open('my_data_loop.json', 'r', encoding='utf-8') as f: data = json.load(f) # 追加内容 for item in mm: # 同时存入用户唯一标识,用于后续数据隔离 data['questions'].append({'name': item, 'user_id': current_user_id}) # 先写临时文件再替换,避免写失败损坏原文件 temp_file = 'my_data_loop.tmp.json' with open(temp_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) os.replace(temp_file, 'my_data_loop.json') # 原子替换原文件 # 读操作示例 posted = [] with lock: with open('my_data_loop.json', 'r', encoding='utf-8') as json_file: data = json.load(json_file) # 只过滤当前用户的数据 for p in data['questions']: if p['user_id'] == current_user_id: posted.append(p['name']) # 后续处理逻辑 - 优化写操作逻辑:你当前的代码是循环每追加一条数据就写一次文件,IO开销非常大,建议修改为所有内容追加完成后统一写一次文件。
2. 解决用户数据隔离问题
两个可选方案按需选择:
- 低存储量场景:存储数据时追加
user_id(用户唯一标识)字段,读取时按当前登录用户的ID过滤数据,从逻辑上隔离不同用户的内容。 - 高存储量场景:按用户ID拆分存储文件,每个用户单独存一个JSON文件(比如
user_data_{user_id}.json),从存储层面彻底隔离,完全不会出现跨用户读的问题。
更推荐的替代方案
如果并发量不低且后续有扩展需求,不建议用JSON文件做多用户并发的存储介质,优先使用轻量关系型数据库SQLite:自带事务、并发控制能力,无需自己处理文件锁逻辑,支持SQL查询可以非常方便的按用户过滤数据,学习成本很低,完全适配你的业务场景。
内容的提问来源于stack exchange,提问作者lobjc
相关产品推荐
相关产品推荐

