Kratos未内置分库分表,因其定位是轻量级、契约优先的微服务框架,Data层只封装数据访问,不介入存储拓扑决策;分片逻辑需开发者在Repository中自主实现,如按user_id哈希选库或按时间动态建表。

Kratos 本身不提供分库分表能力,必须靠外部方案或自研逻辑实现,直接在 Data 层硬编码分片逻辑是最常见也最可控的做法。
为什么 Kratos 没有内置分库分表?
Kratos 的定位是「轻量级、契约优先、分层清晰」的微服务框架,Data 层只负责封装数据访问,不介入存储拓扑决策。它把数据库连接、事务、查询抽象成接口(如 DataRepo),但具体用一个 DB 还是多个 DB、按 user_id 拆还是按时间拆,完全交由开发者决定。
这意味着:你不能指望 kratos new 或 kratos proto 自动生成分片路由代码;所有分片键解析、连接池选择、跨库事务协调,都得自己写。
- 框架只保证
data.UserRepo接口能被service层调用,不管这个UserRepo背后连的是mysql-01还是shard-2024-q3 - 如果你用 GORM,
gorm.DB实例本身不带分片能力;SQLx 也一样,*sqlx.DB是单实例对象 - Protobuf 定义和 gRPC 接口完全感知不到分库——它们只管字段和 RPC 合约
主流分库分表落地方式(Data 层怎么写)
实际项目中,90% 的 Kratos 分库分表都落在 Data 层的 Repository 实现里,而不是框架配置或中间件。关键在于:把分片逻辑封装进 Repo 方法内部,对外保持接口不变。
- 按分片键(如
user_id)哈希取模:shardIndex := int(user_id) % 4,再从预定义的 DB 列表选dbList[shardIndex] - 按时间范围分表(如日志类):
tableName := fmt.Sprintf("log_%s", time.Now().Format("200601")),拼进 SQL 或 GORMTable()调用 - 读写分离 + 分库混合:写走主库集群,读按业务域路由到不同从库(例如用户读走
user-ro,订单读走order-ro) - 避免在 Service 层做路由判断——那会污染业务逻辑;所有分片判定必须收口在
*UserRepo的Get()、Create()等方法内
示例(GORM 场景):
func (r *UserRepo) Get(ctx context.Context, id int64) (*User, error) {
db := r.getShardDB(id) // 内部根据 id 算出对应 *gorm.DB
var u User
if err := db.WithContext(ctx).First(&u, id).Error; err != nil {
return nil, errors.Wrapf(err, "failed to get user: %d", id)
}
return &u, nil
}
跨分片查询和事务的现实约束
一旦分库,就基本放弃「单 SQL JOIN 多库表」和「跨库事务(XA)」。Kratos 不提供分布式事务组件,也不建议你在 Data 层强行封装两阶段提交。
- 聚合查询(如「查某用户最近 5 条订单+对应商品信息」)必须由 Service 层发起多次单库调用,再内存合并
- 强一致性写场景(如扣库存+生成订单)应尽量设计成「单分片内完成」,比如把
user_id和order_id绑定同一分片规则 - 最终一致性靠消息队列补位:下单成功后发 MQ,下游服务消费并更新用户统计等跨片视图
- 不要试图用
database/sql的BeginTx包裹多个 DB 连接——Go 标准库不支持跨连接事务,会静默失败或只作用于第一个 DB
要不要引入 ShardingSphere-Proxy 或 Vitess?
可以,但和 Kratos 集成时要克制。这类代理层解决的是「对应用透明」的问题,而 Kratos 项目通常更倾向「逻辑透明、物理可控」。
- 如果团队运维能力强、能接受 DBA 管控分片策略,用 ShardingSphere-Proxy 是可行的——Kratos 应用只需当它是个普通 MySQL 地址连
- 但要注意:代理层无法透传 gRPC 元数据(如
metadata.MD中的 trace-id),链路追踪会断在代理节点;SQL 注释(如/*+ shard_key=user_id */)需严格匹配代理语法 - Vitess 更重,适合已跑在 Kubernetes 上且有 DBA 团队支撑的场景;对中小团队,直接在 Kratos Data 层写分片逻辑反而迭代更快、问题更可定位
真正容易被忽略的点是:分片键一旦选定就极难变更,而 Kratos 的 Protobuf 接口和 Data 层模型又天然鼓励「稳定契约」。所以选键不是技术问题,是业务生命周期问题——别只看 user_id % 128 好不好算,要想清楚三年后要不要按区域再拆一层。


















