你们在 Go 项目中如何实现分表读写的?插件?手写?代理?

2023-03-21 11:04:47 +08:00
 RedisMasterNode

苦于写了很多重复代码,想了解一下大家在 Go 的项目里面是怎么用 GORM (或者其他 MySQL 客户端,不限 ORM / Raw SQL )来实现分表读写的?

例如 user_tab_00000000 - user_tab_00000199,一共 200 张表,按 user_id % 200 来分表。

了解过的方案:

  1. DAO 层(或操作 DB 层)时根据传入参数计算,相关代码会出现在每个 Query 方法,例如 CreateUser()GetUserByUserID()UpdateUserByUserID()
  2. 挂载插件,init 时定义、注册分表字段、分表算法等等,DAO 层无特殊处理(就像在操作单表一样),实际执行的时候被改写,例如应用里执行 SELECT * FROM user_tab WHERE user_id = 199 最终会被改写成 SELECT * FROM user_tab_00000199 WHERE user_id = 199 发往 MySQL ;
  3. 应用层外挂载 MySQL 的代理,类似 ShardingSphere 这种,流程跟方案 2 类似,只是改写由外部中间件完成。

个人感觉方案 2 是个挺好的思路但是 Go 里面好像没有什么特别好用的中间件。

5112 次点击
所在节点    Go 编程语言
38 条回复
thinkingbullet
2023-03-21 15:08:28 +08:00
https://github.com/flike/kingshard 这个应该是你要找的解决方案虽然我没用过
samin
2023-03-21 15:20:17 +08:00
2 、3 是一样吧 区别在于造轮子还是用现成的工具

最近看了一个帖子 “分库分表必死,分布式数据库必成主流” 意思就是分库分表以后会成为数据库产品自身特性而不是业务系统需要去考虑的

针对题主目前情况 还是建议用 2 灵活些
EAFA0
2023-03-21 15:27:32 +08:00
@lopssh 我们目前是直接分千表, 短期内用户不大量增长的话都够用了
如果需要频繁扩容的话确实不太好处理
xiaocaiji111
2023-03-21 15:56:41 +08:00
没有比较成熟得,毕竟 go 生态摆在这,建议使用分布式数据库,或者使用云厂商服务比如 DRDS
liuxu
2023-03-21 16:32:49 +08:00
其实 mysql 的分区表还是很好用的
poembre
2023-03-21 16:52:21 +08:00
@liuxu
@Famio
分区字段 有个限制 必须主键
kongkongyzt
2023-03-21 16:55:40 +08:00
我们最开始用的 1
后面用的 2
之后改用 3
最后用了腾讯云上一款对标 TiDB 的产品
lance6716
2023-03-21 16:57:23 +08:00
zhongjun96
2023-03-21 18:08:46 +08:00
@zeonll #14 水平分表,比如题主的 “例如 user_tab_00000000 - user_tab_00000199 ,一共 200 张表,按 user_id % 200 来分表。”
假设 id 递增,需要查询最近新增的 200 个用户,那不就是每一张表都要查询。
这种情况怎么处理的?
RedisMasterNode
2023-03-21 18:46:29 +08:00
@Famio
@OutOfMemoryError
有历史原因的 Partition 有些场景不让使用(不管它是否好用,但是出于某些原因确实是不能使用)
RedisMasterNode
2023-03-21 18:47:05 +08:00
@kiddingU resolver 只解决连不同 db 的问题吧,好像不是解决分表的问题的
RedisMasterNode
2023-03-21 18:47:58 +08:00
@thinkingbullet Nice to hear. 不管好不好用,可以了解一下,感谢~
RedisMasterNode
2023-03-21 18:54:28 +08:00
@Famio @OutOfMemoryError 对了还有一个原因是因为有些 sharding 算法并不是简单的取余,也是因为业务的特殊原因,需要实现一些奇奇怪怪的内容进去,所以不能只依靠 partition
dreamramon
2023-03-21 19:52:18 +08:00
直接上 ShardingSphere
dreamramon
2023-03-21 19:57:05 +08:00
或者直接 yugabytedb ,sharding 非常容易,一个命令的事情。
zeonll
2023-03-22 17:06:04 +08:00
@zhongjun96 这种类型的查询应该不会是 toC 量级的 qps 吧,如果次数不多就遍历呗,如果是相对高频(比如营销平台),那就搞离线数据库,汇总数据
S1ngleton
2023-03-22 20:00:15 +08:00
@lopssh 一致性 hash😂
RedisMasterNode
2023-03-22 20:41:59 +08:00
@zhongjun96 binlog 同步到 clickhouse 或者 es 直接查询,相当于用双倍的空间分别支撑 OLTP 和 OLTP 查询,如果能接受较长延迟 /执行耗时,或者说有超大批量查询要求的话应该转移到离线数仓去。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/925774

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX