您的位置首页>企业动态>

数据库为什么有可能喜欢Linux AIO(异步I/O)?

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解数据库为什么有可能喜欢Linux AIO(异步I O)?问题。回忆数据库可能更喜欢使用AIO

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解数据库为什么有可能喜欢Linux AIO(异步I/O)?问题。

回忆

数据库可能更喜欢使用AIO。从时间顺序上看,AIO的意思是用户应用程序发起IO请求io_submit()后,不需要等待,让后台为其做读写。之后,这个线程或者其他线程可以使用io_getevents()来同步I/O的结果。

这个AIO的一个很大的优点就是IO不会阻塞CPU的行为,有利于充分利用硬件资源,让CPU和IO并行。当然,似乎同样的动作也可以用epoll()和SIGIO来呈现。尤其是Epoll(),几乎是Linux中C10K问题解决方案的代名词。Epoll_wait()首先等待IO请求的读写发生,然后根据返回的事件发起读写请求:

事件驱动模型libevent等。似乎是事件发生并执行回调的反应器模式:

但是底层实际上是通过epoll()实现的,我们可以通过strace看到。请看我的3分钟电影:

差别很大

本质上,epoll()就是先等待IO读写发生,然后用Linux常规的read()和write() API发起IO请求。另一方面,AIO不管情况如何,直接发送IO请求,但并不等待这个请求的结束,而是让Linux后台自己完成读写。让我们看一个典型的AIO编程案例:

它通过io_submit()发出io请求,不需要等待IO结束。请稍后使用io_getevents()进行同步。在上面的代码中,io_getevents()的代码和io_submit()的代码放在一起,但实际上它们不必是同一个线程。

AIO与传统epoll()的本质区别在于,epoll()只是一种事件获取机制。获取一个事件后,后续的read()和write()仍然要走Linux的传统路线,要经过Linux内核本身的各个层次(比如页面缓存、IO调度等)。).AIO是一种IO方式,但它不像传统的Linux read()和write()那样,通过VFS式的‘all is file’接口。原生Linux本身的AIO函数是一个系统调用。Strace执行AIO操作的过程直接得到类似于下面的结果:

斯特拉斯。/aio.

.

io_setup(128,{3077799936})=0

io_submit(3077799936,1,0xbfa5e730)=1

io_getevents(-1217167360,1,1,{ 0.}空)=1

在ARM Linux的系统调用表中也可以看到:

因此,AIO可以给用户空间更多的机会,让用户空间可以根据自身的IO特点为自己量身定制IO行为。AIO也常用于直接与DIO(direct IO)结合使用,进一步绕过了内核本身的IO调度和缓存机制。

我喜欢你。

那么数据库青睐的AIO可能有哪些优势呢?

1.通过AIO,可以屏蔽Linux内核底部的页面缓存。并制定应用层缓存机制。

众所周知,Linux会为每个文件对应的索引节点创建一个address_space,并按基数树组织其页面缓存命中。页面的替换算法是LRU作为一个整体来预测页面本身的活动。这个策略当然符合Locality原则,但是不能针对用户程序本身。

特征,进行用户级的cache。

2.透过AIO(尤其是结合DIO),可以一定程度上,进行用户级别的IO scheduling。采用AIO,用户可以控制发送给内核的IO请求,从而控制谁比谁更重要。内核固然有它的IO调度算法,但是它是比较general的。

3. 透过AIO,可以进行用户级别的read-ahead和write-behind控制。

我们都知道,Linux内核本身会根据用户的读请求,去预测后续的读,从而在后续的读还没有发起的情况下,就提前预读。详见:《宋宝华: 文件读写(BIO)波澜壮阔的一生》,但是这种预读的page,并不一定是上层应用想要的page。而内核的write-behind机制,也可能导致内核累积到很多dirty数据后,出现写磁盘的突发性洪泛。现在AIO机制,我们把这些都交给用户。

4. 透过AIO,不阻塞地在前台线程,直接dispatch IO请求,带来很好的

scalability。在InnoDB里面,可以透过innodb_use_native_aio来配置使用同步的IO还是AIO,而且它有一番对比,值得细细地品读。同步IO的时候,query threads是将IO请求放入queue,由InnoDB后台线程的每个线程处理一个IO请求。而AIO的时候,query threads直接发IO请求。

With synchronous I/O, query threads queue I/O requests, andInnoDBbackground threads retrieve the queued requests one at a time, issuing a synchronous I/O call for each. When an I/O request is completed and the I/O call returns, the InnoDBbackground thread that is handling the request calls an I/O completion routine and returns to process the next request. The number of requests that can be processed in parallel isn, wherenis the number ofInnoDBbackground threads. The number ofInnoDBbackground threads is controlled byinnodb_read_io_threadsand innodb_write_io_threads.

With native AIO, query threads dispatch I/O requests directly to the operating system, thereby removing the limit imposed by the number of background threads.InnoDBbackground threads wait for I/O events to signal completed requests. When a request is completed, a background thread calls an I/O completion routine and resumes waiting for I/O events.

回忆一下

数据库可能比较倾向于使用AIO。从时序上面来讲,AIO是用户应用发起IO请求io_submit()后,它就不需要去等待,让后台给它搞定读写。之后本线程或者其他线程就可以通过io_getevents()去同步I/O的结果。

这样的AIO有一个极大的好处在于,IO不会阻塞住CPU的行为,有利于充分利用硬件的资源,有利于让CPU、IO都parallel起来 。当然,同样的动作,似乎用epoll()、SIGIO也可以呈现出来。尤其是epoll(),几乎是C10K问题解决方案在Linux的代名词。epoll_wait()先等待IO请求的read、write可以发生,而后再根据返回的事件发起读写请求:

事件驱动模型libevent等,看起来是事件到来,callback被执行的Reactor模式:

但是其底层其实也是靠epoll()来实现,这个我们透过strace就可以看出。请见我的3分钟小电影:

大不一样

epoll()本质上其实还是先等待IO的读写可以发生,而后再以Linux常规read()、write() API去发起IO请求。而AIO则是不管三七二十一,直接发IO请求,但是并不等待这个请求的结束,让Linux后台自己去完成读写。我们来看一个典型的AIO编程案例:

它是通过io_submit()把IO请求发出去之后,它并不需要等IO的结束。后面用io_getevents()去同步。上面的代码中,io_getevents()的代码与io_submit()的代码摆在一起,但是其实它们并不需要一定是同一个线程。

AIO和传统epoll()的本质区别是,epoll()等方式,它只是一个事件获取机制,获取事件后,之后的read(), write()还是要走Linux的传统路线,经过Linux内核本身的各个层次(如page cache,IO调度等)。而AIO是骨子里面,自己就是一个IO的方式,最终没有经过传统的Linux read(),write()这种"all is file"的类VFS接口。Linux native的AIO本身call的函数,本身就是系统调用。strace执行AIO动作的进程得到的直接就是类似如下的结果:

strace ./aio....

...

io_setup(128, {3077799936}) = 0

io_submit(3077799936, 1, 0xbfa5e730) = 1

io_getevents(-1217167360, 1, 1, {...}NULL) = 1

在ARM Linux的系统调用表里也可以看出:

故而,AIO可以更多地把机会交给用户空间,让用户空间根据自身的IO特点来为自己量身定制IO的行为。AIO一般也直接结合DIO(direct IO)来使用,进一步绕开内核本身的IO调度和cache机制。

我中意你

那么AIO有什么可能的优势被数据库所青睐呢?

1. 透过AIO,可以屏蔽掉Linux内核底层的page cache。而制定application-level的cache机制。

我们都知道,Linux会针对每个文件对应的inode,创立一个address_space,并以Radix树来组织它的page cache命中情况,page的替换算法,整体是LRU,预测页面本身的活跃度。这个策略,固然非常符合局部性原理(Locality),但是不能针对用户程序本身的特征,进行用户级的cache。

2.透过AIO(尤其是结合DIO),可以一定程度上,进行用户级别的IO scheduling。采用AIO,用户可以控制发送给内核的IO请求,从而控制谁比谁更重要。内核固然有它的IO调度算法,但是它是比较general的。

3. 透过AIO,可以进行用户级别的read-ahead和write-behind控制。

我们都知道,Linux内核本身会根据用户的读请求,去预测后续的读,从而在后续的读还没有发起的情况下,就提前预读。详见:《宋宝华: 文件读写(BIO)波澜壮阔的一生》,但是这种预读的page,并不一定是上层应用想要的page。而内核的write-behind机制,也可能导致内核累积到很多dirty数据后,出现写磁盘的突发性洪泛。现在AIO机制,我们把这些都交给用户。

4. 透过AIO,不阻塞地在前台线程,直接dispatch IO请求,带来很好的

scalability。在InnoDB里面,可以透过innodb_use_native_aio来配置使用同步的IO还是AIO,而且它有一番对比,值得细细地品读。同步IO的时候,query threads是将IO请求放入queue,由InnoDB后台线程的每个线程处理一个IO请求。而AIO的时候,query threads直接发IO请求。

With synchronous I/O, query threads queue I/O requests, andInnoDBbackground threads retrieve the queued requests one at a time, issuing a synchronous I/O call for each. When an I/O request is completed and the I/O call returns, the InnoDBbackground thread that is handling the request calls an I/O completion routine and returns to process the next request. The number of requests that can be processed in parallel isn, wherenis the number ofInnoDBbackground threads. The number ofInnoDBbackground threads is controlled byinnodb_read_io_threadsand innodb_write_io_threads.

With native AIO, query threads dispatch I/O requests directly to the operating system, thereby removing the limit imposed by the number of background threads.InnoDBbackground threads wait for I/O events to signal completed requests. When a request is completed, a background thread calls an I/O completion routine and resumes waiting for I/O events.

.dfma { position: relative; width: 1000px; margin: 0 auto; } .dfma a::after { position: absolute; left: 0; bottom: 0; width: 30px; line-height: 1.4; text-align: center; background-color: rgba(0, 0, 0, .5); color: #fff; font-size: 12px; content:"广告"; } .dfma img { display: block; }
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。