gorm-sharding分表插件升级版

代码地址: 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自动递增

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探秘主播们的直播美颜SDK:深度学习算法原理

直播美颜技术作为直播行业中的一项重要技术,广受大家关注。本文将深入探讨主播们常用的直播美颜SDK背后的深度学习算法原理,揭秘其神奇之处。 一、什么是直播美颜SDK? 直播美颜SDK是一种应用程序接口,通过嵌入到直播软件中&…

根据数据写动态生成折线图

根据数据格式 dataGoz: [{"xAxis": ["2017-3-1", "2017-3-15", "2017-4-1", "2017-4-12", "2017-5-21", "2017-6-5", "2017-8-12", "2017-9-1", "2017-10-11"],"y…

C++函数模板可变参数如何一次性解包?

零、问题 如下代码中,调用func1的时候,只能递归一次取到一个值,有没有什么方法像func2中那样,一次把所有的值都拿出来呢? ​ 回答 二元操作 (binary operator) 」 :需要两个操作数的操作,比如…

【全开源】JAVA国际版多语言语聊大厅语音聊天APP系统源码

JAVA国际版多语言语聊大厅小程序 随着全球化的加速和互联网技术的飞速发展,人们越来越需要一种能够跨越语言和文化障碍的交流方式。JAVA国际版多语言语聊大厅小程序应运而生,它以其独特的功能和全球化的设计理念,为全球用户提供了一个无障碍…

5.12母亲节营销攻略:TikTok助力出海品牌赢得用户心

母亲节,作为一个全球性的节日,不仅是表达对母亲的感激之情的时刻,也是品牌们展示创意、赢得用户心的黄金机会。2024母亲节将至,如何利用TikTok在母亲节这一特殊时刻进行营销,赢得用户的心,成为出海品牌必须…

私域流量优化:如何利用 AIPL 模型洞察客户生命周期价值

在当今这个数字化时代,商业战场的硝烟从未如此浓烈。随着互联网红利的逐渐消退,公域流量的成本水涨船高,企业间对于有限用户资源的争夺已进入白热化阶段。每一次点击、每一个曝光背后,都是企业不得不承担的高昂代价。在此背景下&a…

【Web】CTFSHOW月饼杯 题解(全)

目录 web1_此夜圆 web2_故人心 web3_莫负婵娟 web1_此夜圆 拿到源码&#xff0c;一眼字符串逃逸 本地测一测&#xff0c;成功弹出计算器 <?phpclass a {public $uname;public $password;public function __wakeup(){system(calc);} }function filter($string){retur…

报名 | AIGC技术分享峰会苏州场来啦!

IGC是近年来人工智能技术迅速发展的一个重要领域。从早期的简单字符生成到现在可以撰写复杂文章、生成高清图片甚至编写代码&#xff0c;AIGC技术的发展突飞猛进&#xff0c;不仅在文学创作、艺术设计、游戏开发和软件编程等领域展现出惊人的潜能&#xff0c;也对各行业提供了前…

项目管理在软件工程中的实践方法

软件工程是一个复杂的过程&#xff0c;涉及到需求分析、设计、编码、测试和维护等多个阶段。有效的项目管理对于确保软件项目成功至关重要。以下是结合附件内容&#xff0c;关于项目管理在软件工程中实践的一些方法。 1. 明确项目愿景和目标 在项目启动之初&#xff0c;项目经…

SpringBoot+logback实现日志记录写入文件

前言 在实际的开发过程中&#xff0c;日志记录有着极其重要的作用&#xff0c;它帮助我们实现更高效的故障排查与调试、更及时的监控和性能优化、更全面的业务分析与决策支持…那么我们如何在SpringBoot项目中实现日志的个性化定制&#xff0c;以满足其他特殊需求呢&#xff1f…

2024年5月6日优雅草蜻蜓API大数据服务中心v2.0.3更新

v2.0.3更新 2024年5月6日优雅草蜻蜓API大数据服务中心v2.0.3更新-修复改版后搜索框漏掉的bug-增加搜索框 提示&#xff1a;优雅草大数据中心已经 上线137天 稳定运行 1181555 次 累积调用 目前大数据中心用户呈现增长趋势&#xff0c;目标2024年11月底突破1亿次调用&#xf…

大语言模型的后处理

后处理的输入 常规意义上的大模型处理流程 import torch from transformers import LlamaForCausalLM, LlamaTokenizer# 加载模型和tokenizer model LlamaForCausalLM.from_pretrained("decapoda-research/llama-7b-hf") tokenizer LlamaTokenizer.from_pretrain…

这个 TypeScript 技巧会让你大吃一惊

从字符串数组中提取自定义类型 “在 TypeScript 的世界里&#xff0c;自定义类型从字符串数组中显现&#xff0c;就像隐藏的宝石。” TypeScript 是一个操纵现有数据和发展良好实践的神奇工具。 今天&#xff0c;我们将探索如何以正确的方式从字符串数组中提取全名&#xff0c…

MPAndroidChart 详细使用 - BarChart

chart下面的方法 getDescription().setEnabled(boolean enabled);//设置描述是否显示 setPinchZoom(boolean enabled);//设置x轴和y轴能否同时缩放。默认是否 setScaleEnabled(boolean enabled);//是否支持缩放 setScaleXEnabled(boolean enabled);//启用/禁用x轴上的缩放 setS…

Vue2中子组件调用父组件的方法,父组件调用子组件的方法,父子组件互相传值和方法调用

&#x1f49f; 上一篇文章 组件之间的多种通信方式&#xff0c;一文彻底搞懂组件通信&#xff01;​​​​​​​ &#x1f4dd; 系列专栏 vue从基础到起飞 目录 一、父组件调用子组件的方法 二、子组件调用父组件的方法 1、使用this.$emit()向父组件触发一个事件,父组件监听…

HTTPS 原理和 TLS 握手机制

HTTPS的概述与重要性 在当今数字化时代&#xff0c;网络安全问题日益凸显&#xff0c;数据在传输过程中的安全性备受关注。HTTPS 作为一种重要的网络通信协议&#xff0c;为数据的传输提供了强有力的安全保障。它是在 HTTP 的基础上发展而来&#xff0c;通过引入数据加密机制&a…

RazorSQL for Mac:强大而全面的数据库管理工具

RazorSQL for Mac是一款功能强大、操作简便的数据库管理工具。它专为Mac用户设计&#xff0c;支持连接超过30种不同类型的数据库&#xff0c;包括MySQL、Oracle、PostgreSQL等&#xff0c;为用户提供了全面的数据库管理解决方案。 RazorSQL具有强大的数据库浏览功能&#xff0c…

【吃透Java手写】3-SpringBoot-简易版-源码解析

【吃透Java手写】SpringBoot-简易版-源码解析 1 SpringbootDemo2 准备工作2.1 Springboot-my2.1.1 依赖2.1.2 SpringBootApplication2.1.3 SJBSpringApplication2.1.3.1 run方法 2.2 Springboot-user2.2.1 依赖2.2.2 UserController2.2.3 UserApplication 2.3 分析run方法的逻辑…

图神经网络(GNNs)在时间序列分析中的应用

时间序列数据是记录动态系统测量的主要数据类型&#xff0c;由物理传感器和在线过程&#xff08;虚拟传感器&#xff09;大量生成。时间序列分析对于解锁可用数据中隐含的丰富信息至关重要。随着图神经网络&#xff08;GNNs&#xff09;的最近进展&#xff0c;基于GNN的方法在时…

5月10日学习记录

[NCTF2019]True XML cookbook(xxe漏洞利用) 这题是关于xxe漏洞的实际应用&#xff0c;利用xxe漏洞的外部实体来进行ssrf探针内网的主机 和[NCTF2019]Fake XML cookbook的区别就在于xxe漏洞的利用方向&#xff0c;一个是命令执行&#xff0c;一个是SSRF 看题&#xff0c;打开…