☰
Go 数据库分库分表:Sharding-JDBC 不适用?go-sharding 实战
2026/10/2 2:23:49 网站建设 项目流程

Go 数据库分库分表:Sharding-JDBC 不适用?go-sharding 实战

单库扛不住时,怎么分库分表?本文讲解落地方案,并给出 Go 实战代码。

一、什么时候分库分表?

  • 单表行数 > 5000 万
  • 单库写入 QPS > 2 万
  • 单库容量 > 1TB
  • 性能退化明显

二、分片策略

2.1 哈希分片

funcshard(iint64,slotint)string{returnfmt.Sprintf("ds_%d",i%int64(slot))}

优点:均匀分布、简单。
缺点:扩容时需要 rehash。

2.2 范围分片

funcshard(uidint64)string{ifuid<1_000_000{return"ds_a"}elseifuid<10_000_000{return"ds_b"}return"ds_c"}

适合时间序列数据,按 ID 或时间切段。

2.3 列表分片

varregionMap=map[string]string{"BJ":"ds_bj","SH":"ds_sh","GD":"ds_gd",}funcshardByRegion(regionstring)string{returnregionMap[region]}

适合枚举型字段。

三、go-sharding 库实战

import"github.com/go-gorm/sharding"db,_:=gorm.Open(mysql.Open(dsn0),&gorm.Config{})db.Use(sharding.Register(sharding.Config{ShardingColumn:"uid",NumberOfShards:64,},"orders"))db.Create(&Order{UID:42,Amount:199})db.Where("uid = ?",42).First(&order)

库内部用 lookup_table 抽象定位分片。

四、go-sql-rewrite 中间件

import"github.com/rguliyev/sql-masker"dsn:=fmt.Sprintf("query_urls=%s;gorm_db=?",strings.Join(dbs,","))db,err:=gorm.Open(mysql.Open(dsn))

原理:在 driver 层拦截 SQL,按分片键重写。

五、跨分片查询

5.1 分页方案

不能简单 OFFSET,得用 “二次查询 + 归并”:

funcfetchAll(uidMin,uidMaxint64)[]Order{res:=make([][]Order,len(shards))varwg sync.WaitGroupfori,sh:=rangeshards{wg.Add(1)gofunc(iint,shstring){deferwg.Done()res[i]=queryShard(sh,uidMin,uidMax)}(i,sh)}wg.Wait()merged:=[]Order{}for_,list:=rangeres{merged=append(merged,list...)}sort.Slice(merged,func(i,jint)bool{returnmerged[i].ID<merged[j].ID})returnmerged}

5.2 聚合方案

把聚合推到各 shard,结果汇总:

SELECTcount(*)cnt,sum(amt)totalFROMtableWHEREdate=?

每个 shard 都跑一次,再聚合。

六、扩容与一致性 hash

扩容时希望最小数据迁移:

typeConsistentHashstruct{ringmap[uint32]stringreplicasint}func(h*ConsistentHash)Add(nodestring){fori:=0;i<h.replicas;i++{key:=hash(node+strconv.Itoa(i))h.ring[key]=node}}

Virtual nodes 让数据均匀。

七、踩坑清单

  1. 跨 shard 事务:XA 难度大,尽量改造业务
  2. 分片键不可变:用户订单等关键字段
  3. 数据倾斜:小心被均匀哈希打到莫一片
  4. 动库前迁移好历史:预先 rebalance
  5. 不要分库过早:单机 90 分效率时再分

八、生产实战:电商订单

  • 按 user_id 哈希分 8 个库
  • 每库按 time 划分 32 张表(共 256 张)
  • 历史订单归档到冷库,Hot 表保留 6 个月

九、未来趋势

  • DBmesh / Vitess 帮助 SQL 透明分片
  • 各大云原生数据库 TiDB、PolarDB-X 提供原生分布式能力
  • 读写分离与多写冲突解决越来越自动化

十、总结与展望

分库分表是经典大表的演进方向,但同时也是架构复杂化的开始。采用 hash 分片+二次查询是好的入手点,结合一致性 hash 与数据迁移工具,扩容可控。

未来:Go 生态在分布式 DB 接入上会更智能,同时提供 GraphQL/Rest 屏蔽跨 shard 查询。

十一、参考文献

  • go-mysql-org 文档
  • sharding-jdbc 文档参考(虽然 Java,但理论通用)
  • Vitess 官方文档

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询