分库分表之后如何通过非分片键操作
发布日期:2021-06-30 16:14:30 浏览次数:2 分类:技术文章

本文共 1886 字,大约阅读时间需要 6 分钟。

1、场景

今天看到一个场景,比如一个表,表名字是award_use_risk,作用是记录奖品使用的记录,用作风控。表结构如下:

这个表,只是分库,没有分表,db分成4个库,分别是db0-db4。

我的第一反应是根据terminal no或者prize guid,具体看业务逻辑进行分表操作,这样增加、修改、删除都可以通过分片算法定位到哪个库。

后来看到业务场景里面,需要定时删除前一天的风控数据,这种情况下,条件里面只有时间,没有分片键,如何定位每个库呢?

梳理一下:

  1. 根据prize guid进行分片路由,比如prize guid%1024/256,结果0-3,正好我们是四个库,没有问题
  2. 如果删除前一天的所有风控记录,怎么办,这个时候没有prize guid,如何分片?delete from award_use_risk where gmt_create 大约昨天,我们要的就是这个sql语句在每个库执行一遍,不能路由,因为路由不确定哪个库执行,哪个库没有执行。

2、思路

为了确定删除的时候在哪个库,我们不能用prize guid,只能用确定的数字0-3去定位每个库执行一遍,这样我们的分片路由键就必须是一个确定范围的数字,0,1,2,3,称之为data id。

在删除的时候,for 循环,以此传入0,1,2,3,就可以轮询删除每个库里面前一天的数据了。

那么插入呢?我们用data id,每个风控记录,都需要生成这个data id,我们就根据prize guid%1024/256,计算出data id,进行分库分表。ok了。

3、共性问题

上面的案例可以通过冗余字段解决,但是对于一些不带分片键的条件查询,并不是通用方案,我们一起看看非分片键过滤,如何解决:

例如按照状态和时间范围来查询订单表 orders,常见的SQL 这样的。

方案一:直接查询

这样好处是代码简单,但是坏处显而易见,在不带分片字段的情况下,中间件不知道数据具体都在哪个分片上,故而会将查询sql以并发的形式发给所有的分片数据库,造成了数据库的性能下降明显,严重影响了核心业务对数据库的需求,而且在某些情况下还会导致内存溢出,虽然可以建立合适的索引提高性能。

方案二:指定数据库节点读取

Mycat可以指定数据库节点,多线程读取每个数据节点,虽然提高了性能,但是效果并不理想。

方案三:异构索引,空间换时间

计算机领域的问题,都可以通过分而治之或者增加一层解决。这个问题,我们为了提高效率,增大空间,比如订单信息表进行分库分表之后,为了查询买家订单,我们需要根据买家id查询,明显不会走分片键,所以在

创建修改订单的时候,另外创建一个表,这个表按照买家id进行分库分表,查询的时候,根据买家id查询到订单id,然后再去订单表找订单信息。流程如下:

åºäºè®¢åç´¢å¼è¡¨æ¥è¯¢ä¹°å®¶è®¢å

这个方案可以,但是不够通用,如果我们根据时间、状态等信息组合查询呢?

 

方案四:实时数仓

我的思路就是监听数据库的变化,有很多中间件可以实现(Canal+Kafka),根据数据库的binlog,

实时创建数据仓库,把数据归集在一起,方便查询,避免分库分表带来的复杂性。

 

4、回顾分库分表的弊端

1.事务支持

​ 分库分表后,就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价; 如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。

2.复杂查询

​ 分库分表后将无法进行join操作,查询禁止不带切分的维度的查询,即使中间件可以支持这种查询,可以在内存中组装,但是这种需求往往不应该在在线库查询,或者可以通过其他方法转换到切分的维度来实现。

解决这个问题的一些方法:

全局表

全局表,也可看做是 "数据字典表",就是系统中所有模块都可能依赖的一些表,为了避免跨库Join查询,可以将 这类表在每个数据库中都保存一份。这些数据通常

很少会进行修改,所以也不担心一致性的问题。

字段冗余

利用空间换时间,为了性能而避免join查询。例:订单表保存userId时候,也将userName冗余保存一份,这样查询订单详情时就不需要再去查询"买家user表"了。

数据组装

在系统层面,分两次查询。第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。

 

备注:

1.目前营销中心分库分表后的id,并没有用雪花算法,而是一个数据库的sequence表记录了id的next value,从而做到全局不重复。配置如下:

2. 营销中心的非分片键查询?

 

 

 

 

转载地址:https://kerry.blog.csdn.net/article/details/113859723 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JDK 8 的optional类
下一篇:Mybatis 中的$和#

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年05月01日 00时08分56秒