【TiKV / HTAP 内核】悲观事务与 ResolveLock:TTL、死锁检测边界,纠正「TiKV 无锁」

💡 原文中文,约10800字,阅读约需26分钟。
📝

内容提要

TiKV 的悲观锁默认使用内存路径以减少加锁延迟,但在非计划的 Leader 切换时可能会丢失锁。锁的 TTL 动态调整,长事务依赖心跳续期。死锁检测采用集中式方案,Leader 切换时清空历史依赖,存在漏检风险。TiKV 的锁机制与传统数据库相似,需纠正对其“无锁”的误解。

🎯

关键要点

  • TiKV 的悲观锁默认使用内存路径以减少加锁延迟,但在非计划的 Leader 切换时可能会丢失锁。

  • 锁的 TTL 动态调整,长事务依赖心跳续期。

  • 死锁检测采用集中式方案,Leader 切换时清空历史依赖,存在漏检风险。

  • TiKV 的锁机制与传统数据库相似,需纠正对其“无锁”的误解。

🔎

延伸解读

悲观锁的内存优化与风险

TiKV 的悲观锁通过在内存中管理锁来减少加锁延迟,但在非计划的 Leader 切换时,内存中的锁可能会丢失。这意味着在网络分区或节点故障时,事务可能会遇到意外的冲突,导致需要重试。这种设计虽然提高了性能,但也引入了潜在的风险,用户在使用时需考虑这一点。

TTL与心跳机制的动态调整

TiKV 的锁 TTL 不是固定的,而是根据事务的写入量动态调整。这种机制确保了长事务不会因为 TTL 过期而被错误清理,依赖于每 20 秒的心跳续期来维持锁的有效性。用户在设计事务时,应关注写入量对 TTL 的影响,以避免不必要的锁冲突和重试。

死锁检测的设计取舍

TiKV 的死锁检测采用集中式方案,依赖于 Leader 的选举来管理检测状态。然而,Leader 切换时会清空历史依赖,可能导致漏检。这种设计虽然简化了实现,但在高并发场景下可能会影响系统的稳定性。用户应关注这一点,尤其是在事务复杂度较高的情况下。

延伸问答

TiKV 的悲观锁是如何减少加锁延迟的?

TiKV 的悲观锁默认使用内存路径,只在 Region Leader 的内存表中加锁,避免了 Raft 提交的延迟。

TiKV 中锁的 TTL 是如何动态调整的?

锁的 TTL 根据事务的写入量动态调整,默认值为 3000ms,实际值通过公式计算得出。

TiKV 如何检测死锁?

TiKV 使用中心化的死锁检测服务,由 Leader 负责管理 wait-for-graph,检测事务间的依赖关系。

在 TiKV 中,如何处理锁的清理?

锁的清理通过客户端遇锁时的即时清理和 GC 周期性批量清理两条路径进行。

TiKV 的悲观锁与传统数据库的行锁有什么相似之处?

TiKV 的悲观锁在语义上与传统数据库的行锁几乎没有区别,都是在事务执行时显式加锁。

TiKV 中的心跳续期是如何工作的?

TiKV 的心跳续期由持有 primary lock 的事务每 20 秒发送一次,更新锁的 TTL,防止锁被误判为过期。

🏷️

标签

➡️

继续阅读