一、连接类型实现体系
valkey通过ConnectionType
结构体构建了灵活的网络连接抽象,支持多种连接类型的统一管理。每种连接类型都通过填充该结构体的函数指针来实现特定功能,形成了面向接口的设计模式。

1.1 socket连接
Socket连接提供了最基础的TCP/IP通信能力,实现了全部连接与IO操作接口,是valkey网络通信的基础实现。
src/socket.c
c
static ConnectionType CT_Socket = {
/* connection type */
.get_type = connSocketGetType,
/* connection type initialize & finalize & configure */
.init = NULL,
.cleanup = NULL,
.configure = NULL,
/* ae & accept & listen & error & address handler */
.ae_handler = connSocketEventHandler,
.accept_handler = connSocketAcceptHandler,
.addr = connSocketAddr,
.is_local = connSocketIsLocal,
.listen = connSocketListen,
.closeListener = connSocketCloseListener,
/* create/shutdown/close connection */
.conn_create = connCreateSocket,
.conn_create_accepted = connCreateAcceptedSocket,
.shutdown = connSocketShutdown,
.close = connSocketClose,
/* connect & accept */
.connect = connSocketConnect,
.blocking_connect = connSocketBlockingConnect,
.accept = connSocketAccept,
/* IO */
.write = connSocketWrite,
.writev = connSocketWritev,
.read = connSocketRead,
.set_write_handler = connSocketSetWriteHandler,
.set_read_handler = connSocketSetReadHandler,
.get_last_error = connSocketGetLastError,
.sync_write = connSocketSyncWrite,
.sync_read = connSocketSyncRead,
.sync_readline = connSocketSyncReadLine,
/* pending data */
.has_pending_data = NULL,
.process_pending_data = NULL,
.postpone_update_state = NULL,
.update_state = NULL,
/* Miscellaneous */
.connIntegrityChecked = NULL,
};
int RedisRegisterConnectionTypeSocket(void) {
return connTypeRegister(&CT_Socket);
}
1.2 unix域套接字
Unix域套接字专注于本地进程间通信,省略了网络连接相关的接口,优化了本地通信的性能。
src/unix.c
c
static ConnectionType CT_Unix = {
/* connection type */
.get_type = connUnixGetType,
/* connection type initialize & finalize & configure */
.init = NULL,
.cleanup = NULL,
.configure = NULL,
/* ae & accept & listen & error & address handler */
.ae_handler = connUnixEventHandler,
.accept_handler = connUnixAcceptHandler,
.addr = connUnixAddr,
.is_local = connUnixIsLocal,
.listen = connUnixListen,
.closeListener = connUnixCloseListener,
/* create/shutdown/close connection */
.conn_create = connCreateUnix,
.conn_create_accepted = connCreateAcceptedUnix,
.shutdown = connUnixShutdown,
.close = connUnixClose,
/* connect & accept */
.connect = NULL,
.blocking_connect = NULL,
.accept = connUnixAccept,
/* IO */
.write = connUnixWrite,
.writev = connUnixWritev,
.read = connUnixRead,
.set_write_handler = connUnixSetWriteHandler,
.set_read_handler = connUnixSetReadHandler,
.get_last_error = connUnixGetLastError,
.sync_write = connUnixSyncWrite,
.sync_read = connUnixSyncRead,
.sync_readline = connUnixSyncReadLine,
/* pending data */
.has_pending_data = NULL,
.process_pending_data = NULL,
.postpone_update_state = NULL,
.update_state = NULL,
/* Miscellaneous */
.connIntegrityChecked = NULL,
};
int RedisRegisterConnectionTypeUnix(void) {
return connTypeRegister(&CT_Unix);
}
1.3 tls加密连接
TLS连接增加了加密相关的初始化、清理和配置接口,提供了证书处理和加密数据传输能力,是安全通信的实现。
src/tls.c
c
static ConnectionType CT_TLS = {
/* connection type */
.get_type = connTLSGetType,
/* connection type initialize & finalize & configure */
.init = tlsInit,
.cleanup = tlsCleanup,
.configure = tlsConfigure,
/* ae & accept & listen & error & address handler */
.ae_handler = tlsEventHandler,
.accept_handler = tlsAcceptHandler,
.addr = connTLSAddr,
.is_local = connTLSIsLocal,
.listen = connTLSListen,
.closeListener = connTLSCloseListener,
/* create/shutdown/close connection */
.conn_create = connCreateTLS,
.conn_create_accepted = connCreateAcceptedTLS,
.shutdown = connTLSShutdown,
.close = connTLSClose,
/* connect & accept */
.connect = connTLSConnect,
.blocking_connect = connTLSBlockingConnect,
.accept = connTLSAccept,
/* IO */
.read = connTLSRead,
.write = connTLSWrite,
.writev = connTLSWritev,
.set_write_handler = connTLSSetWriteHandler,
.set_read_handler = connTLSSetReadHandler,
.get_last_error = connTLSGetLastError,
.sync_write = connTLSSyncWrite,
.sync_read = connTLSSyncRead,
.sync_readline = connTLSSyncReadLine,
/* pending data */
.has_pending_data = tlsHasPendingData,
.process_pending_data = tlsProcessPendingData,
.postpone_update_state = postPoneUpdateSSLState,
.update_state = updateSSLState,
/* TLS specified methods */
.get_peer_cert = connTLSGetPeerCert,
/* Miscellaneous */
.connIntegrityChecked = connTLSIsIntegrityChecked,
};
int RedisRegisterConnectionTypeTLS(void) {
return connTypeRegister(&CT_TLS);
}
1.4 rdma高性能连接
RDMA连接针对高性能计算场景设计,提供了低延迟的数据传输能力,包含了特殊的状态管理接口。
src/rdma.c
c
static ConnectionType CT_RDMA = {
/* connection type */
.get_type = connRdmaGetType,
/* connection type initialize & finalize & configure */
.init = rdmaInit,
.cleanup = NULL,
/* ae & accept & listen & error & address handler */
.ae_handler = connRdmaEventHandler,
.accept_handler = connRdmaAcceptHandler,
//.cluster_accept_handler = NULL,
.is_local = connRdmaIsLocal,
.listen = connRdmaListen,
.closeListener = connRdmaCloseListener,
.addr = connRdmaAddr,
/* create/close connection */
.conn_create = connCreateRdma,
.conn_create_accepted = connCreateAcceptedRdma,
.shutdown = connRdmaShutdown,
.close = connRdmaClose,
/* connect & accept */
.connect = connRdmaConnect,
.blocking_connect = connRdmaBlockingConnect,
.accept = connRdmaAccept,
/* IO */
.write = connRdmaWrite,
.writev = connRdmaWritev,
.read = connRdmaRead,
.set_write_handler = connRdmaSetWriteHandler,
.set_read_handler = connRdmaSetReadHandler,
.get_last_error = connRdmaGetLastError,
.sync_write = connRdmaSyncWrite,
.sync_read = connRdmaSyncRead,
.sync_readline = connRdmaSyncReadLine,
/* pending data */
.has_pending_data = rdmaHasPendingData,
.process_pending_data = rdmaProcessPendingData,
.postpone_update_state = postPoneUpdateRdmaState,
.update_state = updateRdmaState,
/* Miscellaneous */
.connIntegrityChecked = NULL,
};
int RegisterConnectionTypeRdma(void) {
return connTypeRegister(&CT_RDMA);
}
二、连接类型注册流程
2.1 注册调用链
c
src/server.c
main
| src/connection.c
|--> connTypeInitialize
2.2 注册实现
src/connection.c
c
int connTypeInitialize(void) {
/* currently socket connection type is necessary */
serverAssert(RedisRegisterConnectionTypeSocket() == C_OK);
/* currently unix socket connection type is necessary */
serverAssert(RedisRegisterConnectionTypeUnix() == C_OK);
/* may fail if without BUILD_TLS=yes */
RedisRegisterConnectionTypeTLS();
/* may fail if without BUILD_RDMA=yes */
RegisterConnectionTypeRdma();
return C_OK;
}
这种注册机制实现了:
- 核心连接类型的强制注册(Socket和Unix)
- 可选连接类型的条件注册(TLS和RDMA)
- 编译时决定是否支持特定连接类型的灵活性
三、监听器初始化流程
监听器初始化是valkey网络服务启动的关键步骤,负责根据配置创建并激活各类连接的监听机制。
3.1 初始化调用链
c
src/server.c
main
| src/config.c
|--> loadServerConfig
|
| src/server.c
|--> initListeners
3.2 初始化实现
根据不同的配置,初始化不同的监听器。
c
void initListeners(void) {
/* Setup listeners from server config for TCP/TLS/Unix */
int conn_index;
connListener *listener;
if (server.port != 0) {
conn_index = connectionIndexByType(CONN_TYPE_SOCKET);
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_SOCKET);
listener = &server.listeners[conn_index];
listener->bindaddr = server.bindaddr;
listener->bindaddr_count = server.bindaddr_count;
listener->port = server.port;
listener->ct = connectionByType(CONN_TYPE_SOCKET);
}
if (server.tls_port || server.tls_replication || server.tls_cluster) {
ConnectionType *ct_tls = connectionTypeTls();
if (!ct_tls) {
serverLog(LL_WARNING, "Failed finding TLS support.");
exit(1);
}
if (connTypeConfigure(ct_tls, &server.tls_ctx_config, 1) == C_ERR) {
serverLog(LL_WARNING, "Failed to configure TLS. Check logs for more info.");
exit(1);
}
}
if (server.tls_port != 0) {
conn_index = connectionIndexByType(CONN_TYPE_TLS);
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_TLS);
listener = &server.listeners[conn_index];
listener->bindaddr = server.bindaddr;
listener->bindaddr_count = server.bindaddr_count;
listener->port = server.tls_port;
listener->ct = connectionByType(CONN_TYPE_TLS);
}
if (server.unixsocket != NULL) {
conn_index = connectionIndexByType(CONN_TYPE_UNIX);
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_UNIX);
listener = &server.listeners[conn_index];
listener->bindaddr = &server.unixsocket;
listener->bindaddr_count = 1;
listener->ct = connectionByType(CONN_TYPE_UNIX);
listener->priv = &server.unix_ctx_config; /* Unix socket specified */
}
if (server.rdma_ctx_config.port != 0) {
conn_index = connectionIndexByType(CONN_TYPE_RDMA);
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_RDMA);
listener = &server.listeners[conn_index];
listener->bindaddr = server.rdma_ctx_config.bindaddr;
listener->bindaddr_count = server.rdma_ctx_config.bindaddr_count;
listener->port = server.rdma_ctx_config.port;
listener->ct = connectionByType(CONN_TYPE_RDMA);
listener->priv = &server.rdma_ctx_config;
}
/* create all the configured listener, and add handler to start to accept */
int listen_fds = 0;
for (int j = 0; j < CONN_TYPE_MAX; j++) {
listener = &server.listeners[j];
if (listener->ct == NULL) continue;
if (connListen(listener) == C_ERR) {
serverLog(LL_WARNING, "Failed listening on port %u (%s), aborting.", listener->port,
listener->ct->get_type(NULL));
exit(1);
}
if (createSocketAcceptHandler(listener, connAcceptHandler(listener->ct)) != C_OK)
serverPanic("Unrecoverable error creating %s listener accept handler.", listener->ct->get_type(NULL));
listen_fds += listener->count;
}
if (listen_fds == 0) {
serverLog(LL_WARNING, "Configured to not listen anywhere, exiting.");
exit(1);
}
}
四、抽象连接层设计
valkey通过connection.h
头文件定义了抽象连接层的接口,实现了对各类连接的统一操作,体现了面向对象的多态特性。
4.1 统一接口设计
src/connection.h
c
...
static inline int connWritev(connection *conn, const struct iovec *iov, int iovcnt) {
return conn->type->writev(conn, iov, iovcnt);
}
static inline int connRead(connection *conn, void *buf, size_t buf_len) {
int ret = conn->type->read(conn, buf, buf_len);
return ret;
}
...
4.2 多态实现机制
抽象连接层通过函数指针实现了多态:
- 上层代码使用统一的
connRead
、connWritev
等接口 - 实际执行时根据
conn->type
指向的具体连接类型,调用对应的实现函数 - 新增连接类型时,只需实现
ConnectionType
结构体的函数,无需修改上层逻辑
这种设计带来的优势:
- 接口与实现分离,降低模块间耦合
- 便于扩展新的连接类型
- 保持上层代码的稳定性
- 统一的错误处理和状态管理
五、架构设计亮点
模块化设计: 每种连接类型作为独立模块实现,便于维护和扩展
条件编译支持: 通过编译选项控制TLS、RDMA等可选模块的编译和注册
统一抽象层: 通过函数指针实现多态,简化上层使用
渐进式初始化: 从连接注册到监听器启动,形成完整的初始化流程
灵活的配置体系: 支持多种连接类型的并行配置和启动
valkey的网络管理架构通过这种分层抽象和接口统一,既保证了底层实现的灵活性,又为上层提供了简单一致的使用方式,是高性能网络服务的典型设计模式。