feat: support shared tenant database sharding

This commit is contained in:
richjohnrambo
2026-09-22 15:21:34 +08:00
parent 0596599db9
commit 851eca97ed
6 changed files with 265 additions and 76 deletions
+31 -10
View File
@@ -23,7 +23,7 @@ const registryDbGroup = "imRegistry"
var registryDbGroupOnce sync.Once
// DB resolves a tenant registry record and returns the corresponding business DB.
// DB resolves a tenant registry record and returns the shared IM business DB.
func DB(ctx context.Context, tenantId int64) (db gdb.DB, tenant *entity.ImTenant, err error) {
if tenantId <= 0 {
return nil, nil, gerror.New("租户ID不能为空")
@@ -36,27 +36,48 @@ func DB(ctx context.Context, tenantId int64) (db gdb.DB, tenant *entity.ImTenant
return nil, nil, gerror.New("租户不存在")
}
link, err := tenantLink(ctx, tenant)
db, err = SharedDB(ctx)
if err != nil {
return nil, nil, err
}
return db, tenant, nil
}
group := fmt.Sprintf("im_tenant_%d_%x", tenant.Id, hash(link))
// SharedDB returns the common IM database configured by the default tenant.
// Tenant isolation inside this database is implemented by tenant_id predicates
// and the three tenant-partitioned high-volume table families.
func SharedDB(ctx context.Context) (gdb.DB, error) {
var sharedTenant *entity.ImTenant
if err := RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).
Where(dao.ImTenant.Columns().Code, "default").Scan(&sharedTenant); err != nil {
return nil, gerror.Wrap(err, "获取共享业务库配置失败")
}
if sharedTenant == nil || sharedTenant.Id <= 0 {
return nil, gerror.New("默认商户不存在,无法确定共享业务库")
}
link, err := tenantLink(ctx, sharedTenant)
if err != nil {
return nil, err
}
return dbForLink(link, sharedTenant.Id)
}
func dbForLink(link string, ownerID int64) (gdb.DB, error) {
group := fmt.Sprintf("im_shared_%d_%x", ownerID, hash(link))
if cached, ok := tenantDbGroups.Load(group); ok && cached == link {
db, err = gdb.Instance(group)
return db, tenant, err
return gdb.Instance(group)
}
if err = gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
return nil, nil, gerror.Wrap(err, "初始化租户业务库连接失败")
if err := gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
return nil, gerror.Wrap(err, "初始化共享业务库连接失败")
}
tenantDbGroups.Store(group, link)
db, err = gdb.Instance(group)
db, err := gdb.Instance(group)
if err != nil {
return nil, nil, gerror.Wrap(err, "获取租户业务库连接失败")
return nil, gerror.Wrap(err, "获取共享业务库连接失败")
}
return db, tenant, nil
return db, nil
}
// RegistryDB returns the dedicated tenant registry connection, or the default