状态单一来源
PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
单进程部署不需要集群模式。
以下场景启用:
cluster: enabled: true启用后,Redis 和 cluster.secret 必填。
cluster.secret集群内部 gRPC 共享密钥。cluster.enabled=true 时必填。
cluster: secret_file: "/run/secrets/cluster_secret"生成:
openssl rand -hex 32集群模式解决的是“多个 SyncTV 进程共同服务同一个实例”时的运行时一致性问题。它不是简单的负载均衡开关,也不替代 PostgreSQL、Redis、Ingress 或直播存储/代理策略。
状态单一来源
PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
运行时协调
Redis 保存 ephemeral/shared state:节点注册、pub/sub、Redis Stream catch-up、leader election、限流和短期认证状态。
节点间信任
cluster.secret 用于节点间 gRPC 调用认证。所有节点必须一致,且不能暴露给客户端。
直播可达性
RTMP publisher 可能在任意节点上,观众请求也可能落到任意节点;因此直播需要 publisher registry、HLS gRPC proxy 和明确的 HLS 存储边界。
cluster.discovery_mode 注册和发现其他节点。默认 redis 模式适合大多数环境;Kubernetes 可以选择 k8s_dns 辅助发现 Pod。cluster.catchup_window_secs 窗口内补事件;业务缓存失效另有专用 Redis Stream/XREADGROUP runtime。cluster.leader_election_mode 选出一个 leader,避免多个副本重复执行同一类全局任务。shared_file 的 TS 分片请求由当前节点从共享路径读取。| 部署形态 | 适用场景 | 推荐配置 |
|---|---|---|
| 单进程 | 小规模、自托管、开发测试 | 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 请求量高、需要更稳定的滚动升级边界 | 在集群配置基础上增加 shared_file 或 oss HLS backend |
cluster.secret。| 字段 | 默认值 | 用途 |
|---|---|---|
cluster.critical_channel_capacity | 10000 | 踢人、权限变更等高优先级事件 |
cluster.publish_channel_capacity | 100000 | 普通 Redis publish 事件 |
critical 事件满队列时会反压发送方;普通事件在极端拥塞时可能丢弃并记录 warning。
cluster.discovery_mode可选值:
redisstatick8s_dns默认模式。节点通过 Redis 注册和发现,适合 Docker、服务器和 Kubernetes。
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_NAMESPACEk8s_dns 不替代 Redis。Redis 仍负责健康状态、负载状态、pub/sub 和 catch-up。
| 模式 | 场景 |
|---|---|
redis | 默认;适合 Docker、服务器和 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 默认值:100000。它控制 Redis Stream 近似保留长度。太小会让断线节点还没追上时事件已被裁剪;太大会占用更多 Redis 内存。
集群 HLS 不只有共享存储一种模式。SyncTV 通过 publisher registry 定位推流所在节点;本地 backend 在需要时通过 HLS gRPC proxy 从 publisher 节点读取 playlist/segment,shared_file 的 TS 分片由当前节点从共享路径读取。
适用 backend:
memoryfile这种模型部署简单,不要求所有副本共享分片目录。代价是非 publisher 节点的 HLS segment 请求会跨节点回源到 publisher 节点;publisher 节点重启、不可达或网络分区时,远端节点可能无法继续读取该直播的分片。
示例:
livestream: hls_storage_backend: "memory"或:
livestream: hls_storage_backend: "file" hls_storage_path: "/var/lib/synctv/hls"共享 backend 表示 HLS 分片不会只存在于 publisher 节点本地磁盘。它有利于持久化、重启恢复和统一清理策略。shared_file 模式下,.ts 请求由当前节点从共享路径读取,不再为了 TS 文件回源 publisher 节点。
文件系统方案:
livestream: hls_storage_backend: "shared_file" 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 兼容对象存储。
Helm chart 默认不启用集群模式。扩容前显式设置 config.cluster.enabled=true。HLS 可以先使用 publisher-node proxy;需要更稳定的分片存储和恢复边界时,使用 shared_file 或 oss。
扩容前必须确认:
cluster.secret 稳定且所有副本一致。shared_file + RWX/PVC 或 oss。