绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
分布式思考:锁是个麻烦,限制它
2022-04-15 20:07:29

## 单机单进程下的锁

我们先看基本的操作系统下,一个进程用到的锁。

在知乎上,我有几个回答,可以作为预备知识,

锁的本质

多线程竞争锁时,阻塞等待锁释放是如何实现的?

线程的切换还能让线程快吗?

为什么用互斥锁而不是屏蔽exception/interrupt防止多线程同时对同一公共资源进行读写?

简而言之,锁是让多线程并发时,保证进程数据结果的一致性。同时,在保证一致性的基础上,提高性能Throughput。

在数据库系统里,这个操作系统锁,是作为底层锁的基本工具,称之为Latch。

## 单机下的数据库上层锁

数据库系统有自己一套更高层的基于上面Latch的锁机制,针对的对象是数据库内部的对象,比如:行、页、表和索引、数据库。按特性又区分为读写锁、共享和独占锁、意向锁。也具有操作系统锁不具备的一些特性,比如:死锁的监测和恢复。

我不是一个这方面有经验的程序员,我的理解是:

和操作系统锁一样,单机数据库锁,也是为了保证数据库数据的一致性,在此基础上,提高数据库事务Transaction的并发和吞吐Throughput。

即锁的本质没有变。

1. 由于并发冲突,需要保护共享资源的一致性

2. 在保证一致性的基础上,并发提高Throughput

更重要的是,Relational数据库还需要对数据做出ACID保证。而ACID里面很多特性,是基于锁的。比如:经典的2PL(一种悲观锁),可以支持Isolation到Serializable级别。

# 分布式下,锁是个大的麻

和基于单进程的操作系统锁的单机数据库的锁不同,到了分布式系统里,我们会发现锁不好用。

我们来看分布式锁对于锁的两个目的(本质)可能带来的损害

### 锁是为了保证数据(共享资源)的一致性

如果是单进程的操作系统锁,很多东西你不用考虑。而到了分布式,必须用到网络,也就必须用到通信。

类似LPC(local procedurer call)和RPC(remote procedure call)的差别。

LPC下,你的返回结果一定是预先定义的返回值(deterministic),比如1+1,一定返回结果2,而且Latecny基本是固定的。即它是稳定的、可靠的。

RPC下,你的返回结果还可能包括网络故障、Timeout(因为受限于另外一个机器上的另外一个进程),Latency没有什么保证,即它不是稳定的,也不是可靠的。

因此,分布式锁可能被一个死进程永远霸占。如果你加入Lease属性(即锁有timeout),那么又可能出现两个进程都拥有分布式锁的情况(比如:一个进程GC了)。所以,为了保护资源,我们还必须加入Token防护。一个Redis的例子可以作为参考:怎样实现redis分布式锁?

### 锁在保证数据一致性的前提下,希望提高并发

我们用锁,还有一个目的,是为了提高并发。

大家可以参考我的一个文章:单线程就比多线程性能差吗?不一定

当我们用操作系统锁,如果只是简单的CAS,我们只付出20ns的代价,如果是mutex并有线程切换,也不过几百us的代价。这对于磁盘这个动不动就以ms计价的介质而言,这个成本是划算的。所以,能提高并发。

但到了网络上,首先是有Round Trip的通信损耗(一般是200us),而且,还需要依赖其他进程处理锁的速度。比如:另外一个进程拿到锁,处理任务,然后通过网络释放锁,如果是秒级操作,那么,我们的进程也必须等待这个秒级Latency,而且由于网络特性和多机环境,这个还不可靠。

所以,在分布式下,用分布式锁,不仅很难提高并发性,反而有可能损害并发性。

### 分布式锁还需要自己给自己提供分布式保护

分布式下,我们还要考虑分布式锁本身的健壮,即万一提供锁的机器死了怎么办?

提供一套一致性很强的分布式锁是非常困难的,Redis的RedLock还犯了错误。etcd等提供了,但性能测试显示并不好。

因为:分布式下一致性是有代价的

## 结论

在分布式系统下,对于单机,可以继续用它自己的锁系统,但一旦这个锁要扩展到跨进程、跨网络、参与集群一致性,请谨慎使用。

我的建议:对于分布式锁,不到必须用,尽量不用。

其实很多数据一致性的问题,不用分布式锁,也可以解决。我曾经回答一个关于[卖销售的问题],在这个问题上,我觉得根本不需要分布式锁,一个简单的Relational Database就可以解决。因为,我们可以将单做shard,将工作负载大的任务分配给每个前端node去做,这也是一种分布式(shard),只需要单点的Relational DB(可做强sync cluster Relational Database)去保证一个单分配数据的完整一致即可。

那么对于分布式处理,我们不用锁去保证数据的一致性,那我们是否就不能保证整个集群的数据的可靠性,同时维持一定性能(甚至不能scale-out)?

不是的,请看下一页。

分享好友

分享这个小栈给你的朋友们,一起进步吧。

分布式思考和实践
创建时间:2022-04-14 14:15:30
关于分布式在数据库领域的应用的一些思考以及一些程序应用的开发
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • szstonelee
    栈主

小栈成员

查看更多
  • miemieMIA
  • LCR_
  • jinchuan
  • MrSun
戳我,来吐槽~