暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ring buffer机制

原创 necessary 2025-06-07
115

简介

最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但是其同样入参在不同时间执行时间却相差甚远。进行 SQL 优化并不能对其根除,查看了一下 shared_buffers 才 12GB。SQL 查询得表 size 就有 16GB 且没有所有和分区剪裁,也没有索引。这里就涉及得内存得环形缓冲机制了

一、什么是环形缓冲区?

环形缓冲区(ring buffer 又称循环缓冲区,Circular Buffer)是一种逻辑上首尾相接的固定大小数组结构,主要用于数据的连续读写操作。它具备高效、无碎片、空间可复用等特点

在结构上,它依赖两个核心指针:

写指针(write pointer):指向即将写入数据的位置。

读指针(read pointer):指向即将读取数据的位置。

由于缓冲区是固定大小的,写入末尾之后指针会回绕至起点,形成 “环形”行为。

二、运行机制

环形缓冲区采用一段固定长度的数组作为底层结构。其核心思想在于逻辑上将数组首尾相连,实现空间的循环复用。
例如,一个长度为 8 的缓冲区:

物理空间:  [0] [1] [2] [3] [4] [5] [6] [7] 
逻辑行为:       ↑                   ↑
             read_ptr          write_ptr

当 write_ptr == 7 写入后,下一步会跳转回 0 位置继续写入,实现回绕(wrap around)。

ring-buferr 机制

  1. 写入逻辑
    当有数据需要写入时:
    如果 (write_ptr + 1) % size != read_ptr:
    将数据写入 write_ptr 所在槽位
    write_ptr 前进一格(可回绕)
    否则:
    缓冲区已满(可能阻塞、丢弃或覆盖旧数据)
  2. 读取逻辑
    当有消费者读取时:
    如果 write_ptr != read_ptr:
    读取 read_ptr 所在槽位的数据
    read_ptr 前进一格(可回绕)
    否则:
    缓冲区为空(可能阻塞或返回空)
  3. 状态判断条件
    状态 条件表达式
    空 read_ptr == write_ptr
    满 (write_ptr + 1) % size == read_ptr

三、触发机制说明

触发事件 条件 后果
缓冲区满 写指针追上读指针 阻塞 / 丢弃 / 覆盖旧数据三选一
缓冲区空 读指针追上写指针 返回空数据或阻塞等待
回绕 (wraparound) 指针到达数组尾部 指针回到头部,形成循环

四、优缺点分析

✅ 优势

优点 说明
高效空间复用 写满后继续回绕,无需频繁申请 / 释放内存
无内存碎片 顺序访问性能好,适合嵌入式与内核编程
天然的 FIFO 行为 写入顺序即为读取顺序,适合日志、流式数据
可并发使用 (配合锁或无锁结构) 在生产者-消费者模型中高效、安全

❌ 劣势

缺点 说明
容量固定 超出容量需设计溢出策略 (覆盖 / 丢弃 / 阻塞)
不适合随机访问 只支持顺序读写,随机定位困难
指针管理复杂 需谨慎维护 read_ptr 和 write_ptr 的关系
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论