对于一个高并发的实时系统,低延迟-高吞吐是设计首要考虑的问题,对称多处理器为程序并发提供了硬件平台,当在多线程处理环境中,对一些公共资源的读写难免要互斥,谁获得锁,是随机的,其他的CPU core只能在spinlock下不停的尝试,耗费资源,我们应该将资源用于我们业务系统, 不能把性能浪费在不停的等待,尝试,或者等待操作系统“翻牌子”的无用操作上。

当我们试图建立一个高度可扩展的系统,最大的一个限制是:对同一个资源会有多个竞争写操作。 计算机科学归结为2个基本的方法:一是提供资源的互斥锁,另一种是采取乐观的策略。

Mutual Exclusion互斥

  相互排斥是某个时间对同一个受保护资源保证只有一个写操作,这是通过锁策略实施的。锁策略需要一名仲裁员,通常这个仲裁员是来自操作系统内核,当发生争夺时它决定谁能获得锁,以及以什么顺序获得。这是一个非常昂贵的过程,通常我们需要更多的CPU循环实现我们的业务逻辑,而不是做这些“家务事”。对于那些等待进入临界区,提前进行Mutual的还必须排队,排队效果(Little’s Law)导致延迟变得难以预测,最终制约了吞吐量。这是一种堵塞Blocking做法。

Optimistic Concurrency Control乐观并发锁

  比如Hibernate或JPA都有乐观锁策略,见:JPA/Hibernate:基于版本的乐观锁并发控制,包括MongoDB的乐观锁

  乐观的策略是:保留有数据的一个副本,当修改数据时,如果在此期间原本尚未发生变化,那么复制数据的变化覆盖原本。如果在此期间原本发生的变化,你重复这个过程,直到成功为止。

  这种重复过程中增加争夺可能性,会造成排队的效果,就如同相互排斥锁一样。现实中源代码控制系统如Subversion或CVS都在使用这种算法。乐观的策略能够在争夺数据情况下使用,但在争夺一些硬件资源下却工作得不怎么好,因为你不能获得一个硬件资源的副本! 也许只有通过CAS指导硬件完成执行原子数据的变化。

 笔记注:它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。乐观事务控制最早是由孔祥重(H.T.Kung)教授提出[1]

乐观并发控制多数用于数据争用不大、冲突较少的环境中,这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据的成本,因此可以获得比其他并发控制方法更高的吞吐量