当试图构建一个高度可伸缩的系统时,可伸缩性的最大限制是让多个写入器争夺任何数据或资源。当然,算法可能不好,但让我们假设它们有一个合理的大O符号,所以我们将重点放在系统设计的可扩展性限制上。我一直看到人们只是接受拥有多个写入器作为标准。计算机科学中有很多研究来管理这种争用,归根结底是两种基本方法。一种是在变异的同时,对争用的资源提供互斥。另一种是采取乐观策略,如果在创建新副本时底层资源没有更改,则交换更改。互斥互斥是一种一次只有一个编写器可以访问受保护资源的方法,通常使用锁定策略来实现。锁定策略需要仲裁器(通常是操作系统内核)在竞争发生时介入,以决定谁获得访问权限以及以什么顺序。这可能是一个非常昂贵的过程,通常需要比实际事务应用于业务逻辑的CPU周期多得多的CPU周期。这可能是一个非常昂贵的过程,通常需要比实际事务应用于业务逻辑的CPU周期多得多的CPU周期。这可能是一个非常昂贵的过程,通常需要比实际事务应用于业务逻辑的CPU周期多得多的CPU周期。在执行变异之前必须排队,而这种排队效应(Little';S定律)会导致延迟变得不可预测,并最终限制吞吐量。乐观并发控制乐观策略包括获取数据的副本,对其进行修改,如果在此期间数据没有发生变化,则将更改复制回来。如果在此期间发生了更改,则重复此过程,直到成功为止。此过程的重复会随着争用而增加,因此会导致排队效应,就像互斥一样。如果您使用的是源代码控制系统,如Subversion或CVS,然后你每天都在使用这个算法。乐观的策略可以处理数据,但不能很好地处理硬件等资源,因为你不能复制硬件!*通过硬件提供的CAS指令来自动执行数据更改的能力是可能的。大多数锁定策略由更改锁定状态或互斥原语的乐观策略组成。管理争用与进行实际工作CPU通常可以在每个周期处理一条或多条指令。例如,现代英特尔CPU核心每个都有6个执行单元,它们可以并行地执行算术、分支逻辑、字处理和存储器加载/存储的组合。如果在进行工作时CPU核心导致高速缓存未命中,并且必须转到主存储器,它将停滞数百个周期,直到内存请求的结果返回。为了尝试和改进,CPU将猜测内存请求将返回什么以继续处理。*如果发生第二次未命中,CPU将不再推测,而只是等待内存请求返回,因为它通常不能将推测执行的状态保持在2个高速缓存未命中以上。管理高速缓存未命中是扩展我们当前一代CPU性能的最大限制。现在,这与管理争用有什么关系?很好,如果两个或更多线程使用锁来提供互斥,则它们最多将前往L3高速缓存,或通过套接字互连,以使用CAS操作来访问锁的共享状态。在最好的情况下,当无争用时,这些锁/CAS指令耗费10秒的周期,此外,它们导致CPU的无序执行被挂起并且加载/存储缓冲器被刷新。在最坏的情况下,冲突会发生,内核将需要介入并使一个或多个线程处于休眠状态,直到锁被释放。*对阻塞线程的重新调度将导致高速缓存污染。如果线程在另一个具有冷高速缓存的内核上重新调度,导致许多高速缓存未命中,情况可能会更糟。*对于争用很多的数据,很容易陷入这样一种情况,即系统在管理争用上花费的时间比实际工作多得多。下表给出了在程序中管理争用的基本成本的概念。对于高度争用的数据,很容易陷入这样一种情况:系统在管理争用上花费的时间比实际工作多得多。下表给出了在程序中管理争用的基本成本的概念。别管主内存了。这张表说明了在2.4 Ghz的韦斯特米尔处理器上使用各种技术将64位计数器递增5亿次的成本。我可以听到人们回来说,“但这只是一个微不足道的例子,现实世界的应用程序并不是那么争用的”。这是真的,但请记住,现实世界的应用程序有更多的状态,当上下文切换发生时,您认为高速缓存中所有的热状态会发生什么?通过测量基本的争用成本,可以推断出争用的基本成本,这是可能的,但请记住,现实世界的应用程序有更多的状态,当上下文切换发生时,您认为高速缓存中所有的热状态会发生什么?通过测量基本的争用成本,可以推断出争用的基本成本