Sharding-JDBC踩坑记

本文最后更新于2019年12月27日,可能由于时间等因素导致内容失效,请自行辨别或联系作者。

一、前言

随着外呼项目的不断迭代,外呼的记录和日志数据不断攀升,高峰时期,这两张表每天会有60W条记录,为了避免单表存放数据所带来的弊端,准备将记录表和日志表按照月份自动进行分表存储和相关查询。我第一个想法就是,设置个定时任务,自动把主表的记录转移到按月划分的分表上,但是这样又会有个问题,这些数据还需要查询啊,如果在主表找不到应该怎么处理?再依次查找所有的分表吗?那对于范围查询又应该怎么处理?

按照自己的逻辑,似乎很难行得通,而且很可能需要大量修改已有的逻辑,非常麻烦。于是,在师傅的推荐下,开始了解Sharding-JDBC。稍微看了一下,分库分表,不错,于是就采取了这套方案。只是当时的我不知道的是,给自己挖了好几个巨大的坑……

写这篇文章,除了为了记录之外,还想分享一下我的学习方法以及解决问题的思路,分享出来,一起讨论,一起进步。

二、Sharding-JDBC是什么

Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动、数据库中间层,完全兼容JDBC和各种ORM框架。

三、Sharding-JDBC有什么用

  • 数据分片
  • 读写分离
  • 数据脱敏

本文主要使用到的是数据分片。简单概括一下场景:现有一条数据需要插入,通过Sharding-JDBC配置,可以自动按月份插入到对应的表中,实现数据的分片,将数据按照月份进行划分。

四、采坑记录

一开始看了一下官网,官网对于数据分片,只提供了一个分库分表,两库两表的例子,我是需要动态分表啊,照着官网的例子来肯定行不通,于是开始搜其他的教程。

找了一圈下来,绝大部分都是对官网提供的例子的应用,而且需要大量的配置。最终,找到了一篇“从零开始利用JPA与SHARDING-JDBC动态划分月表”的文章,虽然是用JPA,但一点也不妨碍我学习白嫖啊。

于是,新建工程,先把文章里面的效果实现再说,因为我所在的项目组,已经迭代了好几个版本了,我也没有这个胆量直接边学习边集成进去,这怎么说也算是升级底层架构了啊。照着教程下来,其实没什么难度的,思路也比较清晰,也跟着教程,把源码给改了,所以在反编译这里卡了一会儿。

大概过了两天,我基本了解了这个玩意儿,例子也实现了,做好了基本的调研,去找师傅确定最终的方案。跟师傅简单说了一下,当他得知我修改了源码之后,立马指出不需要这么麻烦,并且拿出了他之前在项目中使用的代码给我看。其实之前的代码我是瞄过一眼的,我觉得太复杂了,他是用纯JAVA的方式进行配置,不利于人员的维护和修改,而且,所有的表,都已经是固定、配置好的,无法满足本次的按月自动划分的需求。

最终,师傅同意了整体的实施方案,但是不需要改源码。教程中之所以需要修改源码是因为,查询时必须带上分片键,这样才能通过策略找到对应的逻辑表,若想不带,作者就修改了源码。我现在主要该解决这个问题。

好在,办法还是有的,最后找到了“Sharding-Jdbc 自定义分库分表-复合分片算法自定义实现”一文,自定义了复合分片策略,参考了部分,最终实现了。其实现在回想起来,用最开始看到的教程实现也是可以的,用自定义复合分片策略的好处就是,将所有的分片算法写在了一个类中,代码看起来是多了不少。

其实,看到这,或许会觉得没什么大坑,那你就错了,Sharding-JDBC的坑,对于我这种刚接触的小白来说,压根就想不到,其中,我因为一个坑,足足想了2天,才找出问题的原因….你看我开发的记录,应该就知道我有多煎熬了….

先贴一下最终的代码,然后再一一吐槽其中的坑!这次就直接截图了,若对你有帮助的话,还是希望自己手敲一下,对于一些坑,印象会更深刻一点(让你们也体会一下痛苦)。

Maven依赖

Yml配置

自定义复合分片策略

好了,铺垫了这么多,坑来了~~

第一个坑:Sharding-JDBC的策略中无法通过注解的方式获取Yml文件中的配置。

在自定义的策略中拿取配置文件中的配置,主要是为了实现统一配置和管理,我需要获取分片键,找了很久,终于找到了无需注入获取配置的方法(实际上在自定义策略中也无法注入),见下图。

第二个坑

出现情景:在Springboot+Mybatis环境下,使用xml编写sql插入数据库。该表已配置好相关的分片策略,数据库中主键为id,int类型,自增。在测试插入时,如下图所示报错。

原因:

  1. ShardingJdbc无法解析在sql语句中调用的函数:NOW() (若通过注解的方式实现mybatis,则能够解析sql语句中的函数)
  2. 若在配置时,指定了自增的主键名称,则ShardingJdbc会通过自己的主键生成策略来生成主键,类型为Long,所以数据库对应的类型应该改为bigint。

解决方法:

  1. 不使用NOW(),传入当前时间
  2. 见下图,有两种解决方法

第三个坑:有些情况下,不会进入自定义策略。

  • 若where 后面的条件 始终没有 列名 = 期望值 则不会进入策略
  • 见下图

第四个坑:若数据库字段有text类型,在对该字段进行操作的时候,可能会报错(具体忘了…)

五、主要参考

官网:https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/

从零开始利用JPA与SHARDING-JDBC动态划分月表:https://juejin.im/post/5d9fe175f265da5bba417a28

Sharding-Jdbc 自定义分库分表-复合分片算法自定义实现:https://www.cnblogs.com/rinack/p/11241111.html

六、总结

前面的三个坑其实还不算啥,至少是开发阶段的,第四个坑,就真的是坑了!因为本次我的开发任务,是在项目的架构上进行升级,所以需要足够了解这个项目所涉及到分表的操作,需要一个个去测试,你们懂的,毕竟当时我入职连一个月都没有,没有培训,各种经验,绝大部分都是通过自己不断出错积累的,所以,这个版本迭代完成,上线之后,出问题了….

可能你们会有疑问,难道没有测试岗吗?直接就上线?有测试岗,但是我师傅带领的这个组的这个项目,免测….所以没有发现问题,直到出了第四个坑所造成的错误,师傅给整个项目组的人发邮件,说以后上线需要提测….现在你们懂了吧,为什么我说第四个坑具体忘了….因为当时慌的一批!当天一个同组的前辈,帮我补锅,补了一天….(我当时调去其他组的项目了)

我当时,真的吓傻了。师傅坐在我斜对面的工位,我不敢面露表情,眼睛不敢看他….我觉得都没脸面对大家了。后来,师傅什么也没说,也没有找我,这让我更加自责了。再后来,前辈告诉我,以后可以先丢到测试环境,跑几天再说。真的,当时除了慌,连写代码的自信都没有了……

所以,到现在,一直在总结,自己写完代码之后,应该怎么自检,如果碰到临时接入的项目,又应该怎么办,因为涉及到其他的逻辑可能非常多,短时间内又很难了解全面。

为TA充电
共{{data.count}}人
人已赞赏
Java编程语言

Log4j2抽丝剥茧之入门及进阶

2019-12-26 20:49:43

Java编程语言

【Java学习笔记(一)】数据类型、变量与常量、数组以及注释

2020-2-9 22:56:48

2 条回复 A文章作者 M管理员
  1. mouxiaohao

    操作有点高深

  2. clingingx

    大佬 看不懂操作

个人中心
今日签到
有新私信 私信列表
搜索