Idea - 双写缓冲区

双写缓冲区

概述

概念:在服务器开发中 通常的做法是把逻辑处理线程和IO处理线程分离。

  • I/0处理线程:负责网络数据的发送和接收,连接的建立和维护。
  • 逻辑处理线程:处理从IO线程接收到的包。

通常逻辑处理线程和IO处理线程是通过数据队列来交换数据,就是生产者--消费者模型。这个数据队列是多个线程在共享,每次访问都需要加锁,因此如何减少互斥/同步的开销就显得尤为重要。可以通过双缓冲队列来优化这种场景。

下面是几个应用场景

MySQL中的 Doublewrite Buffer Files

  • MySQL应用:双写缓冲区,innoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

参考:MySQL进阶 - InnoDB引擎

异步日志系统

使用消息队列实现,生产者写入日志,提供给消费者来读取日志,写入磁盘。

存在问题:

  • 消费者从消息队列每读取一条日志信息就写入文件系统,但是写文件操作是很耗时的。
  • 写日志和读日志都需要上锁影响效率。(至少有写日志和读日志两个线程)

采用双写缓冲区

  • 第一缓冲区,接收应用程序高速写日志请求
  • 第二缓冲区,读取日志,写入磁盘(缓冲区满后一次性写入磁盘,提高效率)

备注:双写缓冲区默认一个线程写日志,一个线程读日志,如果多个线程同时去读写也会存在加锁问题。

特点:两个缓冲区各自处理,互不干扰;通过交换指针的方式实现两个缓冲区的功能互换。(仅交换缓冲区需加锁

扩展:日志来不及写,怎么处理?

针对双写缓冲区,日志太快,写日志请求的缓冲区已满,但是写文件的缓冲区还没写完,没办法交互缓冲区的问题?

解决方法:多块当前缓冲区 + 多块备用缓冲区,程序动态调整当前缓存区和备用缓冲区的数量。

参考资料 (opens new window)