gorm-sharding分表插件升级版

news2025/1/11 0:47:50

代码地址: GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别.解决了原生sharding的三个问题:1.不支持不带分表键的查询 2,不支持不同分表策略的配置 3.没有配置分表的自定义sql可能因为无法解析而发生异常

更新点

💡

原生gorm-sharding支持的功能有限,在公共包common中做了功能的扩展

  • 本插件的gorm版本与现在的大部分服务一致v1.20.8,与原作者的不一致,避免版本冲突
  • 原sharding解析sql用的sqlParse不一定能成功解析一些自定义的复杂sql,所以遇到解析不了的直接扔给gorm处理。如果涉及到分表的则需改成可以被sharding识别的标准gorm sql写法
  • 原sharding本身不支持全表扫描,在此做了支持
  • 原sharding不支持全表汇总查询,在此做了对count和sum的支持
  • 原sharding不支持多分表配置不同分表策略,在此增加了配置接口

简要

Gorm Sharding 插件使用 SQL 解析器和替换将大表拆分为较小的表,将查询重定向到分片表。给您高性能的数据库访问。

Gorm Sharding 是一个高性能的数据库分表中间件。

它基于Conn层做SQL拦截、AST解析、分表路由、自增主键填充,带来的额外费用极小。对开发者友好、透明,使用上与普通SQL、Gorm查询无差别,只需要额外注意一下分表键条件。

注意事项

  • 1.不要自己拼接sql会导致无法识别分表键,目前解析的是gorm条件表达式,而不是sql树(binaryTree),所以无法支持原生sql的分表 建议写法.where().orderby().limit().offset().find这样子
  • 2.查询条件需要分表键,如果没有的话需要UnionFlag 配置为true才不会报错,但是会导致全表扫描,慎用

特征

  • 非侵入式设计。加载插件,指定配置,一切就完成了。
  • 快如闪电。没有基于网络的中间件,与 Go 一样快。
  • 多种数据库(PostgreSQL、MySQL)支持。
  • 集成主键生成器(Snowflake、PostgreSQL 序列、自定义等)。

快速上手

1. go mod引入

2. gorm插件加载


    shardByOrderIdConf := gormsharding.Config{
        ShardingKey:        "order_id",
        NumberOfShards:      uint(shardingNumber),
        PrimaryKeyGenerator: gormsharding.PKCustom, 
        PrimaryKeyGeneratorFn: func(_ int64) int64 {
            return 0
        },
        ShardingAlgorithm: func(value any) (suffix string, err error) {
            if orderId, ok := value.(string); ok {
                return fmt.Sprintf("_%04d", HashStr(orderId)%shardingNumber), nil
            }
            return "", errors.New("invalid orderId")
        },
        ShardingAlgorithmForUnion: func(tableId int) (suffix string, err error) {
            return fmt.Sprintf("_%04d", tableId), nil
        },
        UnionFlag: true,
    }

    db.Use(gormsharding.RegisterMultiConf(map[string]gormsharding.Config{
        "order":            shardByOrderIdConf,
    }))

原始代码加载方式:

    //分表中间件
    DBHandle.Use(sharding.Register(sharding.Config{
        ShardingKey:    ShardingKey,
        NumberOfShards: ShardingNumber,
        //PrimaryKeyGenerator: sharding.PKMySQLSequence,
        PrimaryKeyGenerator: sharding.PKCustom,
        PrimaryKeyGeneratorFn: func(_ int64) int64 {
            return 0
        },
    }, ShardTablesByUid...))

dao层调用

尽量采用gorm的标准写法,避免使用原生sql,可能导致无法分表

示例代码

    orm := dao.GetKpayDB()
    db := orm.DBHandle.Table("order")
    if order.Uid != 0 {
        db = orm.DBHandle.Table("uid_order")
    }
    getOrderCondition(order, db)
    db = db.Order(" create_tm desc ")
    if order.CurPage > 0 && order.PageSize > 0 {
        db = db.Limit(order.PageSize).Offset((order.CurPage - 1) * order.PageSize)
    }
    err = db.Find(&orders).Error
    if err != nil && err != gorm.ErrRecordNotFound {
        _ = log.Error(nil, fmt.Sprintf("GetOrders error, err=%v", err))
        return
    }

工作原理

原理图

插件加载

Sharding实现了gorm接口

// Plugin GORM plugin interface
type Plugin interface {
   Name() string
   Initialize(*DB) error
}

Initialize中执行了函数compile

参数预处理(分表主键算法、后缀处理)

Initialize中生成了gorm语句执行的钩子,switchConn主要处理双写的

func (s *Sharding) registerCallbacks(db *gorm.DB) {
    s.Callback().Create().Before("*").Register("gorm:sharding", s.switchConn)
    s.Callback().Query().Before("*").Register("gorm:sharding", s.switchConn)
    s.Callback().Update().Before("*").Register("gorm:sharding", s.switchConn)
    s.Callback().Delete().Before("*").Register("gorm:sharding", s.switchConn)
    s.Callback().Row().Before("*").Register("gorm:sharding", s.switchConn)
    s.Callback().Raw().Before("*").Register("gorm:sharding", s.switchConn)
}

sharding实现gorm的接口

type ConnPool interface {
    PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
    ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
    QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
    QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}

实现的接口中都会调用resolve的函数 (解决旧查询拆分为全表查询和分表查询)

配置参数说明

以下标红的是本包中新增的字段

  1. UnionFlag
    • 类型:布尔值
    • 说明:表示是否启用联合查询标志。当为 true 时,即使没有分表键,也能够查询,但会扫描全表,需要注意性能问题。 建议配成false,暴露出没有分表键的查询
  2. DoubleWrite
    • 类型:布尔值
    • 说明:表示是否启用双写功能。当启用时,数据将同时写入主表和分表中。
  3. ShardingKey
    • 类型:字符串
    • 说明:指定用于分表的列名。例如,对于产品订单表,可以根据 user_id 来分表。
  4. NumberOfShards
    • 类型:无符号整数
    • 说明:指定分表的数量,即分表的个数
  5. tableFormat
    • 类型:字符串
    • 说明:指定分表的表名格式。在不重写ShardingAlgorithm 分表函数时,自动根据分表数量算出

  1. ShardingAlgorithm
    • 类型:函数
    • 说明:指定用于生成分表后缀的算法函数。该函数根据传入的列值,生成对应的分表后缀。
  2. ShardingAlgorithmForUnion
    • 类型:函数
    • 说明:与 ShardingAlgorithm 对应,用于处理全表扫描但无分表字段查询的情况。根据传入的表 ID,直接返回对应的分表后缀。
  3. ShardingSuffixs
    • 类型:函数
    • 说明:生成所有分表后缀的函数,用于支持迁移器和生成主键。在compile插件的时候生成函数--根据函数ShardingAlgorithm拼接后缀
  4. ShardingAlgorithmByPrimaryKey
    • 类型:函数
    • 说明:指定根据主键生成分表后缀的算法函数。当没有指定分表键时使用。
  5. PrimaryKeyGenerator
    • 类型:整数
    • 说明:指定主键生成器算法,可选项有 PKSnowflake、PKPGSequence 和 PKCustom
  6. PrimaryKeyGeneratorFn
    • 类型:函数
    • 说明:指定生成主键的算法函数。当使用自动增量类似的生成器时,可以忽略 tableIdx 参数。PrimaryKeyGenerator为 PKCustom时,直接返回0表示不做处理,让mysql自动递增

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1656853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS学习 -- 任务相关API函数

一、任务创建和删除API函数 FreeRTOS 最基本的功能就是任务管理,而任务管理最基本的操作就是创建和删除任务。 FreeRTOS的任务创建和删除API函数如下: 1、函数 xTaskCreate() 此函数用来创建一个任务,任务需要 RAM 来保存于任务有关的状…

nginx的应用部署nginx

这里写目录标题 nginxnginx的优点什么是集群常见的集群什么是正向代理、反向代理、透明代理常见的代理技术正向代理反向代理透明代理 nginx部署 nginx nginx(发音同enginex)是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3&…

每日一题 第九十七期 洛谷 [NOIP2000 提高组] 方格取数

[NOIP2000 提高组] 方格取数 题目背景 NOIP 2000 提高组 T4 题目描述 设有 N N N \times N NN 的方格图 ( N ≤ 9 ) (N \le 9) (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0 0 0。如下图所示(见样例&#xf…

同步电机原理解析

同步电机 同步带年纪,顾名思义无论负载如何,都能以恒定的速度运转,它以高效率著称 这种恒速特性是通过恒定磁场和旋转磁场的相互作用实现的,与其他电机一样,同步电机由定子和转子组成,定子铁芯由硅片层叠而…

STC8增强型单片机开发 【GPIO的理解⭐⭐】

目录 一、引言 二、GPIO概述 三、GPIO的功能 1. 输入功能: 2. 输出功能 四、GPIO的配置方法 1. 选择GPIO端口和引脚: 2. 设置GPIO模式: 3. 配置GPIO参数: 五、GPIO应用实例 1. 硬件连接: 2. 编程实现&…

2.1初识Spark

Spark于2009年诞生,最初是加州大学伯克利分校的研究项目。2013年加入Apache孵化器项目,2014年成为Apache顶级项目。Spark以内存内运算技术为核心,包含多个计算框架,成为大数据计算领域的后起之秀,打破了Hadoop的基准排…

2.外卖点餐系统(Java项目 springboot)

目录 0.系统的受众说明 1.系统功能设计 2.系统结构设计 3.数据库设计 3.1实体ER图 3.2数据表 4.系统实现 4.1用户功能模块 4.2管理员功能模块 4.3商家功能模块 4.4用户前台功能模块 4.5骑手功能模块 5.相关说明 新鲜运行起来的项目:如需要源码数据库…

如何防止源代码泄露?彻底解决源代码防泄密的方法

SDC沙盒系统:数据安全的守护者 SDC沙盒系统,为研发型企业设计,实现了对数据的代码级保护,同时不影响工作效率和正常使用。系统通过自动加密敏感数据,并配合多种管控机制,有效防止了数据的泄露。 涉密可信…

Python专题:五、条件语句

流程控制语句 count()字符串计数 句尾\分行写码 运行输入cmd 输入Python 回车进入shell python 解释器 shell模式 再给x1,没有结果出来 if条件语句关键词,x>5条件表达式,:条件结束,四个空格&#x…

压缩机继电器EOCRDS-30NY7Q升级后型号:EOCRDS3-30S

EOCR-DS3系列型号: EOCRDS3-05S EOCRDS-05S EOCRDS1-05S EOCRDS3-30S EOCRDS-30S EOCRDS1-30S EOCRDS3-60S EOCRDS-60S EOCRDS1-60S EOCRDS3-05W EOCRDS-05W EOCRDS1-05W EOCRDS3-30W EOCRDS-30W EOCRDS1-30W EOCRDS3-60W EOCRDS-60W EOCRDS1-60W EOCR-DS3T-…

Java:就业市场上的常青树-永远的宠儿

除了兴趣,我们学习编程最主要的目标是找一份好工作,选择合适的编程语言就非常重要了,毕竟选择大于努力,男怕选错行,学编程最怕选错语言。比如,如果你选Perl,那就糟糕了,基本上可以断…

「网络流 24 题」试题库 【最大流】

「网络流 24 题」试题库 思路 建立超级源点 S S S 和超级汇点 T T T,将每一类题目拆分为入点 i n in in 和出点 o u t out out,连边 i n → o u t in \rarr out in→out,边权为 k i k_i ki​,也就是所需的题目数量&#xf…

cannot import name ‘ForkProcess‘ from ‘multiprocessing.context‘问题解决

问题描述 cannot import name ForkProcess from multiprocessing.context 问题原因 ForkContext用于Unix系统。SpawnContext可以在 Windows 环境中使用 解决方案 改成SpawnProcess就可以运行了 将原来的ForkProcess修改为SpawnProcess wrappers.py脚本,下面的代…

Python学习——环境搭建

Python 介绍 Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/)是一种广泛使用的解释型、高级编程、通用型编程语言,由吉多范罗苏姆创造,第一版发布于1991年。可以视之为一种改良(加入…

QGraphicsView实现简易地图12『平移与偏移』

前文链接:QGraphicsView实现简易地图11『指定层级-定位坐标』 提供地图平移与偏移功能。地图平移是指将地图的中心点更改为给定的点,即移动地图到指定位置。地图偏移是指将当前视口内的地图向上/下/左/右/进行微调,这里偏移视口宽/高的四分之…

商务分析方法与工具(六):Python的趣味快捷-字符串巧妙破解密码本、身份证号码、词云图问题

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊! 喜欢我的博客的话,记得…

【Pytorch】1.读取训练数据集

导入Dataset类 from torch.utils.data import Dataset # 注意是Dataset(大写)的才是类通过jupyter我们可以阅读一下Dataset类的具体使用方法 help(Dataset) # 或者直接 Dataset??我们可以看到具体对Dataset类的解释 从蓝色字体我们可以得出 所有的代…

【Vue】Vue packages version mismatch(vue 和 vue-template-compiler)

报错:Vue packages version mismatch 原因:vue和vue-template-compiler版本不一样解决:如上vue版本为 2.6.14,vue-template-comiler版本为2.7.16。将vue-template-comiler版本设置为和vue版本一致即可。 npm install vue-templat…

中国M2总量是两个美国,意味着什么

中国人民银行公布数据:2月末,我国广义货币(M2)余额299.56万亿元,同比增长8.7%。 2000年末我国M2仅13万亿元,2013年3月达到100万亿元;2020年1月突破200万亿元;2024年2月接近300万亿元, 与美欧日…

阵痛中的乳业产业,何时才能成为下一个啤酒产业?

说起饮品,近年来中国啤酒业中各大品牌齐齐聚焦高端化的趋势绝对值得一提。然而,与之相反,国内乳业却是仍未进入高端化阶段,甚至陷入了周期底部中。 图源:中国圣牧财报 增收降利 牧企承受巨大的供需缺口压力 从产业链…