并发编程与数据隔离
并发编程与数据隔离
核心问题
并发场景下的典型数据问题:
| 问题 | 描述 | 例子 |
|---|---|---|
| 竞态条件 | 多个线程同时读写同一数据,结果依赖执行顺序 | 两个请求同时修改用户余额 |
| 脏读 | 读到未提交的事务数据 | A 修改未提交,B 读到了 |
| 丢失更新 | 后提交的覆盖先提交的 | 两人同时编辑同一文档 |
| 幻读 | 同一查询在不同时间返回不同行数 | 统计用户数时有人新注册 |
数据库层面解决方案
事务隔离级别:
| 隔离级别 | 脏读 | 丢失更新 | 幻读 | 默认数据库 |
|---|---|---|---|---|
| Read Uncommitted | ❌ | ❌ | ❌ | - |
| Read Committed | ✅ | ❌ | ❌ | Oracle, PostgreSQL |
| Repeatable Read | ✅ | ✅ | ❌ | MySQL |
| Serializable | ✅ | ✅ | ✅ | - |
乐观锁 vs 悲观锁:
1 | -- 悲观锁(先锁再改) |
应用层面解决方案
分布式锁(Redis):
1 | async function acquireLock(key, ttl) { |
队列****串行化:
- 用户级队列,保证同一用户操作串行执行
- 适用于:订单处理、账户操作
架构层面解决方案
| 方案 | 说明 | 适用场景 |
|---|---|---|
| 数据分片 | 按用户/租户分片,天然隔离 | 多租户 SaaS |
| 读写分离 | 写主库、读从库 | 读多写少 |
| CQRS | 命令查询职责分离 | 复杂业务系统 |
常见场景推荐方案
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 库存扣减 | 乐观锁 + 重试 | 高并发,冲突率低 |
| 账户转账 | 悲观锁 / 分布式锁 | 强一致性要求 |
| 秒杀抢购 | 队列串行化 + 预扣减 | 抗高并发 |
| 配置更新 | 版本号 + CAS | 简单有效 |
实践项目:gf_v3 进销存系统
可应用点:
- 库存扣减(高并发场景)
1 | UPDATE products |
- 多租户数据隔离
- 每行数据加
tenant_id字段 - 查询强制带上
WHERE tenant_id = ?
- 每行数据加
- 采购单/销售单并发编辑
- 使用乐观锁版本号
- 冲突时提示用户刷新重试
- 用户会话隔离
- 不同租户的数据完全隔离
- 数据库层面 + 应用层双重校验
推荐学习资源
书籍:
- 《数据库系统概念》- 事务隔离章节
- 《高性能 MySQL》- 锁与并发
- 《数据密集型应用系统设计》(DDIA) - 第 7、8 章 ⭐⭐⭐
DDIA 阅读链接:
- 中文版:https://github.com/Vonng/ddia(《数据密集型应用系统设计》中文翻译)
- 英文版:https://dataintensive.net/
- 第 7 章:事务(Transactions)
- 第 8 章:分布式系统的麻烦事(The Trouble with Distributed Systems)
在线文档:
- PostgreSQL 事务隔离:https://www.postgresql.org/docs/current/transaction-iso.html
- MySQL InnoDB 锁:https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
- Redis 分布式锁:https://redis.io/topics/distlock
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 EIGHTJIU!
评论


