在 WhatsApp 这样超高并发、全球分布的系统中,锁竞争(Lock Contention)和死锁(Deadlock)是性能和可用性的巨大杀手。传统的、基于行锁或表锁的关系型数据库在高并发场景下极易遭遇这些问题。因此,WhatsApp 的策略是从根本上避免或最小化对传统锁机制的依赖,通过架构设计来应对并发问题。
WhatsApp 处理高并发下锁竞争和死锁的核心策略
WhatsApp 主要依赖于其所使用的**分布式 NoSQL 数据库(如 Apache Cassandra 或 ScyllaDB)**的特性,以及事件驱动、异步处理的设计模式。
1. 避免使用传统锁机制 (Architecting Away from Traditional Locks)
分布式 NoSQL 数据库的设计理念: Cassandra 等数据库被设计为高可用和高写入吞吐。它们通过分区(Partitioning)和多副本(Replication)来分散负载,而不是依赖全局锁。
最终一致性模型: WhatsApp 优先选择可用性(Availability)和分区容错性(Partition Tolerance),采用**最终一致性(Eventual Consistency)**模型。这意味着它不会为了立即的强一致性而牺牲性能和可用性,从而避免了大量因严格一致性要求而产生的锁。
2. 数据分区/分片 (Data Partitioning/Sharding)
核心策略: 这是避免锁竞争最直接的方法。WhatsApp 的数据(用户、消息、群组等)会根据其唯一标识符(如用户 ID、会话 ID)进行水平分区(sharding),将数据分布到数千个节点上。
减少冲突域: 大多数操作(例如,发送一条消息、更新用户状态)都只涉 捷克共和国 whatsapp 数据库 及特定的分区。操作只会在该分区所在的节点上进行。由于不同的分区分布在不同的节点上,操作在不同的分区之间不会产生锁竞争。即使在同一分区内,Cassandra 也是非阻塞写入的。
3. 消息队列 (Message Queues - Decoupling and Serialization)
异步处理: 消息发送后,会先写入到高吞吐的持久化消息队列(如 Apache Kafka)。消息队列作为生产者和消费者之间的缓冲区和解耦层。
缓解直接竞争: 大量的并发写入请求首先被序列化到消息队列中。后端服务从队列中异步消费消息进行处理。这消除了前端服务与后端数据库之间直接、高频的锁竞争。写入到队列本身是追加操作,并发冲突小。
分区内部序列化: Kafka 的分区机制可以确保在单个分区内,消息是按顺序处理的,这在一定程度上减少了对共享资源的并发访问。
4. 幂等性 (Idempotency)
避免重复操作的副作用: 所有操作(特别是写入和状态更新)都设计成幂等的。这意味着即使由于网络重试或其他原因导致同一个操作被执行多次,其最终结果也与执行一次相同。
如何帮助避免锁: 幂等性允许系统在不使用复杂锁的情况下安全地重试操作。如果一个操作因为竞争失败,它可以被安全地重试而不会导致错误或数据重复,从而减少了对锁的依赖。每条消息都有唯一的 ID。
5. 乐观并发控制 (Optimistic Concurrency Control, OCC)
冲突检测而非预防: 对于一些需要更强一致性或事务性保证的场景(例如,更新用户资料、群组配置等),WhatsApp 可能会使用数据库提供的乐观并发控制机制。
Compare-and-Swap (CAS): Cassandra 的 LightWeight Transactions (LWT) 就是基于 Paxos 协议实现的 CAS 操作。它允许在写入前检查当前数据是否符合预期状态。如果冲突发生,写入会失败,应用程序需要重试。
避免死锁: OCC 不使用悲观锁,因此从根本上避免了死锁的发生。它通过冲突检测和重试来解决并发问题,而不是通过阻塞。
6. 去中心化冲突解决 (Decentralized Conflict Resolution)
最后写入胜出 (Last Write Wins, LWW): Cassandra 的默认冲突解决策略。如果两个并发写入操作对同一键进行冲突更新,数据库会根据写入的时间戳来决定哪个写入是“最新”的并保留它。这是一种无锁的冲突解决方式,但需要应用程序层面理解其含义(可能丢失一个“旧”的并发更新)。
CRDTs (Conflict-free Replicated Data Types): 虽然不适用于所有数据,但对于某些特定数据类型(如计数器、集合),可以使用 CRDTs。CRDTs 允许在分布式环境中并发更新,并在合并时保证结果的一致性,无需复杂的协调或锁。
7. 避免复杂分布式事务 (Avoiding Complex Distributed Transactions)
WhatsApp 的数据模型和业务流程被设计为尽可能避免需要跨多个不同服务或数据库的复杂分布式事务。操作被分解为小的、独立的、最终一致的步骤。
通过上述策略,WhatsApp 从架构层面就避免了传统关系型数据库中常见的锁竞争和死锁问题。它优先选择高可用和吞吐量,通过数据分区、异步处理、幂等操作和乐观并发控制等手段,来高效地管理高并发下的数据一致性。