SRE & AI 实践录

分布式数据库分库分表策略与一致性保障

· 更新于 2026-07-26 ⏱️ 阅读约 2 分钟 (632 字) 数据库 分布式 Go

深入探讨分布式数据库场景下的分库分表设计策略,涵盖哈希分片、范围分片及分布式事务一致性保障方案。

一、分库分表策略

当单库数据量达到 TB 级别时,分库分表成为必然选择。常见的分片策略包括哈希分片、范围分片和一致性哈希。选择合适的分片键是设计的核心。

二、Go 分片逻辑实现

以下示例展示了一个使用 Go 实现的一致性哈希分片路由器,负责将请求路由到正确的数据库分片。

Go 分片逻辑

go
package shard

import (
	"crypto/sha256"
	"fmt"
	"hash/crc32"
)

type Router struct {
	shards []string
}

func NewRouter(nodes []string) *Router {
	return &Router{shards: nodes}
}

// ShardKey 根据用户ID计算目标分片
func (r *Router) ShardKey(userID string) string {
	h := crc32.ChecksumIEEE([]byte(userID))
	idx := int(h) % len(r.shards)
	return r.shards[idx]
}

// ShardKeyConsistent 一致性哈希分片
func (r *Router) ShardKeyConsistent(userID string) string {
	hash := sha256.Sum256([]byte(userID))
	value := int(hash[0])<<24 | int(hash[1])<<16 |
		int(hash[2])<<8 | int(hash[3])
	idx := value % len(r.shards)
	// 虚拟节点支持(简化)
	return r.shards[idx]
}

func main() {
	nodes := []string{"shard-0", "shard-1", "shard-2", "shard-3"}
	router := NewRouter(nodes)

	userIDs := []string{"user_1001", "user_1002", "user_1003"}
	for _, uid := range userIDs {
		shard := router.ShardKeyConsistent(uid)
		fmt.Printf("User %s -> %s\n", uid, shard)
	}
}

SQL 查询示例

sql
-- 创建分片表
CREATE TABLE IF NOT EXISTS orders_0000 (
    id BIGINT PRIMARY KEY,
    user_id VARCHAR(64) NOT NULL,
    amount DECIMAL(12,2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id)
);

-- 跨分片查询(需在应用层合并结果)
-- 查询语句将在每个分片上独立执行
SELECT user_id, SUM(amount) as total
FROM orders_0000
WHERE created_at >= '2026-01-01'
GROUP BY user_id;

三、一致性保障

分布式事务推荐使用 TCC 或 Saga 模式,结合最终一致性补偿机制。对于读场景,可使用读写分离与缓存预热策略提升性能。

本文作者:技术领航员 | 许可协议:CC BY-NC-SA 4.0

本文链接:https://sre-ai-blog.pages.dev/zh/posts/database-sharding/(转载请注明出处)