高可用改造之构建双活冗余的TDengine时序数据处理架构
文章目录
- 一、背景说明
- 二、方案设计
- 三、安装部署
- 3.1 TDengine 备库安装
- 3.2 Tengine代理服务安装
- 四、初始化配置
- 4.1 TDengine
- 4.1.1 备库同步表结构
- 4.1.2 备库同步用户
- 4.2 Tengine
- 4.2.1 创建自定义配置文件
- 4.2.2 写入 TDengine 代理配置
- 4.2.3 测试验证
- 五、验证高可用功能
- 5.1 检查健康状态
- 5.2 模拟故障转移
- 六、小结
一、背景说明
此前,相关系统曾遭遇数据丢失事故,本方案旨在提升系统可用性,以规避类似风险。然而,该业务系统存在以下特殊性,构成了方案设计的核心约束:
- 服务器资源严格受限: 无法部署标准的 TDengine 生产级集群(最小要求为 3 Management Node + 2 Data Node,共计 5 节点)。资源投入必须高度精简。
- 应用层改造成本敏感: 期望避免为达成高可用目标而对应用层进行大规模的、侵入式的改造,需尽可能降低适配成本。
- 超级表管理方式特定: 当前超级表 (STable) 采用手动维护策略。这意味着可以暂时搁置跨节点数据实时复制的需求,方案的核心目标简化为保障现有存量表结构的可靠同步。
- 故障恢复时效性要求高: 对数据库服务故障转移 (Failover) 后的恢复时间 (RTO) 非常敏感,需最大限度减少业务中断时间。
二、方案设计
逻辑简图如下:
本方案构建一个双活冗余的高可用时序数据处理架构,通过主备两套独立的数据链路(数据写入服务→TDengine时序库)实现全链路冗余,最终汇聚至统一的 Tengine(淘宝开源)代理服务;
该代理服务集成健康监控与自动故障转移能力,实时检测数据库状态,在主库故障时无缝切换至备库,恢复后自动回切,使业务应用通过单一访问点获得持续可靠的数据服务,确保系统具备故障自愈能力与业务连续性保障。
主要使用的组件:
- Tengine:代理服务,Tengine是淘宝网发起的Web服务器项目,基于Nginx优化,用于高并发场景。
- TDengine:时序数据库:TDengine是涛思数据开发的高性能、分布式、支持SQL的时序数据库,专为物联网、工业互联网等场景设计。
三、安装部署
操作系统版本:Ubuntu 24.04.2 LTS
3.1 TDengine 备库安装
版本最好保持与主库一致,尽量减少数据一致性兼容问题。
具体步骤参考官方文档:
- 使用安装包快速体验 TDengine
3.2 Tengine代理服务安装
下载文件:
wget https://tengine.taobao.org/download/tengine-2.4.1.tar.gztar -zxvf tengine-2.4.1.tar.gz
安装依赖库:
sudo apt updatesudo apt install g++ -ysudo apt install libpcre3 libpcre3-dev -ysudo apt install openssl libssl-dev -ysudo apt install zlib1g zlib1g-dev -ysudo apt make -y
编译安装:
cd tengine-2.4.1sudo ./configure \
--prefix=/usr/local/src/tengine \
--without-http_upstream_keepalive_module \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-threads --with-stream \
--with-stream_ssl_module \
--with-http_slice_module \
--with-file-aio \
--with-http_v2_module \
--add-module=modules/ngx_backtrace_module \
--add-module=modules/ngx_debug_pool \
--add-module=modules/ngx_debug_timer \
--add-module=modules/ngx_http_concat_module \
--add-module=modules/ngx_http_footer_filter_module \
--add-module=modules/ngx_http_proxy_connect_module \
--add-module=modules/ngx_http_reqstat_module \
--add-module=modules/ngx_http_slice_module \
--add-module=modules/ngx_http_sysguard_module \
--add-module=modules/ngx_http_trim_filter_module \
--add-module=modules/ngx_http_upstream_check_module \
--add-module=modules/ngx_http_upstream_consistent_hash_module \
--add-module=modules/ngx_http_upstream_dynamic_module \
--add-module=modules/ngx_http_upstream_dyups_module \
--add-module=modules/ngx_http_upstream_keepalive_module \
--add-module=modules/ngx_http_upstream_session_sticky_module \
--add-module=modules/ngx_http_user_agent_module \
--with-compatsudo make
sudo make install
安装完成后,Tengine 的文件结构如下:
- 二进制文件:/usr/local/src/tengine/sbin/nginx
- 配置文件:/usr/local/src/tengine/conf/nginx.conf
- 日志目录:/usr/local/src/tengine/logs/
- 模块目录:/usr/local/src/tengine/modules/
验证 Tengine 是否安装成功:
# 查看版本
$ sudo ./nginx -v
Tengine version: Tengine/3.1.0
nginx version: nginx/1.24.0# 查看编译时启用的模块
$ sudo ./nginx -V
Tengine version: Tengine/3.1.0
nginx version: nginx/1.24.0
built by gcc 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04)
built with OpenSSL 3.0.13 30 Jan 2024
TLS SNI support enabled
configure arguments: --prefix=/usr/local/src/tengine --without-http_upstream_keepalive_module --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-file-aio --with-http_v2_module --add-module=modules/ngx_backtrace_module --add-module=modules/ngx_debug_pool --add-module=modules/ngx_debug_timer --add-module=modules/ngx_http_concat_module --add-module=modules/ngx_http_footer_filter_module --add-module=modules/ngx_http_proxy_connect_module --add-module=modules/ngx_http_reqstat_module --add-module=modules/ngx_http_slice_module --add-module=modules/ngx_http_sysguard_module --add-module=modules/ngx_http_trim_filter_module --add-module=modules/ngx_http_upstream_check_module --add-module=modules/ngx_http_upstream_consistent_hash_module --add-module=modules/ngx_http_upstream_dynamic_module --add-module=modules/ngx_http_upstream_dyups_module --add-module=modules/ngx_http_upstream_keepalive_module --add-module=modules/ngx_http_upstream_session_sticky_module --add-module=modules/ngx_http_user_agent_module --with-compat
启动 Tengine:
# 启动 Tengine
sudo /usr/local/src/tengine/sbin/nginx# 检查是否运行
ps aux | grep nginx
四、初始化配置
4.1 TDengine
4.1.1 备库同步表结构
TDengine 提供的数据备份、恢复工具 — taosdump。
主库导出数据(按天导出数据):
taosdump -h localhost -P 6030 -o /file/path -D dbname -S '2024-12-17 00:00:00' -E '2024-12-18 00:00:00'
执行上述命令后,taosdump 会连接 localhost:6030 所在的 TDengine 集群,查询数据库 dbname 中的所有数据,并将数据备份到 /file/path 下。
# 备库恢复数据
taosdump -i /file/path -h localhost -P 6030
执行上述命令后,taosdump 会连接 localhost:6030 所在的 TDengine 集群,并将 /file/path 下的数据文件恢复到 TDengine 集群中。
4.1.2 备库同步用户
1.备库创建与主库在用的相同的用户,保持账号密码一致。
2.主库和备库均创一个相同的最小权限的只读用户,方便后续代理监测数据库状态使用。
用户和权限管理参考官方文档:
- 用户和权限管理
4.2 Tengine
根据之前的需求,需要配置 Tengine 作为 TDengine 的 HTTP API 代理,并实现高可用故障转移。
4.2.1 创建自定义配置文件
避免覆盖默认配置
sudo mkdir -p /usr/local/src/tengine/conf/conf.d
sudo nano /usr/local/src/tengine/conf/conf.d/tdengine.conf
4.2.2 写入 TDengine 代理配置
编辑tdengine-proxy.conf
配置文件:
# =============================================
# 动态 Upstream 配置:定义 TDengine 后端服务器组
# =============================================upstream tdengine_servers {# 主要后端服务器:192.168.3.55,监听 6041 端口(TDengine 的 HTTP API / REST 接口)# max_fails=3:如果连续 3 次请求失败,则标记此节点为不可用# fail_timeout=30s:在 30 秒内失败达到 max_fails 次数后,该节点会被暂时剔除,30 秒后可能重新尝试恢复server 192.168.3.55:6041 max_fails=3 fail_timeout=30s;# 备用服务器:192.168.3.30,仅当所有非 backup 的服务器都不可用时,才会将请求转发至此server 192.168.3.30:6041 backup;# -------------------------------# Tengine 健康检查模块配置(关键)# 注意:此功能是 Tengine 特有,原生 Nginx 不支持# -------------------------------# 健康检查配置check interval=5000 # 每隔 5000 毫秒(即 5 秒)对后端发起一次健康检查timeout=10000 # 健康检查请求的超时时间为 10 秒rise=2 # 连续 2 次检查成功,标记节点为健康fall=2 # 连续 2 次检查失败,标记节点为不健康type=http # 健康检查类型为 HTTP(适用于 TDengine 的 /rest/sql 接口)port=6041; # 检查的端口,必须与后端服务端口一致# 健康检查发送的 HTTP 请求报文(模拟一次 SQL 查询,检测服务是否存活)# 这是一个标准的 POST 请求,访问 /rest/sql 接口,执行 "select 1;" 语句check_http_send "POST /rest/sql HTTP/1.1\r\nHost: $host\r\nAuthorization: Basic cm9vdDp0YW9zZGF0YQ==\r\nContent-Type: text/plain\r\nContent-Length: 9\r\n\r\nselect 1;";# 健康检查响应校验:只检查 HTTP 响应状态码是否为 2xx (即请求是否成功返回)# 如果希望更严格,可以进一步校验返回的 JSON 中的 code 是否为 0(需要 Tengine 支持更高级匹配,如 json 匹配)check_http_expect_alive http_2xx;# 注意:下面这行是注释掉的,因为 Tengine 默认可能不支持直接匹配 JSON 字段(如 {"code":0})# 如果你的 Tengine 支持高级健康检查匹配(如 json 匹配模块),可以取消注释并配置:# check_http_match json:{"code":0};# 会话保持策略:使用 ip_hash,确保同一个客户端的请求始终落到同一台后端服务器# 适用于需要“有状态”访问的场景,比如避免频繁切换导致会话或缓存不一致ip_hash;
}# =============================================
# Server 块:监听 6041 端口,接收客户端请求并代理到上游的 TDengine 服务器
# =============================================server {# 监听 6041 端口(与 TDengine 的 HTTP API 端口一致)listen 6041;# -------------------------------# 反向代理核心配置# -------------------------------location / {# 将请求反向代理到上面定义的 tdengine_servers upstream 组proxy_pass http://tdengine_servers;# 代理协议相关头部设置(确保后端能获取到真实的客户端信息)proxy_http_version 1.1; # 使用 HTTP/1.1 协议(支持长连接等特性)proxy_set_header Host $host; # 设置请求的 Host 头proxy_set_header X-Real-IP $remote_addr; # 记录客户端真实 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 记录经过的代理 IP 链proxy_set_header Upgrade $http_upgrade; # 支持 WebSocket 等升级协议proxy_set_header Connection $http_connection;# -------------------------------# 超时控制(根据业务需求调整)# -------------------------------proxy_read_timeout 600s; # 读取后端响应的超时时间(600 秒,适合复杂查询)proxy_send_timeout 600s; # 发送请求到后端的超时时间proxy_connect_timeout 600s; # 与后端建立连接的超时时间# -------------------------------# 故障转移相关配置# -------------------------------proxy_next_upstream error timeout http_500 http_502 http_503 http_504 non_idempotent;# 如果出现以下错误,尝试自动切换到下一个可用的 upstream 服务器:# - error:连接失败等底层错误# - timeout:请求超时# - http_500 / 502 / 503 / 504:后端返回这些 HTTP 错误码# - non_idempotent:允许对非幂等请求(如 POST)也进行重试(谨慎使用)proxy_next_upstream_timeout 10; # 故障转移时,最多等待 10 秒尝试下一个节点proxy_next_upstream_tries 3; # 最多尝试 3 次(包括首次)}# =========================================# 健康检查状态页(Tengine 提供)# 访问 /status 可以查看 upstream 各节点的健康状态# =========================================location /status {# 启用 Tengine 的健康检查状态监控页面check_status;access_log off; # 关闭该页面的访问日志(避免日志过大)}# =========================================# 默认访问页面(可选)# 访问根路径 / 返回一个简单的文本提示# =========================================location = / {return 200 'Tengine TDengine Proxy is operational\n';add_header Content-Type text/plain;}
}
注意:
- Authorization: Basic cm9vdDp0YW9zZGF0YQ== 是 root:taosdata 的 Base64 编码,请确保 TDengine 监测用户权限配置正确。如果你修改了 TDengine 的用户名或密码,需要同步更新这里的 Authorization 头。
- /status 页面访问控制:目前 /status 是开放的,生产环境中建议增加访问限制(如 IP 白名单、Basic Auth 等),避免泄露后端状态信息。
- 超时与重试参数调优:根据你的业务场景(如查询复杂度、网络延迟等),可以适当调整 proxy_read_timeout、proxy_next_upstream_timeout 等参数。
- 日志与监控:建议开启 Tengine 的 access 日志(或部分路径的日志),便于排查问题。可通过 /status 页面实时查看 upstream 各节点健康状态,实现快速故障定位。
编辑主配置文件nginx.conf
:
# =============================================
# Tengine 或 Nginx 主配置文件
# 通常文件名为 nginx.conf 或 tengine.conf
# 此配置为服务的基础配置,包含全局运行参数、事件模型、HTTP 服务定义等
# =============================================# -------------------------------
# 运行用户配置(通常注释掉,使用默认用户,如 nobody 或 nginx)
# -------------------------------
#user nobody;
# 如果你希望 Tengine/Nginx 以特定系统用户身份运行(如 nginx、tengine),可以取消注释并指定,例如:
# user nginx;
# user tengine;
# 默认情况下,Tengine/Nginx 通常以 nobody 或编译时指定的用户运行。# -------------------------------
# 工作进程数配置:自动根据 CPU 核心数设置
# -------------------------------
worker_processes auto;
# 定义 Tengine/Nginx 启动的工作进程数,通常设置为 auto 让其自动检测 CPU 核心数量并启动对应进程数,
# 也可以手动指定,例如:worker_processes 4;# -------------------------------
# 错误日志配置
# -------------------------------
error_log logs/error.log;
# 定义错误日志的存储路径,这里为相对路径 logs/error.log(相对于 Tengine/Nginx 的安装目录或 prefix 路径)
# 错误日志用于记录服务运行过程中的错误、警告等信息,是排查问题的重要依据# 可选:你可以取消注释下面的某一行,调整错误日志的记录级别:
# #error_log logs/error.log notice; # 记录 notice 级别及以上的日志信息
# #error_log logs/error.log info; # 记录 info 级别及以上的日志信息# 另外,你也可以将错误日志输出到管道,进行日志切割和归档(当前是注释掉的):
# #error_log "pipe:rollback logs/error_log interval=1d baknum=7 maxsize=2G";# -------------------------------
# 进程 PID 文件(记录主进程 ID,默认注释掉,通常位于 logs/nginx.pid)
# -------------------------------
#pid logs/nginx.pid;
# 定义存储 Tengine/Nginx 主进程 PID 的文件路径,用于管理进程(如启动、停止、重载配置)
# 默认情况下通常位于 logs/nginx.pid,也可以自定义路径# -------------------------------
# events 块:定义与连接处理模型相关的参数
# -------------------------------
events {worker_connections 1024;# 每个工作进程允许的最大并发连接数,即每个工作进程可以同时处理 1024 个连接# 如果你的服务器并发访问量较高,可以适当调大此值,比如 2048、4096# 注意:总并发连接数 ≈ worker_processes × worker_connections
}# -------------------------------
# http 块:定义 HTTP 服务的全局配置
# -------------------------------
http {include mime.types;# 引入 MIME 类型定义文件,通常为 conf/mime.types# 该文件定义了各种文件扩展名对应的 Content-Type,例如 .html -> text/html, .jpg -> image/jpeg# 用于正确设置响应头中的 Content-Type 字段default_type application/octet-stream;# 默认的 MIME 类型,当请求的文件类型未在 mime.types 中匹配时,使用此默认类型# application/octet-stream 表示二进制流,通常用于文件下载# -------------------------------# 日志格式定义(当前被注释,未启用)# -------------------------------#log_format main '$remote_addr - $remote_user [$time_local] "$request" '# '$status $body_bytes_sent "$http_referer" '# '"$http_user_agent" "$http_x_forwarded_for"';# 定义一个名为 main 的日志格式,包含客户端 IP、时间、请求内容、状态码、响应大小、来源页、用户代理等信息# 可用于 access_log 记录详细的访问日志# -------------------------------# 访问日志配置(当前被注释,未启用)# -------------------------------#access_log logs/access.log main;# 启用访问日志,并使用上面定义的 main 格式记录每个请求的详细信息# 可选:使用管道进行日志切割与归档(比如按天切割、限制大小等,当前注释掉):# #access_log "pipe:rollback logs/access_log interval=1d baknum=7 maxsize=2G" main;# -------------------------------# 高性能传输相关配置# -------------------------------sendfile on;# 启用 sendfile 零拷贝传输机制,提升静态文件(如图片、CSS、JS)的发送效率,减少用户态与内核态数据拷贝# 推荐开启,除非你的系统不支持#tcp_nopush on;# 仅在 sendfile 开启时生效,用于优化数据包的发送策略,提高网络传输效率# -------------------------------# 长连接超时时间配置# -------------------------------#keepalive_timeout 0;keepalive_timeout 65;# 设置客户端与服务器之间的长连接保持时间,单位为秒# 即客户端在多长时间内没有新请求时,Tengine/Nginx 会主动关闭连接# 默认 65 秒是一个较为通用的设置,可根据业务需求调整# -------------------------------# gzip 压缩配置(当前注释掉,未启用)# -------------------------------#gzip on;# 是否启用 gzip 压缩功能,开启后可以对响应内容(如 HTML/JSON/CSS/JS)进行压缩,减少传输数据量,提升加载速度# 如果需要启用,取消注释,并可进一步配置 gzip_types 等参数# -------------------------------# 引入自定义配置文件(模块化管理配置,推荐!)# -------------------------------include /usr/local/src/tengine/conf/conf.d/*.conf;# 引入 conf.d 目录下的所有 .conf 文件,常用于将不同功能模块(如 server 块、upstream 块、location 路由等)拆分到独立文件中管理# 推荐将不同虚拟主机、代理规则、静态资源目录等配置拆分到 conf.d/ 目录下,便于维护# -------------------------------# map 指令:动态变量映射(常用于协议升级,如 WebSocket)# -------------------------------map $http_upgrade $connection_upgrade {default upgrade;'' close;}# 功能:根据客户端请求头中的 $http_upgrade 值动态设置变量 $connection_upgrade 的值# 应用场景:主要用于支持 WebSocket 协议或 HTTP 长连接升级# - 如果 $http_upgrade 有值(比如 "websocket"),则 $connection_upgrade = upgrade# - 如果为空,则 $connection_upgrade = close# 通常与 proxy_set_header 和 proxy_pass 配合使用,实现 WebSocket 代理# -------------------------------# server 块:定义一个监听 8088 端口的 HTTP 服务# -------------------------------server {listen 8088;# 监听本机 8088 端口,可以是 HTTP 默认端口 80、HTTPS 默认端口 443,或者自定义端口如 8088、8888 等# 该服务将响应发送到此端口上的 HTTP 请求server_name localhost;# 定义该 server 块匹配的服务器名称(即域名),这里设置为 localhost# 通常用于开发环境,生产环境中应设置为你的实际域名,如 example.com 或 *.example.com# 你可以配置多个 server_name,支持基于域名的虚拟主机# =========================================# 此处通常会继续定义:# - location / {} # 根路径的路由规则,比如反向代理、静态文件目录等# - proxy_pass # 反向代理到后端服务# - root / alias # 静态文件路径# - 其他 location 块# =========================================location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
}
4.2.3 测试验证
测试配置并重载 Tengine:
# 测试配置语法是否正确
sudo /usr/local/src/tengine/sbin/nginx -t# 重载配置(不中断服务)
sudo /usr/local/src/tengine/sbin/nginx -s reload
五、验证高可用功能
5.1 检查健康状态
# 查看上游节点状态(需 Tengine 支持 status 模块)
curl "http://127.0.0.1/status/upstream?upstream=tdengine_backend"
输出应显示节点状态(up 或 down)。
5.2 模拟故障转移
1.手动停止一台 TDengine 节点:
sudo systemctl stop taosd # 假设 TDengine 通过 systemd 管理
2.观察 Tengine 日志:
tail -f /usr/local/src/tengine/logs/error.log
3.通过 /status 页面实时查看 upstream 各节点健康状态:
4.再次访问代理端口,验证请求是否自动切换到其他节点:
curl -u root:taosdata "http://127.0.0.1:6041/rest/sql?query=SELECT+1"
六、小结
本文通过构建双活冗余的高可用时序数据处理架构,通过以下核心组件实现全链路冗余与自动故障切换:
- 双独立数据链路:业务数据写入服务分别连接主备两套TDengine时序库,形成双写冗余。
- 统一代理入口:所有业务请求通过单一的Tengine代理服务访问数据库,代理层集成健康监控与自动故障转移能力。
- 无缝故障切换:代理实时检测数据库状态,主库故障时自动切换至备库,主库恢复后支持自动回切,确保业务持续访问。
关键特性
- 高可用保障:主备TDengine库互为冗余,结合代理层的健康检查与自动切换,避免单点故障导致的数据不可用。
- 低改造成本:业务应用仅需连接统一的Tengine代理地址,无需感知底层主备库切换逻辑,无需大规模修改代码。
- 存量表同步:聚焦存量表结构的可靠同步(手动维护超级表),暂不强制要求跨节点实时数据复制,降低复杂度。
- 快速故障恢复:代理层实时监控数据库健康状态,故障转移响应迅速,满足高时效性的RTO要求。
核心组件
- Tengine:基于Nginx优化的代理服务,支持高并发场景,集成健康检查、负载均衡及自动故障转移功能,作为业务访问的唯一入口。
- TDengine:高性能时序数据库,负责存储和管理时序数据,主备库通过双写和代理切换实现冗余。
该方案通过“双写+统一代理+智能切换”的组合设计,在资源受限和应用低改造的前提下,有效解决了数据丢失风险,保障了系统的连续性与可靠性。