saas 类型的系统,目前是采用了最 low 的行级多租户,也就是每个表加一个 tenantId,然后用代码逻辑隔离,现在随着系统的用户增长,很多问题随着出现了,维护麻烦,性能低效,代码逻辑复杂混乱
于是决定重构,打算采用多租户的另外一套方案,单库多 schema,但查阅了资料,发现 mysql 根本没有真正意义上的 schema,或者说 schema 就是 database
再后来了解到 PostgreSql,感觉国内资料挺少的,用的也很少,但看到一些比较资料发现他比 mysql 好太多了,但又怕上了踩坑,而且还要数据迁移之类的,有没有大佬给个方案
1
czyt 2021-05-11 15:22:01 +08:00
有迁移数据库的需求,建议开发的时候用 orm
|
2
ez728s 2021-05-11 15:27:10 +08:00
怕不是因为方案 low
|
3
xiaoxinshiwo 2021-05-11 15:28:36 +08:00
淘宝算不算多租户系统?
|
4
lostSoul OP @ez728s 就是因为方案 low 才改的 我现在已经想到另外一方案 采用 Mysql+MyCat 中间件,采用 mycat 去增强 mysql 的功能,mycat 中间件提供了多租户方案,实现 SQL 方式切换数据源
|
5
emmettwoo 2021-05-11 15:44:10 +08:00
插眼等老哥们的方案,这种用数据库字段隔离然后代码去判断真的太难受了。
|
6
312ybj 2021-05-11 15:48:46 +08:00 1
我们公司的数据隔离级别就是单独 schema, 使用 myact 拦截 sql,从而导向不同的数据库。redis 也这样干的。
|
7
BQsummer 2021-05-11 15:52:38 +08:00
租户 id 放 theadlocal,自定义个 mybatis 插件,自动补全租户 id 的查询条件,在业务层面不需要额外处理租户的信息,还是体验可以的。好处是数据库层可以简单化,没啥 low 不 low 的。
|
8
wangxiaoaer 2021-05-11 15:53:32 +08:00 1
”现在随着系统的用户增长,很多问题随着出现了,维护麻烦,性能低效,代码逻辑复杂混乱“
租户表示我不背这个锅。 |
9
johnsona 2021-05-11 15:56:29 +08:00 via iPhone
@emmettwoo 判断 tenantid 是吧
orm 的方案的话可以 hook 一下自动带上 tenantid |
10
FightPig 2021-05-11 15:57:14 +08:00 1
不建议 schema 模式,tenantId 模式挺好的,schema 随着用户多起来,你会发现很头疼,如果你再有要查询多租户信息的需求,你就要崩溃了
|
11
lostSoul OP @wangxiaoaer 哈哈 不被也得背啊 没办法 现在新建一个商户 虽然他看不到其他租户的数据 但都等于他有 100W 条数据了 大家同一条船迟早都得淹死
|
12
lostSoul OP @FightPig 查询多租户需求也是可以满足的吧 我目前这个方案而言 我们已经用血的教训证明 tenantId 并不是长久方案
|
13
tairan2006 2021-05-11 16:10:19 +08:00 1
你这个思路好奇怪…而且这都 2021 年了,还有人用 Mycat ?
你直接上 tidb 啊……当然 pg 生态也有 greenplum 之类的 |
14
Huiao 2021-05-11 16:14:42 +08:00
单数据库 多租户表 表名:business_{租户 id} mybatis 插件动态补全表名
|
15
love 2021-05-11 16:19:43 +08:00 3
为什么 tenantId 是最 low 的方案?能列个实际的代码例子吗,我以前的公司也这样,我感觉是最高级的方案,一点不觉得不方便。
反而一个用户一个数据库才是 low 到爆的方案,维护复杂更不用提了 |
16
ipwx 2021-05-11 16:23:28 +08:00 1
我直觉上,tenantId 是很好的方案。但是得配合分库分表,通过 tenantId 哈希到某个机器的数据库上,每个机器上又存储若干 tenantId 的数据。如果之前的数据库满了就增加机器,哈希函数改一改。如果某个租户变成狗大户就专门给他放到狗大户的机器上,狗大户的机器少放点租户,小用户的机器上多放点用户。
|
17
wangxiaoaer 2021-05-11 16:50:07 +08:00
@FightPig #10 楼上有老哥提到淘宝,你说这算不算多租户呢,刚开始我还没觉得,但是一细想,也算多租户,每个商家就是一个租户,维护自己的产品。难道这些产品分别放到不同的库里才是优雅?
你说全部放到一起量大起来迟早淹死,可是我寻思面对这个问题你应该寻求的是海量数据存储、检索的方案,这些应该成熟的吧,什么 nosql 、分布式不行吗? 另外,我觉得 tenantId (其实就是特么的 UserID 了)方案还有个好处:当后面需要做跨租户统计、分析的时候,明显要比多租户方便吧。 |
18
hbkdsm 2021-05-11 18:24:12 +08:00 1
不同意逻辑隔离是最 low 的方案,这是最高效的方案 (虽然牺牲了数据隔离性)
多 db 和 多 schema 维护成本太高了,大表跑 DDL 痛苦死了 Salesforce 就是 tenantID 纯逻辑隔离,Zendesk, Freshdesk, GitHub 都是这样 这是业内最成熟的方案 库大了,还可以根据 tenantID 做水平分库,PostgreSQL 有 Citus,MySQL 有 ShardingSphere,都可以按照 tenantID 分库。 还有 TiDB 这种 NewSQL,或者 Vitess 这种方案。 |
20
dbskcnc 2021-05-11 18:35:15 +08:00
用的 PostgreSql 的话还可以继续用原来的方案的,表针对 tenantID 做 hash 分区,性能和开发都方便
用中间件感觉还是有点折腾,有条件当然可以上 newsql |
21
miao1007 2021-05-11 19:54:10 +08:00
万事不绝,ELK 包治百病,用 ELK 索引作为二级主键
|
22
zzl22100048 2021-05-11 20:06:36 +08:00
元数据驱动模式做 saas 不是更好么
|
23
zieglar 2021-05-11 20:07:13 +08:00
PostgreSQL 做错了什么要把矛头指向它(
|
24
joesonw 2021-05-11 20:18:04 +08:00
其实这种场合 sqlite 很合适.
|
25
AngryPanda 2021-05-11 20:21:36 +08:00 via iPhone
我们 mongodb 分 db 方案
|
26
xuanbg 2021-05-11 21:45:14 +08:00
第三种增加据的维护难度和让代码变得异常复杂???我怎么一点感觉都无?哦哦,我是手写 SQL,无非就是查询条件增加一个 tenantId = #{tenantId}的条件而已。没事了没事了。
|
27
kaneg 2021-05-12 01:45:06 +08:00 via iPhone
table 加 tennat id 如果能在框架层面做还好。否则纯手动维护,如果碰到粗心的程序员在某些语句中忘了加 tenant id,那后果就不可设想了。在某个项目中碰到过这样的案例:开发在本地测试的时候只有一个 tenant,没有测出这个问题。结果在项目上线后被客户发现看到了其他公司的数据。。。
|
28
zzlhr 2021-05-12 08:45:17 +08:00
我们系统用 sqlserver 五年了快,就是 low3 方案,加了个 compid
|
29
securityCoding 2021-05-12 10:54:21 +08:00
tennat id 不是挺好的吗?
|
30
HashV2 2021-05-12 11:30:35 +08:00
哪有什么 low 不 low 的 只看使用场景和需求 能满足的需求的设计就是好设计
|
31
ccppgo 2021-05-12 11:40:56 +08:00
什么意思, 如果有上万个用户就有上万个库吗,,,
|
32
notejava 2021-05-12 12:16:35 +08:00
通过租户 ID 进行数据隔离才是最简单,最好扩展的方案。我目前项目也遇到一模一样的场景。
|
33
lostSoul OP 1.租户处于爆发式增长应该越倾向于共享,因为一旦租户多了起来,不管是单库还是单表多 schema,维护的成本都是巨大的,涉及后期迭代的时间成本也会随即累加(场景:一些对外开放的 Saas 系统,支持用户自主注册使用,而非人工开通或付费开通)
|
34
lostSoul OP 2.租户数量平稳同时租户数据多应该倾向于隔离,使用隔离级别高的有利于对每个租户进行定制化开发而不会影响到其他租户
|
35
lostSoul OP 因为我是新号回复受限只能回复在评论里
|
36
oneforallsoft 2021-05-12 18:46:36 +08:00
|
37
solos 2021-05-12 22:18:52 +08:00
这不是很正常,现在有 tidb / cockroach 这些支持水平扩展的分布式数据库了,更不是问题了
|
38
ccde8259 2021-05-12 23:25:24 +08:00 via iPhone
MySQL 有分区表……
直接拿 tenantId 做 Column Partition 就避免发生新租户上来就在查百万表的情况…… 同时 5.7 开始支持索引条件下推…… |