Linux 是多任务的操作系统,也就是说在同一时间里可以同时有许多的线程在执行,所以,很有可能某个线程在依序读取inode list,同时却又有另一个在inode list 里加入新的inode,这会造成inode list 的不稳定。
所以,在 Kernel 里,我们需要一个机制,可以使得当我们在修改某个重要的结构时,不能被中断,即使被中断了,这个资料结构由于还没修改完,别的线程也都不能去读取和修改它,这个机制就叫做锁。Linux Kernel 提供多种锁机制支持线程同步,常用的如mutex和spinlock。
Mutex为例解读锁机制
Mutex是属于sleep-waiting类型 的锁。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和Core1上。当线程A想要通过mutex得到一个临界区的锁时,如果这个锁正被线程B所持有,那么线程A就会被阻塞(bolcking),Core0 会在此时进行上下文切换(Context Switch),这样Core0就可以运行其他的任务(例如另一个线程C)而不必进行忙等待。
存储介质进化推动去锁运动
锁是一把双刃剑,一方面锁可以处理多个线程的同步问题;另一方面大量的锁会影响到系统整体性能,这里对系统性能的影响体现在两个方面。首先锁之间的竞争会影响CPU本身的性能,使得处理器本身的执行效率降低,缓存被不断刷新;其次,大量的锁竞争会导致处理器之间无法并发运行。
锁的存在降低了系统性能,但是在传统系统中最大的性能瓶颈并不在软件上,而在于磁盘。传统机械硬盘的延迟一般为100ms,软件层引入的延迟<1ms,因此软件是否优化对系统的性能影响非常小。随着存储介质的发展,尤其是进入NVMe SSD时代,硬件的延迟<100us, 此时软件层面的性能优化就必须要提上日程了。
FlashRAID性能聚合技术突破软件瓶颈
FlashRAID从软件架构设计开始考虑了多核并发IO处理问题,通过无锁算法,在整个数据链路不存在任何竞争锁,多核并发、协同的处理IO请求,达到性能的最大化。FlashRAID多核并发处理模型如图1所示:
图1
无锁算法的基本原理是应用处理软件在访问逻辑卷时,将LBA通过HASH算法规则定位到具体的IO处理线程,IO处理线程以一定的规则独立处理IO请求。不同IO处理线程对应的逻辑地址完全不同,因此不存在任何竞争关系。由于多核处理器的协同工作,IO处理性能随处理器数量线性增加而线性增加。
实测数据证明性能聚合技术价值
随机读 IOPS随FlashRAID IO Handler数量增加而增加
测试环境:
图4
单块SSD在IO Patter为随机读情况下的性能为700000 IOPS。4块SSD的理论随机读性能IOPS为4*700000 = 2800K。
图5
如图5所示在IO Handler< 系统物理core数目(28)时,性能随FlashRAID IO Handler数量增加而增加;在IO Handler从28(物理core数量)增加到56(超线程后的core数量)的过程中,性能增加得比较缓慢,说明系统性能和实际core数目更密切相关。IO Handler为56时, 性能为2600K,接近理论上限。
带宽随FlashRAID IO Handler数量增加而增加
测试环境:
单块SSD在顺序读带宽为2GB/s, 顺序写带宽为800MB/s。
图7
如图7所示顺序读写性能在达到峰值之前, 均随FlashRAID IOHandler数量增加而增加。最终顺序读写带宽都接近理论上限。