状态单一来源
PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
如果你只运行一个 SyncTV 进程,通常不需要开启集群模式。
需要开启的场景:
开启方式:
cluster: enabled: true开启后,Redis 和 server.cluster_secret 都是必需项。
集群模式解决的是“多个 SyncTV 进程共同服务同一个实例”时的运行时一致性问题。它不是简单的负载均衡开关,也不替代 PostgreSQL、Redis、Ingress 或直播存储/代理策略。
状态单一来源
PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
运行时协调
Redis 保存 ephemeral/shared state:节点注册、pub/sub、Redis Stream catch-up、leader election、限流和短期认证状态。
节点间信任
server.cluster_secret 用于节点间 gRPC 调用认证。所有节点必须一致,且不能暴露给客户端。
直播可达性
RTMP publisher 可能在任意节点上,HLS segment 也可能被任意节点读取;因此直播需要 publisher registry,并在本地 backend 与共享 backend 之间选择合适模型。
cluster.discovery_mode 注册和发现其他节点。默认 redis 模式适合大多数环境;Kubernetes 可以选择 k8s_dns 辅助发现 Pod。cluster.catchup_window_secs 窗口内补事件。cluster.leader_election_mode 选出一个 leader,避免多个副本重复执行同一类全局任务。| 部署形态 | 适用场景 | 推荐配置 |
|---|---|---|
| 单进程 | 小规模、自托管、开发测试 | cluster.enabled=false,Redis 可选但生产建议配置 |
| 多进程固定节点 | 多台 VM 或裸机,节点数量稳定 | cluster.enabled=true、discovery_mode=static 或 redis |
| Kubernetes 多副本 | 水平扩缩容、滚动升级、Ingress 暴露 | cluster.enabled=true、discovery_mode=redis 或 k8s_dns、HTTP/gRPC 独立 Service |
| 多副本直播,小流量 | HLS/FLV 需要跨节点播放,但 segment 请求量不高 | cluster.enabled=true,可使用 memory 或本地 file,依赖 publisher-node proxy |
| 多副本直播,高流量 | HLS 请求量高、需要更稳定的滚动升级边界 | 在集群配置基础上增加 file 共享存储或 oss HLS backend |
cluster.enabled默认值:false。
开启后,SyncTV 会启用跨节点协调逻辑。
必须满足:
server.cluster_secret。cluster.critical_channel_capacity默认值:1000。
作用:高优先级事件通道容量,例如踢人、权限变更等不能随便丢的事件。
满了以后发送方会等待,而不是丢弃事件。
cluster.publish_channel_capacity默认值:10000。
作用:普通 Redis publish 通道容量。
普通事件在极端拥塞时可能丢弃并记录 warning,避免拖垮主流程。
cluster.discovery_mode可选值:
redisstatick8s_dns默认值。节点通过 Redis 注册和发现。
优点:
static手动配置节点地址。
cluster: discovery_mode: "static" peers: - "node2.example.com:8080" - "node3.example.com"适合固定服务器数量的小集群。
如果 peer 不写端口,SyncTV 会尝试使用 server.port。
k8s_dns通过 Kubernetes headless service DNS 发现 Pod。
需要环境变量:
HEADLESS_SERVICE_NAMEPOD_NAMESPACE注意:k8s_dns 仍然需要 Redis。DNS 只帮助更快发现 Pod,不替代 Redis 的健康监控、负载均衡和 pub/sub。
cluster.leader_election_mode可选值:
redisk8s_lease默认值。通过 Redis 锁做 leader election。
适合 Docker Compose、普通服务器、Kubernetes。
k8s_lease使用 Kubernetes coordination.k8s.io/v1 Lease。
需要:
POD_NAMEPOD_NAMESPACEHelm chart 会在需要时渲染相关 RBAC。
cluster.catchup_window_secs默认值:300。
作用:新节点加入时,从 Redis Stream 回放多久以内的事件,避免刚订阅时漏掉短时间内发布的事件。
调大:
调小:
cluster.stream_max_length默认值:10000。
作用:每个 Redis Stream 大约保留多少条事件。
高流量房间很多时,太小可能导致断线节点还没追上,事件就被裁剪。太大则占用更多 Redis 内存。
集群 HLS 不只有共享存储一种模式。当前实现通过 publisher registry 定位推流所在节点,并在需要时通过 HLS gRPC proxy 从 publisher 节点读取 playlist/segment。
适用 backend:
memoryfile 且 hls_shared_storage=false这种模型部署简单,不要求所有副本共享分片目录。代价是非 publisher 节点的 HLS segment 请求会跨节点回源到 publisher 节点;publisher 节点重启、不可达或网络分区时,远端节点可能无法继续读取该直播的分片。
示例:
livestream: hls_storage_backend: "memory"或:
livestream: hls_storage_backend: "file" hls_shared_storage: false hls_storage_path: "/var/lib/synctv/hls"文件系统方案:
livestream: hls_storage_backend: "file" hls_shared_storage: true hls_storage_path: "/var/lib/synctv/hls"并确保所有 Pod 都能读写同一个路径,例如 NFS、RWX PVC 或 CSI volume。
对象存储方案:
livestream: hls_storage_backend: "oss" hls_oss: endpoint: "https://s3.example.com" bucket: "synctv-hls" base_path: "synctv/hls/"oss backend 使用 S3 兼容对象存储,不需要 hls_shared_storage。hls_shared_storage=true 只允许搭配 hls_storage_backend=file,在 memory 或 oss 下会被配置校验拒绝。
Helm chart 默认不启用集群模式。扩容前必须显式开启 config.cluster.enabled=true。HLS 可以先使用 publisher-node proxy 模型;如果直播 HLS 流量较高,建议配置 file 共享存储或 oss 对象存储。
扩容前必须确认:
server.cluster_secret 已设置。file + hls_shared_storage=true + RWX/PVC 或 oss。