服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - 详解数据库分片,大幅提升Spring Boot查询MySQL性能

详解数据库分片,大幅提升Spring Boot查询MySQL性能

2024-01-08 15:56Java学研大本营 Mysql

我们既使用了表分片又使用了数据库分片。除此以外,我们可以进一步提高性能,方法是在单个服务器中增加更多的数据库,可能总共有1000个表的副本。

背景

微服务项目中通常包含各种服务。其中一项服务与存储用户相关的数据有关。我们使用Spring Boot作为后端,使用MySQL数据库。

目标

随着用户基数的增长,服务性能受到了影响,延迟也上升了。由于只有一个数据库和一张表,许多查询和更新由于锁异常返回错误。此外,随着数据库的规模不断扩大,性能进一步下降。因此,需要一种解决方案来处理不断增长的用户基数。

解决方案

表格分片

详解数据库分片,大幅提升Spring Boot查询MySQL性能图片

第一种方法是在单个数据库中创建多个类似的表,并使用user_id作为分片键。

我们在user_id列出现的任何地方创建了每个表的10个副本。因此,代码中需要进行两个更改。第一个更改是获取用户请求中的user_id。第二个更改是替换由Hibernate生成的查询中的表名。

关于第一个更改,获取user_id很容易,因为我们已经在请求标头中获取了user_id。

对于第二个更改,我们扩展了Hibernate的EmptyInterceptor类,并覆盖了onPrepareStatement方法,该方法在准备SQL字符串时调用。该方法有一个字符串参数,即SQL语句。该SQL语句中也包含表名。因此,这里根据请求头中存在的user_id用所需的表名替换表名。例如,如果user_id为77。我们取它10的模得到7,并将表名user_profile替换为user_profile_7,因为我们已经在数据库中创建了10个副本。以下是扩展EmptyInterceptor类的代码。如果您使用的是spring boot 3,则EmptyInterceptor已经弃用,你可以使用StatementInspector接口,并覆盖inspect方法,并将逻辑从onPrepareStatement方法移动到inspect方法中。

public class DynamicTableNameSharding extends EmptyInterceptor {
    @Override
    public String onPrepareStatement(String sql) {
        // 替换表名
        if (Boolean.parseBoolean(DatabaseEnvironment.TABLE_SHARDING_ENABLED.label)) {
            for (String tableName : SHARDED_TABLES) {
                if(sql.contains(tableName)) {
                    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                    String shardingNumber = getSharding(attr);
                    sql = sql.replace(tableName, tableName + shardingNumber);
                    // 这里不要使用break,因为一条查询可以包含多个表,因此需要更改所有已启用分片的表的名称
                }
            }
        }
        return super.onPrepareStatement(sql);
    }
}

在上述函数中,SHARDED_TABLES是已启用分片的表的列表。getSharding方法根据请求头中传递的用户ID返回分片号。由于在单个查询中存在多个表(例如连接或复杂逻辑),因此我们使用for循环来正确替换查询中出现的所有表。

我们还通过扩展DefaultVisitListener类,在某些操作中使用了JOOQ。

数据库分片

详解数据库分片,大幅提升Spring Boot查询MySQL性能图片

虽然通过表格分片提升了一定性能,但还有进一步改进的空间,我们进一步对数据库进行分片。与创建表副本类似,我们创建10个数据库服务器/实例的副本,每个服务器都有10个表的副本。总共有100个表副本。

因此,同时保持10个数据库服务器运行也需要路由查询到正确的数据库。

首先,在的Spring Boot应用程序中创建了10个数据源,每个数据源都有不同的数据库URL。现在,我们需要一种方法将数据库连接路由到正确的数据源。因此,我们使用了AbstractRoutingDataSource,它是一个路由getConnection()调用到其中一个多个目标数据源的抽象DataSource实现,这个目标数据源基于一个查找键。然后,我们重写了这个方法determineCurrentLookupKey。

因此,这个方法返回一个键,用于标识我们已定义的10个数据源中的一个特定数据源。因此,我们也更改了一些用于确定表和数据库的逻辑。我们使用个位数字标识数据库服务器,使用十位数来标识表。例如,用户ID为447将被路由到第7个数据库服务器及该服务器上的第4个表副本。因此,我们在10个数据库服务器上有100个表,这大大提高了性能。

结论

在这个例子中,我们既使用了表分片又使用了数据库分片。除此以外,我们可以进一步提高性能,方法是在单个服务器中增加更多的数据库,可能总共有1000个表的副本。


原文地址:https://mp.weixin.qq.com/s/AgEDAxx9bkjM3X38Ve6M_Q

延伸 · 阅读

精彩推荐
  • MysqlMySQL乐观锁和悲观锁具体实现

    MySQL乐观锁和悲观锁具体实现

    这篇文章主要介绍了MySQL乐观锁和悲观锁具体实现,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的小伙伴可以参考一下...

    7small79092022-09-07
  • MysqlMySQL全文索引应用简明教程

    MySQL全文索引应用简明教程

    这篇文章主要介绍了MySQL全文索引应用简明教程,需要的朋友可以参考下...

    MYSQL教程网3752020-06-29
  • MysqlWindows下mysql5.7.21安装详细教程

    Windows下mysql5.7.21安装详细教程

    这篇文章主要为大家详细介绍了Windows下mysql5.7.21安装详细教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    江木5002020-08-25
  • Mysqlmysql乱码问题分析与解决方法

    mysql乱码问题分析与解决方法

    开发过程中总避免不了遇到恶心的乱码,或者由乱码引发的一系列问题,这里简要介绍一下自己遇到的乱码问题和解决问题的过程中的想法以及大致的操作...

    MYSQL技术网4542019-12-13
  • Mysql浅谈sql语句中GROUP BY 和 HAVING的使用方法

    浅谈sql语句中GROUP BY 和 HAVING的使用方法

    GROUP BY语句和HAVING语句,经过研究和练习,终于明白如何使用了,在此记录一下同时添加了一个自己举的小例子,通过写这篇文章来加深下自己学习的效果...

    云浩舟5912020-09-27
  • Mysqlmysql 8.0.12 解压版安装教程

    mysql 8.0.12 解压版安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.12 解压版安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    小鲁班跑慢点2012020-09-04
  • MysqlMySql日期查询语句详解

    MySql日期查询语句详解

    在mysql中对时间日期操作的函数有很多,有时我们就希望直接通过sql查询出指定日期的数据 ...

    MYSQL教程网6072020-01-13
  • Mysql在 Docker 中部署 Mysql 并挂载配置文件

    在 Docker 中部署 Mysql 并挂载配置文件

    在 Docker 中部署 MySQL 并挂载配置文件,可以使用以下步骤:首先,在主机上创建一个目录,用于存放 MySQL 的配置文件。例如,创建一个名为 mysql 的目录,...

    程序员朱永胜4402023-10-12