SQL Server 环形缓冲区(Ring Buffer) -- 介绍

  1. 云栖社区>
  2. 博客>
  3. 正文

SQL Server 环形缓冲区(Ring Buffer) -- 介绍

技术小甜 2017-11-08 13:32:00 浏览683
展开阅读全文

以下关于Ring Buffer的介绍转载自:

http://zh.wikipedia.org/wiki/%E7%92%B0%E5%BD%A2%E7%B7%A9%E8%A1%9D%E5%8D%80

 

环形缓冲区(Ring Buffer),也称作圆形缓冲区(Circular Buffer),也称作圆形队列(Circular Queue)循环缓冲区(Cyclic Buffer),是一种数据结构用于表示一个固定尺寸、头尾相连的缓冲区,适合缓存数据流。

 

圆形缓冲区的一个有用特性是:当一个数据元素被用掉后,其余数据元素不需要移动其存储位置。相反,一个非圆形缓冲区(例如一个普通的队列)在用掉一个数据元素后,其余数据元素需要向前搬移。换句话说,圆形缓冲区适合实现先进先出缓冲区,而非圆形缓冲区适合后进先出缓冲区。

 

圆形缓冲区适合于事先明确了缓冲区的最大容量的情形。扩展一个圆形缓冲区的容量,需要搬移其中的数据。因此一个缓冲区如果需要经常调整其容量,用链表实现更为合适。

 

写操作覆盖圆形缓冲区中未被处理的数据在某些情况下是允许的。特别是在多媒体处理时。例如,音频的生产者可以覆盖掉声卡尚未来得及处理的音频数据。

 

以下关于Ring Buffer的译文转载自:

http://www.cnblogs.com/shanyou/archive/2013/02/04/2891300.html

原文地址为:

http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html

 

Ring Buffer 究竟是什么?


正如名字描述那样 - 它是一个环 (圆形,首尾相接的),你可以把它当作一个缓存 (buffer),用来在一个线程上下文与另一个线程上下文之间传递数据。

clip_image002

(好吧,我是用 Paint 画的。我尝试画草图,希望强迫症没有掺和进来要求我画出完美的圆和直线)。


所以基本上 Ring Buffer 就是拥有一个序号指向下一个可用元素的数组。

clip_image004

 

如果你持续向 buffer 中写入数据(应该也会从里面读数据),这个序号会一直增长,直到绕过整个环。

clip_image006

 

要找到数组中当前序号指向的元素,你可以用 mod 运算。

sequence mod array length = array index

因此对于上面的 Ring Buffer,这个算法就是(用 JAVA 的 mod 语法):12 % 10 = 2。很简单。

其实图片里画着 10 个元素完全是一个意外。2 的 N 次方个元素会更好,因为计算机是用二进制思考的。

 

接下来呢?


如果你从 Wikipedia 查到 Circular Buffers?,你会看到它与我们的实现方式有一个重要的差别-没有指向末尾的指针。我们只有下一个可用的序号。这是刻意的-选择 Ring Buffer 的根本原因是需要支持可靠的消息通信。我们需要把服务发出的消息存储起来,那么当另一个服务发来一个 NAK (拒绝应答信号)?? 说他们没有收到消息的时候,我们可以重新发送给他们。


Ring Buffer 看起来很理想。它用序号来指出 buffer 的末尾在哪里,而且当它收到一个 NAK 信号的时候,可以重发从那一点到当前序号之间的所有消息:

clip_image008


我们所实现的 Ring Buffer 与传统队列的区别是:buffer 里的对象不会被销毁-它们留在那儿直到下次被覆盖写入。这是与 Wikipedia 上的版本相比我们的实现不需要尾指针的原因。在我们的实现中,确定 Ring Buffer 是否重叠的工作,是由数据结构之外来完成的(这是生产者与消费者行为的一部分-如果你来不及等我写博客说明它,可以自己检出 Disruptor 代码??)。

 

Ring Buffer 这么棒是因为...?


我们使用 Ring Buffer 这种数据结构,是因为它给我们提供了可靠的消息传递特性。这个理由就足够了,不过它还有一些其他的优点。

 

首先,Ring Buffer 比链表要快,因为它是数组,而且有一个容易预测的访问模式。这很不错,对 CPU 高速缓存友好 (CPU-cache-friendly)-数据可以在硬件层面预加载到高速缓存,因此 CPU 不需要经常回到主内存 RAM 里去寻找 Ring Buffer 的下一条数据。

 

第二点,Ring Buffer 是一个数组,你可以预先分配内存,并保持数组元素永远有效。这意味着内存垃圾收集(GC)在这种情况下几乎什么也不用做。此外,也不像链表那样每增加一条数据都要创建对象-当这些数据从链表里删除时,这些对象都要被清理掉。

















本文转自UltraSQL51CTO博客,原文链接:http://blog.51cto.com/ultrasql/1583220 ,如需转载请自行联系原作者


网友评论

登录后评论
0/500
评论
技术小甜
+ 关注