1. 项目背景与挑战
去年ChatGPT用户量突破1亿时,我们的PostgreSQL集群已经出现性能瓶颈。当预测显示年底用户可能达到8亿规模时,数据库团队面临前所未有的挑战:单集群写入QPS需要从5万提升到40万,同时保证99.99%的可用性。
传统垂直扩容方案在3台物理机满配SSD的情况下,写入性能仅能达到15万QPS。我们最终选择了分布式架构改造路线,通过分库分表+读写分离+缓存层的组合方案,用6个月时间完成了平滑迁移。现在这套系统每天处理200TB新增数据,支撑着全球用户对话的持久化存储。
2. 架构设计方案
2.1 数据分片策略
采用用户ID哈希分片,将8亿用户数据分散到256个物理分片。每个分片组包含:
- 1个主库(16核64G内存 NVMe SSD)
- 2个只读副本(用于负载均衡)
- 1个延迟副本(用于备份和ETL)
分片键设计为user_id % 256,确保同一用户的对话记录始终落在同一分片。我们在应用层实现了分片路由中间件,自动将SQL路由到对应分片。
2.2 读写分离实现
所有写操作直连主库,读操作根据业务特征分流:
- 实时性要求高的查询(如最近对话)走主库
- 历史数据分析走只读副本
- 报表类查询走延迟副本
通过配置default_transaction_read_only参数,强制只读副本拒绝写操作。使用hot_standby_feedback避免只读查询被取消。
3. 性能优化实践
3.1 分区表优化
对话记录表按时间范围分区:
sql复制CREATE TABLE messages (
id BIGSERIAL,
user_id BIGINT,
content TEXT,
created_at TIMESTAMPTZ
) PARTITION BY RANGE (created_at);
每天自动创建新分区,旧分区每月合并归档。通过pg_partman扩展实现自动化管理:
sql复制SELECT partman.create_parent(
'public.messages',
'created_at',
'native',
'daily',
p_start_partition := CURRENT_DATE::text
);
3.2 连接池配置
使用PgBouncer实现连接池,关键参数:
code复制pool_mode = transaction
max_client_conn = 10000
default_pool_size = 20
reserve_pool_size = 5
每个应用服务器部署独立的PgBouncer实例,避免连接风暴。通过SHOW POOLS命令实时监控连接使用情况。
4. 高可用保障
4.1 故障自动转移
基于Patroni实现HA:
yaml复制restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.0.1:8008
etcd:
hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
当主库故障时,能在30秒内完成自动选主。通过patronictl list命令查看集群状态。
4.2 跨机房同步
采用级联复制架构:
code复制主库 -> 同机房副本 -> 异地机房副本
配置wal_level = logical + synchronous_commit = remote_write,确保数据不丢失。使用pg_stat_replication监控复制延迟。
5. 监控与调优
5.1 关键指标监控
部署Prometheus + Grafana监控:
- 查询延迟:
histogram_quantile(0.95, rate(pg_stat_statements_total_time_seconds_bucket[1m])) - 复制延迟:
pg_replication_lag - 缓存命中率:
sum(pg_stat_database_blks_hit) / sum(pg_stat_database_blks_hit + pg_stat_database_blks_read)
5.2 参数调优
针对NVMe SSD优化的关键参数:
code复制shared_buffers = 16GB
effective_cache_size = 48GB
random_page_cost = 1.1
max_worker_processes = 16
maintenance_work_mem = 2GB
使用pg_repack在线重建表消除膨胀,避免锁表:
bash复制pg_repack -d chatgpt -t messages
6. 经验总结
在实际运行中,我们发现了几个关键点:
- 批量写入性能比单条写入高10倍,建议应用层实现批量提交
- 长连接会导致内存持续增长,需要定期重启连接池
- 逻辑解码消耗大量CPU,需要单独部署解码节点
- 每月一次的统计报表会导致副本延迟,需要单独路由到延迟副本
通过这套架构,我们最终实现了:
- 写入吞吐:50万QPS
- 查询延迟:<50ms (P99)
- 数据可靠性:99.9999%
- 扩展能力:支持未来用户增长到20亿