news 2026/8/23 17:52:48

【kv存储】实时主从同步实现与eBPF旁路转发方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【kv存储】实时主从同步实现与eBPF旁路转发方案

一、背景

本文重点是实时数据的主从同步,以及使用eBPF做旁路转发的方案。

功能实现
仿照Redis实现的主从同步功能

Redis的主从同步分为两个阶段,第一个阶段:从机启动时,拉取主机的已有的数据,拉取完毕后从机正式上线。第二个阶段是从机上线后,主机实时将新的命令传播给从机,实现实时数据的变更。总结为:

  • 已有数据同步
  • 实时数据同步

    阶段一:已有数据同步
  1. 从机配置为slave,并且指定主机的IP和端口,从机启动时向主机发送SYNC指令
  2. 主机收到SYNC指令,将从机添加到从机列表当中后,打开积压缓冲区,触发BGSAVE全量保存数据到RDB文件中
  3. 主机将保存的RDB文件发送到从机
  4. 主机将积压缓冲区的数据发送到从机

阶段二:实时数据同步

  1. 主机收到来自客户端的新指令
  2. 主机解析RESP格式后后将变更类的指令(不包括GET等指令)重新编码,转发到从机

二、send网络转发实现

指令解析后,再变更类指令的分发分支上调用feed_slave

voidkvs_replication_feed_slaves(constchar*cmd,constchar*key,size_tklen,constchar*value,size_tvlen){if(g_repl.role!=KVS_ROLE_MASTER||g_repl.slave_count==0)return;charbuf[REPL_CMD_BUF];intlen=0,encoded=0;inthas_online=0,has_syncing=0;// 统计从库状态for(inti=0;i<g_repl.slave_count;i++){if(g_slaves[i].state==SLAVE_ONLINE)has_online=1;elsehas_syncing=1;}// 有同步中的从库 → 写 Backlogif(has_syncing){len=resp_encode_cmd(...);encoded=1;ensure_backlog();buffer_add(g_backlog,buf,len);// 满了则踢掉同步中的从库// ...}// 有在线从库 → 直接推送if(has_online){if(!encoded)len=resp_encode_cmd(...);for(inti=0;i<g_repl.slave_count;i++){if(g_slaves[i].state==SLAVE_ONLINE){reactor_append(...);// 失败则 drop_slave(i--);}}}}

待网络转发的数据填进reactor的wbuffer里,等待事件循环。

intreactor_append(intfd,constvoid*data,uint32_tlen){structconn*c=reactor_conn(fd);if(!c||!c->wbuffer||!data||len==0)return-1;if(buffer_add(c->wbuffer,data,len)!=0)return-1;set_event(fd,EPOLLIN|EPOLLOUT,0);return0;}

可以看到,这种方案面临着比较重的开销:

  • 整个过程中有两次编码
  • 若干次拷贝
  • 占用主机send的吞吐。

三、提出eBPF旁路转发的方案

eBPF 主从同步开启时,将hook点选择KV存储主机解析之后(RESP格式)的一个指定函数,此时hook函数的参数中已经获取了cmd、key、value以及klen、vlen等数据。

  1. 主机网络接收来自客户端的命令
  2. 解析完毕之后,拷贝到专门的hook函数(声明非内联,非优化,以便eBPF捕获)
  3. eBPF内核态程序捕获cmd,key,value等数据,抛入ringbuf(BPF map)中
  4. 用户态程序轮询获取ringbuf中的数据,并且编码
  5. send转发到从机

我们分析这条路径,不难发现,eBPF的思路是利用了旁路捕获并转发的思路,将编码、多次拷贝、send转发的开销旁路到了eBPF用户态进程中。KV存储中只需要维护一个类似这样的hook函数

__attribute__((noinline))voidkvs_eBPF_propagation_hook(constchar*cmd,constchar*key,size_tklen,constchar*value,size_tvlen){(void)cmd;(void)key;(void)klen;(void)value;(void)vlen;asmvolatile("");}

eBPF的实现比较复杂,涉及libbpf-bootstrap程序的改造,vertifier下编程容易踩的坑等,将来我写新的博客专门讲解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 17:47:53

深入解析Kconfig语法:从核心元素到实战应用

1. 项目概述&#xff1a;为什么我们需要深入理解Kconfig语法&#xff1f;如果你在嵌入式开发、Linux内核或者任何使用Makefile构建的大型C/C项目中工作过&#xff0c;那你一定见过那个神秘的Kconfig文件。它通常和Makefile躺在一起&#xff0c;在你执行make menuconfig或make x…

作者头像 李华
网站建设 2026/8/23 17:47:29

C++模板与泛型编程:从STL容器到现代概念的核心机制解析

1. 从“重复造轮子”到“一劳永逸”&#xff1a;为什么我们需要模板与泛型编程&#xff1f; 如果你写过一段时间的C&#xff0c;尤其是写过一些需要处理多种数据类型的工具函数或数据结构&#xff0c;你大概率经历过这种痛苦&#xff1a;为了给 int 、 double 、 string …

作者头像 李华
网站建设 2026/8/23 17:47:19

蓝桥杯国赛递增序列题解:双指针算法与竞赛思维实战

1. 项目概述&#xff1a;从“签到题”看蓝桥杯国赛的考察逻辑 在算法竞赛圈里&#xff0c;“签到题”这个词总是带着一种微妙的双重含义。一方面&#xff0c;它意味着题目相对简单&#xff0c;是参赛者必须拿下的基础分&#xff0c;是稳定军心的第一步。另一方面&#xff0c;它…

作者头像 李华
网站建设 2026/8/23 17:46:59

车载空间音频技术解析:从BOSE虚拟环绕声看沉浸式座舱体验

如果你最近在关注新能源汽车的智能化配置&#xff0c;可能会发现一个有趣的现象&#xff1a;各大厂商的“军备竞赛”已经从三电系统、智能驾驶&#xff0c;悄然蔓延到了座舱体验&#xff0c;尤其是车载音响。从简单的“多喇叭”到“品牌音响”&#xff0c;再到如今各家都在宣传…

作者头像 李华
网站建设 2026/8/23 17:44:06

OpCore-Simplify 使用指南:从硬件报告一键生成 OpenCore EFI

OpCore-Simplify 使用指南&#xff1a;从硬件报告一键生成 OpenCore EFI 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify OpCore-Simplify 是一款黑苹果…

作者头像 李华