面试题答案
一键面试一致性实现机制与技术点
- 文档级原子操作:
- MongoDB在文档级别的操作是原子性的。例如,对单个文档的更新操作,要么完全成功,要么完全失败。这保证了单个文档状态的一致性。比如在更新一个用户文档中的年龄字段时,不会出现部分更新成功的情况,要么年龄字段成功更新,要么由于错误(如验证失败)保持原状态不变。
- 多文档事务:
- 两阶段提交(2PC):
- 准备阶段:在事务开始时,MongoDB会记录所有事务操作涉及的文档和操作内容。对于每个操作,它会检查操作的有效性,例如文档是否存在、更新是否符合验证规则等。如果所有操作在各个分片(如果是分片集群)上都准备成功,就进入提交阶段;否则,事务回滚。例如,在一个涉及多个文档更新的转账事务中,会先检查源账户余额是否足够等条件。
- 提交阶段:当所有分片都准备好后,协调者会向所有分片发送提交指令,各个分片持久化事务操作。如果某个分片提交失败,协调者会通知其他分片回滚,以确保事务的一致性。
- 日志记录:
- MongoDB使用预写式日志(WAL)。在事务操作过程中,操作记录会先写入WAL日志。即使在事务提交前系统崩溃,重启后可以通过重放WAL日志恢复事务状态,保证一致性。例如,在一个复杂的多文档事务中,WAL日志记录了每个操作步骤,确保在故障恢复时可以重新执行或回滚事务。
- 两阶段提交(2PC):
- 快照隔离:
- 在事务执行期间,MongoDB会为事务创建一个数据快照。这意味着事务内读取的数据在事务开始时就已经确定,不受其他并发事务的影响。例如,在一个事务中多次读取某个集合的数据,无论其他事务在期间如何更新这些数据,该事务看到的数据都是事务开始时的快照版本,从而保证了事务内数据读取的一致性。
- 读一致性:
- 线性一致性读:通过设置读偏好为线性一致性,可以确保读取操作返回的是最新已提交的数据。MongoDB会在读取时等待所有未完成的写入操作完成,从而保证读取到的数据与最近提交的事务状态一致。例如,在一个高一致性要求的金融交易系统中,读取账户余额时希望确保读到的是最新已完成转账事务更新后的余额,就可以使用线性一致性读。
- 因果一致性读:在分布式环境下,因果一致性读保证了读取操作能反映出因果相关的写入顺序。例如,如果事务A更新了文档X,然后事务B基于文档X的更新结果进行操作,因果一致性读能确保事务B读取到事务A更新后的文档X状态,维护了操作之间的因果一致性。