考虑一个问题,以负载均衡中的虚服务为例,新增一个虚服务,控制面存在数据库里,查询的时候,从数据库查询。 因为控制平面的对象,好像只起到增删改查的作用,并不需要一直在内存里。 网络设备之所以在内存里,是因为没有办法连外部的数据库服务,使用的是配置文件持久保存配置。 是否使用数据库是区分嵌入式和互联网的标志。
典型架构:控制平面 vs 数据平面
lua
深色版本
+---------------------------+
| 控制平面 (Control Plane) |
| |
| +----------------------+ |
| | 配置管理 (CLI/Web/API) | | ← 用户输入
| +----------+-----------+ |
| | |
| +----------v-----------+ |
| | 配置数据库 (SQLite/etcd)| | ← 持久化存储
| +----------+-----------+ |
| | 同步/更新 |
+-------------|---------------+
↓
+-------------v---------------+
| 数据平面 (Data Plane) |
| |
| +------------------------+ |
| | 运行时配置 (内存结构) | | ← 哈希表、RBTree、RCU 链表
| | (虚服务、RS、会话表等) | |
| +------------+-----------+ |
| | 查表/转发 |
| +------------v-----------+ |
| | 转发引擎 (LVS/NIC/XDP) | | ← 每秒百万级包处理
| +------------------------+ |
+-----------------------------+
以"新增虚服务"为例,完整流程
场景:用户通过 Web UI 新增一个虚拟服务(VIP:Port)
步骤 1:写入数据库(持久化)
sql
sql
深色版本
INSERT INTO virtual_service (vip, vport, protocol, scheduler)
VALUES ('192.168.1.100', 80, 'TCP', 'wrr');
✅ 目的:持久化配置,防止重启丢失
步骤 2:控制平面通知数据平面
- 控制平面进程(如
keepalived
、dpvs-control
、nginx -s reload
)检测到变更 - 解析数据库配置,生成内存数据结构
arduino
c
深色版本
struct dpvs_virtual_service {
struct in_addr vip;
uint16_t vport;
uint8_t proto;
struct list_head rs_list; // 真实服务器链表
struct rte_hash *conn_hmap; // 会话表(内存哈希表)
struct dpvs_sched *scheduler; // 调度算法
};
步骤 3:数据平面加载配置
-
使用 RCU(Read-Copy-Update) 机制:
- 创建新配置副本
- 原子替换旧指针
- 延迟释放旧配置(等待所有读者完成)
✅ 实现"零中断更新",连接不中断
步骤 4:数据平面查表转发
scss
c
深色版本
// 数据平面伪代码
struct dpvs_virtual_service *vs = vs_lookup(vip, vport);
if (vs) {
struct dpvs_real_server *rs = vs->scheduler->schedule(vs);
forward_packet(pkt, rs);
}
✅ 查表在 < 1 微秒 内完成(哈希表 O(1))
✅ 五、数据库的作用是什么?
虽然不能用于实时转发,但数据库仍然非常重要:
作用 | 说明 |
---|---|
✅ 持久化存储 | 重启后恢复配置 |
✅ 配置审计 | 记录谁在什么时候修改了什么 |
✅ 集群同步 | 多台设备间通过数据库(如 etcd)同步配置 |
✅ API/CLI 后端 | Web UI、REST API 的数据源 |
✅ 版本管理 | 支持配置回滚、diff、备份 |
🔹 常见选择:
- 单机:SQLite
- 集群:etcd、Consul、ZooKeeper
✅ 六、不同产品的实现对比
产品 | 控制平面内存结构 | 数据库 | 同步机制 |
---|---|---|---|
DPVS | dpvs_virtual_service + rte_hash |
etcd/SQLite | 控制进程通知 |
Nginx | ngx_http_upstream_srv_conf_t |
无(配置文件) | nginx -s reload |
F5 BIG-IP | TMM 内存结构(C++ 对象) | tmsh config db | config sync |
Linux LVS | ip_vs_service + hlist |
无 | ipvsadm 命令直接写内核 |
✅ 七、总结:内存 vs 数据库的角色
问题 | 答案 |
---|---|
控制平面对象存在内存中是为了什么? | ✅ 为数据平面提供低延迟、高并发、无锁访问的运行时配置 |
可以只存在数据库里,查询时读吗? | ❌ 不行,数据库查询太慢,无法满足数据平面性能要求 |
数据库有什么用? | ✅ 持久化、审计、集群同步、API 后端 |
正确架构是什么? | ✅ 数据库(持久化) ←→ 控制平面 ←→ 内存结构(运行时) ←→ 数据平面 |
🎯 最终结论:
内存中的控制平面对象是"运行时加速层",数据库是"持久化存储层" 。
就像:
- 数据库是"硬盘" :保存配置,不怕重启
- 内存结构是"CPU 缓存" :供数据平面高速访问
两者不是替代关系,而是协作关系 。高性能网络系统必须同时具备两者,才能兼顾 性能、可靠性、可管理性。