Idea - 双写缓冲区
双写缓冲区
概述
概念:在服务器开发中 通常的做法是把逻辑处理线程和IO处理线程分离。
- I/0处理线程:负责网络数据的发送和接收,连接的建立和维护。
- 逻辑处理线程:处理从IO线程接收到的包。
通常逻辑处理线程和IO处理线程是通过数据队列来交换数据,就是生产者--消费者模型。这个数据队列是多个线程在共享,每次访问都需要加锁,因此如何减少互斥/同步的开销就显得尤为重要。可以通过双缓冲队列来优化这种场景。
下面是几个应用场景
MySQL中的 Doublewrite Buffer Files
- MySQL应用:双写缓冲区,innoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。
异步日志系统
使用消息队列实现,生产者写入日志,提供给消费者来读取日志,写入磁盘。
存在问题:
- 消费者从消息队列每读取一条日志信息就写入文件系统,但是写文件操作是很耗时的。
- 写日志和读日志都需要上锁影响效率。(至少有写日志和读日志两个线程)
采用双写缓冲区
- 第一缓冲区,接收应用程序高速写日志请求
- 第二缓冲区,读取日志,写入磁盘(缓冲区满后一次性写入磁盘,提高效率)
备注:双写缓冲区默认一个线程写日志,一个线程读日志,如果多个线程同时去读写也会存在加锁问题。
特点:两个缓冲区各自处理,互不干扰;通过交换指针的方式实现两个缓冲区的功能互换。(仅交换缓冲区需加锁)
扩展:日志来不及写,怎么处理?
针对双写缓冲区,日志太快,写日志请求的缓冲区已满,但是写文件的缓冲区还没写完,没办法交互缓冲区的问题?
解决方法:多块当前缓冲区 + 多块备用缓冲区,程序动态调整当前缓存区和备用缓冲区的数量。