×

零拷贝、微秒级!Linux 双服务“实时数据”通信 5 大杀器,性能翻 10 倍指南

hqy hqy 发表于2025-12-12 01:29:29 浏览11 评论0

抢沙发发表评论

零拷贝、微秒级!Linux 双服务“实时数据”通信 5 大杀器,性能翻 10 倍指南


想让两个 Linux 服务在 1 台机器上“说悄悄话”,还要实时到毫秒甚至微秒?

传统 HTTP/TCP 回环 127.0.0.1 虽然能跑,但内核协议栈一插手,延迟直接 50 µs 起步,CPU 也跟着飙。

今天给你 5 套现成方案,全部亲测可落地,从“代码 5 分钟”到“极限 80 ns”全覆盖,看完就能抄。


1. UNIX Domain Socket——“本机通信天花板”

关键词:双向、能传文件描述符、跟 TCP 同套 API

性能:本机 RTT 5 µs,带宽 5–7 GB/s

场景:100 k qps 以下的交易撮合、游戏网关、微服务 sidecar

代码骨架(C):

int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr = {.sun_family = AF_UNIX,
                           .sun_path = "/run/mysock"};
connect(fd, (struct sockaddr*)&addr, sizeof(addr));
writev(fd, iov, 2);   // 小包直接发,内核不攒批

Tips

  • • 路径放在 /run 或 /tmp,重启自动清。
  • • 需要秒传 GPU 显存?用 sendmsg + SCM_RIGHTS 把 dmabuf fd 甩给对端,零拷贝到帧。



2. 共享内存 + 无锁环形队列——“行情脉冲级”

关键词:80 ns 延迟、单 CPU cycle 完成读写

实现:

  1. 1. shm_open("/quote_shm", O_CREAT|O_RDWR, 0666);
  2. 2. mmap 后前 64 B 做 head/tail 计数器,数据区 2^n 对齐
  3. 3. 用 __atomic_fetch_add 更新,伪共享用 __attribute__((aligned(64))) 隔开
    性能:单生产者单消费者 200 万消息/秒,延迟 80–120 ns
    踩坑:
  • • 多生产者务必加 futex,别用 pthread_mutex(会陷内核)
  • • NUMA 机器绑核:taskset -c 2,3 ./consumer
    扩展:
    把 head/tail 拆成 2 个 cache-line,再配一个 eventfd,让读端能 epoll_wait 唤醒,兼顾轮询+阻塞。

3. eventfd + mmap 文件——“零拷贝 + 可持久化”

套路:

  • • 数据落在 mmap 文件,生产完写 8 B 序号到 eventfd
  • • 消费者 epoll 收到可读事件,直接去 mmap 拿

优势:

  • • 进程重启数据还在;
  • • 唤醒延迟 2–3 µs,比 pipe 少一次内存拷贝
    代码 3 行:
int efd = eventfd(0, EFD_NONBLOCK);
epoll_ctl(ep, EPOLL_CTL_ADD, efd, &(struct epoll_event){.events=EPOLLIN});

适用:日志采集、广告计费“落盘前”实时聚合。


4. pipe + vmsplice/splice——“内核帮你 DMA”

场景:视频采集→编码→转发,一次数据 4 MB 以上

做法:

  • • pipe2(fd, O_DIRECT) 申请 16 页环形缓冲
  • • 采集进程 vmsplice 把用户态页钉到 pipe,zero-copy
  • • 编码进程 splice 把 pipe 内容直接推到 socket 或磁盘


性能:4 GB/s 以上,CPU 占用比 write 降 30%

注意:

  • • 必须 4 k 对齐、大小页倍数;
  • • 需要 Linux 5.6+ 才支持 O_DIRECT pipe

5. Netlink——“内核主动推事件”

只有当对端是内核模块时才用;

用户态打开 socket(AF_NETLINK, SOCK_RAW, NETLINK_USER)

内核用 genl_register_family 注册 family,

延迟 10 µs 级,支持多播,一条消息能带 4 KB 数据。

纯用户态服务请跳过。


一张图带走选型

方案
延迟
吞吐
代码量
额外能力
UNIX Domain Socket
5 µs
5–7 GB/s
★☆☆
传 fd
共享内存+无锁队列
80 ns
200 M msg/s
★★☆
需自旋锁
eventfd+mmap 文件
3 µs
文件级
★★☆
持久化
pipe+splice
5 µs
4 GB/s
★★★
零拷贝大吞吐
Netlink
10 µs
中等
★★★
内核↔用户


实战小结

  • • 100 k qps 以内、想 5 分钟写完:UNIX Domain Socket
  • • 行情/撮合/高频,延迟 <10 µs:共享内存无锁队列
  • • 又要实时又要重启不丢数据:eventfd + mmap 文件
  • • 视频流/大文件零拷贝:pipe + vmsplice
  • • 以后可能跨机:提前用 TCP,但本机先跑 127.0.0.1 压测

把这篇文章丢进浏览器收藏夹,下次老板再说“给我想办法再压 1 毫秒”,直接甩方案 2,让他感受 80 ns 的暴力浪漫。


打赏

本文链接:https://www.kinber.cn/post/6053.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客