昨天谈了一个数据库与NUMA内存的问题,实际上对于大多数应用场景而言,NUMA的远程内存在性能上不是一个特别大的问题,目前的主要商用数据库也都针对NUMA的内存架构做了优化,开源和国产数据库也正在这方面做一些优化工作。目前NUMA内存最大的影响是产生不必要的换页,因而有些国产数据库官方建议关闭SWAP。其实简单的关闭SWAP并非一个最佳的选择,因此昨天写了这篇文章。
另外一个出发点是针对目前的信创CPU,有些信创服务器的NUMA远程内存延时是本地内存的5倍甚至更高,据说有的高达10倍,这种情况下,如果数据库产品不针对NUMA内存架构做优化,那么简单的从X86迁移过去,性能还是会出现明显的下降的。
第一次了解内存条不能瞎配是几年前搞数据库一体机的时候,当时一体机的压测性能到了某个水准就再也上不去了,在数据库层面,存储层面做了大量的优化,效果还是不明显。后来INTEL的朋友提醒我们,我们的服务器内存配置为512G,可能不平衡,改为384G试试。当时我还觉得奇怪,减少内存条性能还能提高?不过重新调整内存条后,各种指标确实有10%左右的提升。
其中的主要原理是CPU和内存是通过内存控制器的通道来交换数据的,如下图,DIMM内存是一条条的插到内存插槽里的,而内存插槽是连接到内存控制器上的。

比如说skylake CPU支持2个内存控制器,每个内存控制器有3个通道,每个通道可以插两条内存条。只有当内存是按照平衡的方式插入到内存插槽中的时候,服务器的内存访问性能才能达到最佳。下面是一组平衡插法的示意图:

其中5个内存条是无法达到平衡的,后面有些图省略掉了,7-11根内存条也是无法达到平衡的,12根内存条可以达到平衡。如果内存不平衡,对性能有多大影响呢?下面是一组数据:这是一个8 DIMM插槽的单路服务器上测试获得的数据(大家注意,这个CPU不是skylake,而是早期的一款CPU的数据,仅用来说明这个问题),可以看出插2根内存条的时候,内存带宽只有35%的理论带宽,4根时候可以达到67%,6根的时候(满配)可以达到接近理论带宽,8根的时候效果最差,只有34%:

其实服务器上的内存插槽并不是说插满了,服务器就能获得最佳的性能,对于内存吞吐量要求不高的系统,插满内存条确实是一个最好的选择,而对于某些内存吞吐量要求极高的场景,要根据内存通道数平衡插内存才会有较好的效果。下面是一台两路服务器(12 DIMM插槽)上获得的数据:

从上面的数据可以看出,按照最平衡的模式配置内存,可以达到接近100%的访问带宽,而最差的情况只有1/3的访问带宽。我们配置内存的时候喜欢按照16的倍数,比如256G/512G/1TB,而从上面的测试数据看,情况十分糟糕。如果CPU是6个内存通道的,那么性能最佳的是6的倍数配置的内存条,而按照16条内存条配置的系统性能最差。我们经常看到配置了1TB内存的两路服务器,其内存带宽只能达到34%。下面是DELL公司针对SKYLAKE的一个测试数据:
从上面的图上我们可以看出,针对任何一种SKYLAKE CPU,12条内存条和16条内存条的性能差异是相当大的。当然实际使用的情况并不一定如上述的数据那么糟糕,有可能我们的内存带宽并不需要达到那么高,对于那些不追求极致性能的普通的应用,或者说对于内存吞吐量要求并不大的系统来说,平时的影响并不大,不过对于内存访问要求较高的系统来说,更高的内存带宽对系统性能关系重大。
对于某些系统来说,提供足够的内存就可以了,那么也不用特别纠结。
其实我们日常也会遇到很多大内存吞吐量的需求。最典型的就是内存数据库,报考REDIS、SPARK这样的数据库,内存访问性能会对访问性能有很大的影响。另外一些大型的数据库应用场景的内存访问是十分频繁的,大型的负载较高的数据库应用也会因为土豪不理性的消费而多花了钱,没有买到所需要的性能。




