面试题答案
一键面试策略
- 细粒度锁
- 文档级锁:MongoDB 4.0 及以上版本支持多文档事务,在一些场景下,可尽量以单个文档为事务操作对象。例如,对于用户账户余额更新,每次仅针对单个用户文档进行操作。这样不同用户的余额更新事务可并行执行,提升并发性能。同时,由于操作原子性在文档级保证,数据一致性也能得到维护。
- 字段级锁:在某些情况下,若仅需更新文档的特定字段,可考虑类似字段级锁的逻辑。虽然 MongoDB 没有直接的字段级锁概念,但可通过对字段更新逻辑的设计,使得不同事务对同一文档不同字段的更新可并发。例如,一个用户文档包含 “基本信息” 和 “积分信息” 字段,不同事务分别更新这两个字段,只要更新逻辑不相互冲突,就可并发执行,提高并发性能且不影响数据一致性。
- 粗粒度锁
- 集合级锁:在一些对数据一致性要求极高,且操作关联性很强的场景下,可采用集合级锁。比如,在一个电商订单系统中,订单集合涉及订单创建、支付、发货等一系列紧密关联操作,若这些操作必须原子执行以保证数据一致性,可对整个订单集合加锁。但这种方式会降低并发性能,因此只适用于关键且操作频率相对较低的业务场景。
- 数据库级锁:极少情况下,当多个集合间的操作存在强一致性需求时,如跨集合的复杂数据迁移或数据清理操作,可考虑数据库级锁。但这会极大限制并发,仅在非常特殊的业务场景下使用。
实践案例
假设开发一个社交媒体平台,用户发布动态时,不仅要在 “posts” 集合插入新动态文档,还要更新用户 “users” 集合中的发布动态计数。
- 初始方案(未优化锁粒度):使用默认的多文档事务,对 “posts” 和 “users” 集合的操作在一个事务中。这种情况下,相当于采用了相对粗粒度的锁,因为涉及两个集合操作,若同时有多个用户发布动态,可能出现锁争用,并发性能较低。
- 优化方案(细粒度锁):
- 文档级锁优化:首先,对 “posts” 集合的插入操作和 “users” 集合的更新操作分别进行事务设计。当用户发布动态时,先开启一个事务插入 “posts” 集合的新动态文档,提交事务后,再开启另一个事务更新 “users” 集合中的发布动态计数。这样,不同用户发布动态时,插入 “posts” 集合的操作可并发执行,更新 “users” 集合计数操作也可并发执行,大大提升了并发性能。同时,由于每个事务内操作对单个文档的原子性,数据一致性也能得到保证。
- 字段级锁优化(假设场景):若 “users” 集合文档结构复杂,除了发布动态计数,还有其他如粉丝数、关注数等字段。在更新发布动态计数时,可确保更新逻辑不会与其他字段更新逻辑冲突,使得不同事务可并发更新不同字段,进一步提升并发性能。例如,一个事务更新发布动态计数,另一个事务更新粉丝数,只要更新逻辑独立,即可并发执行。