谈谈存储软件的无锁设计

面向磁盘设计的存储软件不需要考虑竞争锁带来的性能影响。磁盘存储软件的性能瓶颈点在于磁盘,磁盘抖动会引入极大的性能损耗。因此,传统存储软件的设计不会特别在意处理器的使用效率。曾经对一个存储虚拟化软件进行性能调优,在锁竞争方面做了大量优化,最后也没有达到性能提升的效果,原因就在于存储虚拟化的性能瓶颈点在于磁盘,而不在于处理器的使用效率。正因为如此,在面向磁盘设计的软件中,很多都采用单线程、单队列处理的方式,一定程度上还可以避免由于并发所引入的磁盘抖动问题。

在面向NVMe SSD设计的存储软件中,这一切正发生着变化。和传统磁盘相比,NVMe SSD具有极高的IO读写性能,不存在传统磁盘所具有的访问寻道、抖动问题。为了发挥NVMe SSD的性能,无论在软件还是在硬件上都需要采用多队列技术,通过多队列方式充分发挥NVMe SSD的性能。通常NVMe SSD控制器可以提供128个IO提交和结束队列,NVMe驱动会根据处理器的核数利用SSD控制器提供的硬件能力,实现IO的并发处理。在驱动层面,可以绑定处理器与IO队列,达到IO并发处理的效果。在这种情况下,业务线程一定要多线程并发利用处理器,才可以将NVMe SSD的多队列真正用起来。在很多情况下,业务的软件模型往往会分为计算单元和存储单元两部分。计算单元往往是多线程并发处理的模式;存储单元在传统磁盘上是单线程模式,在NVMe SSD上会变成多线程并发处理的方式。这种软件处理模型可以描述如下:

在上述软件模型中,如果Compute和IO单元通过合理的资源切分划分在一起,Compute和IO单元在同一个执行上下文中,那么整个软件的效率将会变得非常高。但是在很多情况下,计算和存储可以是两个软件模块,或者计算和存储资源无法有效的进行划分,那么在这种情况下,计算和存储线程之间需要通过消息队列进行通信。这种消息通信可以抽象成生产者-消费者模型。Compute单元是生产者;IO单元是消费者。

生产者-消费者在实现过程中需要进行同步操作。如果采用传统的锁机制实现“生产者-消费者”队列,那么存储系统的性能瓶颈将会转移到锁竞争点。锁竞争一方面使得处理器处于长时间等待或者睡眠调度的状态;另一方面由于大量的缓存无效操作使得CPU的访存效率大大降低。总的来说,锁竞争将会导致CPU使用效率的降低,从而可以看到处理器的IPC指标变得很低。

那么在上述软件模型中,如何提升处理器效率,充分发挥NVMe SSD的性能呢?这就需要考虑采用无锁设计。在多线程并发处理的场景下,难免需要在线程之间进行数据交互,为了提高CPU的效率,这种大量的线程交互可以采用无锁的方式进行同步。无锁设计需要采用特殊的算法与处理器提供的特殊指令,常用的无锁算法有采用CAS指令实现的无锁队列,该种类型的算法需要一个Dummy节点,因此存在动态分配内存的问题。为了避免动态内存分配,可以采用固定长度的无锁队列Lock-free Ring,但是会存在队列深度固定的问题。在存储系统设计中,关键路径上最好需要避免内存资源的频繁分配,另外还需要实现队列深度的可变与IO数量的流控。因此,需要根据存储系统的特征,需要设计符合自身特点的无锁算法。在最近一个存储项目中,我们创造了一种无锁生产者-消费者及无锁流控算法,采用这种算法之后,我们可以发现IO的性能可以随着CPU核数线性变化。当CPU核数越多,IO性能越高。下图是实际测试的性能与IO线程数量之间的关系图:

上图我们可以看出当IO线程数量增加到28之后,随机读性能变化不明显,并且出现了一定的性能下降。在该测试平台上,一共具备28个CPU硬核,通过超线程的方式,达到56个CPU核。从上面的实验结果来看,超线程对IO性能贡献不大。随机读性能在IO Thread数量达到8个之后,性能达到峰值。这是由于后端NVMe SSD盘性能达到了峰值。

NVMe存储系统设计面临CPU性能瓶颈的问题,如何提高CPU的IO处理效率是高性能存储系统设计必须要考虑的问题。无锁设计是提高CPU效率的一种有效手段,一个好的无锁设计需要与系统软件的设计整体考虑。

时间: 2024-10-10 09:41:44

谈谈存储软件的无锁设计的相关文章

c语言多线程缓冲队列无锁设计思路

公司里开发的一个项目需要在server端添加多线程缓冲队列,来存取数据,我也是初出茅庐没有太多经验,在网上搜集了大量资料后,终于有了一套自己的设计思路,并解决了项目里的问题,因为当时搜集资料时,发现网上这个的具体文章不是太多或者要么太复杂,要么太简陋,对于新手很难能看懂,所有我就打算将我的设计思路发出来,希望能帮助和我一样的同学朋友们,如有不足请指导!谢谢 项目需求: 两个线程,线程1接收客户端数据并有序的存入缓冲队列:线程2从缓冲队列有序的取出数据并解析插入数据库: 解决方法: 1:新建一个结

一个高性能无锁哈希表的设计和实现

无锁哈希表(Lock-Free Hash Table)是多线程编程中的理想数据结构,但是实现以及使用都需要一定的技巧.作者对此做了一个巧妙的设计实现,在现代X86平台上能取得千万次每秒的并发查找/增加/删除操作. 通过考察各种基于CAS原子操作的无锁数据结构实现,目前公认可实现无锁安全的数据结构是数组和单向队列.其他实现都一定程度上受到ABA问题的威胁.数组的实现相对于单向队列要简单,所以无锁hash table理想的选择是数组,对于冲突不拉链.但是如何解决hash冲突呢?基本思想依然是开放寻址

如何在高并发环境下设计出无锁的数据库操作(Java版本) 转载

一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Java的Disruptor就是一个很好的例子.如果用java的concurrentCollection类去做,原理就是启动一个线程,跑一个Queue,并发的时候,任务压入Queue,线程轮训读取这个Queue,然后一个个顺序执行. 在这个设计模式下,任何并发都会变成了单线程操作,而且速度非常快.现在的n

一个无锁消息队列引发的血案(六)——RingQueue(中) 休眠的艺术 [续]

目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的艺术 [续] 开篇 这是第五篇的后续,这部分的内容同时会更新和添加在 第五篇:RingQueue(中) 休眠的艺术 一文的末尾. 归纳 紧接上一篇的末尾,我们把 Windows 和 Linux 下的休眠策略归纳总结一下,如下图: 我们可以看到,Linux 下的 sched_yield() 虽然包括了

DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天晚上,DEMO基本成型,今天再加入了QWorkers来做逻辑处理进程,进一步使得逻辑处理进程更加方便和高效.今天特意写篇blog来记录我的心得与大家分享. [功能实现说明] 沿用上次的草图 目前DEMO图上的功能都已经实现.下面谈谈各部分的实现. 通信服务, 由DIOCP实现,担当与客户端的通信工作

Nah Lock: 一个无锁的内存分配器

概述 我实现了两个完全无锁的内存分配器:_nalloc 和 nalloc.  我用benchmark工具对它们进行了一组综合性测试,并比较了它们的指标值. 与libc(glibc malloc)相比,第一个分配器测试结果很差,但是我从中学到了很多东西,然后我实现了第二个无锁分配器,随着核数增加至30,测试结果线性提高.核数增加至60,测试结果次线性提高,但是仅比tcmalloc好一点. 想要安装,输入命令: git clone ~apodolsk/repo/nalloc,阅读 README文档.

无锁队列的环形数组实现

对无锁队列的最初兴趣来自梁斌同志的一个英雄帖:http://coderpk.com/. 第一次看到这个题目的时候还不知道CAS,FAA等所谓的“原子操作”,但直觉上感觉,通过对读写操作的性能优化来达到大幅提高队列性能的方法是行不通的,就算读写操作全用汇编来写,也不会和正常的read及 write有数量级上的区别.后来搜索了一下lock free data structure,才知道了关于原子操作的一些东西,同时也纠正了自己由来已久的一个错误观点:C++中的++操作和--操作都不是原子操作.这篇笔

boost 无锁队列

一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久违的Boost.Lockfree模块,本着学习的心态,将其翻译如下.(原文地址:http://www.boost.org/doc/libs/1_53_0/doc/html/lockfree.html) Chapter 17. Boost.Lockfree 第17章.Boost.Lockfree Ta

无锁编程与有锁编程的性能对比与分析

最近维护的一个网络服务器遇到性能问题,于是就对原有的程序进行了较大的框架改动.改动最多的是线程工作模式与数据传递方式,最终的结果是改变锁的使用模式.经过一番改进,基本上可以做到 GMb 网卡全速工作处理.在 性能达标之后,一度在想有没有什么办法使用更加轻量级锁,或者去掉锁的使用,为此搜索一些相关的研究成果,并做了一些实验来验证这些成果,因而就有这篇文章.希望有做类似工作的同行可以有所借鉴.如果有人也有相关的经验,欢迎和我交流. 1 无锁编程概述 本节主要对文献 [1] 进行概括,做一些基础知识的