面试官:单表数据量大一定要分库分表吗?我用6个字和10张图回答

本文介绍了互联网场景中的读写分离策略,包括使用多读库、MySQLbinlog同步,以及ShardingSphere组件的路由管理。随后探讨了垂直和水平数据拆分技术,重点讲解了范围分片、查表分片和哈希分片。此外,文章还讨论了数据异构和canal在数据同步中的作用,以及如何处理热点数据以确保系统的稳定和性能。
摘要由CSDN通过智能技术生成

四、 分


我们首先看一个概念:读写比。互联网场景中一般是读多写少,例如浏览20次订单列表信息才会进行1次确认收货,此时读写比例就是20:1。面对读多写少这种情况我们可以做什么呢?

我们可以部署多台MySQL读库专门用来接收读请求,主库接收写请求并通过binlog实时同步的方式将数据同步至读库。MySQL官方即提供这种能力,进行简单配置即可。

在这里插入图片描述

那么客户端怎么知道访问读库还是写库呢?推荐使用ShardingSphere组件,通过配置将读写请求分别路由至读库或者写库。

五、拆


如果删除了历史数据并采用了其它存储介质,也用了读写分离,但是单表压力还是太大怎么办?这时我们只能拆分数据表,即把单库单表数据迁移到多库多张表中。

假设有一个电商数据库存放订单、商品、支付三张业务表。随着业务量越来越大,这三张业务数据表也越来越大,我们就以这个例子进行分析。

5.1 垂直拆分

垂直拆分就是按照业务拆分,我们将电商数据库拆分成三个库,订单库、商品库。支付库,订单表在订单库,商品表在商品库,支付表在支付库。这样每个库只需要存储本业务数据,物理隔离不会互相影响。在这里插入图片描述

5.2 水平拆分

按照垂直拆分方案,现在我们已经有三个库了,平稳运行了一段时间。但是随着业务增长,每个单库单表的数据量也越来越大,逐渐到达瓶颈。

这时我们就要对数据表进行水平拆分,所谓水平拆分就是根据某种规则将单库单表数据分散到多库多表,从而减小单库单表的压力。

水平拆分策略有很多方案,最重要的一点是选好ShardingKey,也就是按照哪一列进行拆分,怎么分取决于我们访问数据的方式。

5.2.1 范围分片

现在我们要对订单库进行水平拆分,我们选择的ShardingKey是订单创建时间,拆分策略如下:

(1) 拆分为四个数据库,分别存储每个季度的数据

(2) 每个库三张表,分别存储每个月的数据

上述方法优点是对范围查询比较友好,例如我们需要统计第一季度的相关数据,查询条件直接输入时间范围即可。

在这里插入图片描述

但是这个方案问题是容易产生热点数据。例如双11当天下单量特别大,就会导致11月这张表数据量特别大从而造成访问压力。

5.2.2 查表分片

查表法是根据一张路由表决定ShardingKey路由到哪一张表,每次路由时首先到路由表里查到分片信息,再到这个分片去取数据。

我们分析一个查表法实际案例。Redis官方在3.0版本之后提供了集群方案Redis Cluster,其中引入了哈希槽(slot)这个概念。

一个集群固定有16384个槽,在集群初始化时这些槽会平均分配到Redis集群节点上。每个key请求最终落到哪个槽计算公式是固定的:

SLOT = CRC16(key) mod 16384

那么问题来了:一个key请求过来怎么知道去哪台Redis节点获取数据?这就要用到查表法思想。

(1) 客户端连接任意一台Redis节点,假设随机访问到为节点A

(2) 节点A根据key计算出slot值

(3) 每个节点都维护着slot和节点映射关系表

(4) 如果节点A查表发现该slot在本节点则直接返回数据给客户端

(5) 如果节点A查表发现该slot不在本节点则返回给客户端一个重定向命令,告诉客户端应该去哪个节点上请求这个key的数据

(6) 客户端再向正确节点发起连接请求

查表法优点是可以灵活制定路由策略,如果我们发现有的分片已经成为热点则修改路由策略。缺点是多一次查询路由表操作增加耗时,而且路由表如果是单点也可能会有单点问题。

5.2.3 哈希分片

现在比较流行的分片方法是哈希分片,相较于范围分片,哈希分片可以较为均匀将数据分散在数据库中。

我们现在将订单库拆分为4个库编号为[0,3],每个库4张表编号为[0,3],如下图如所示:

在这里插入图片描述

现在使用orderId作为ShardingKey,那么orderId=100的订单会保存在哪张表?我们来计算一下:由于是分库分表,首先确定路由到哪一个库,取模计算得到序号为0表示路由到db[0]

db_index = 100 % 4 = 0

库确定了接着在db[0]进行取模表路由

table_index = 100 % 4 = 0

最终这条数据应该路由至下表

db[0]_table[0]

最终计算结果如下图所示:

在这里插入图片描述

在实际开发中最终路由到哪张表,并不需要我们自己算,因为有许多开源框架就可以完成路由功能,例如ShardingSphere、TDDL等等。

六、异


现在数据已经使用哈希分片方法完成了水平拆分,我们选择的ShardingKey是orderId。这时客户端需要查询orderId=111的数据,查询语句很简单如下:

SELECT * FROM order WHERE orderId = 111

这个语句没有问题,因为查询条件包含orderId,可以路由到具体的数据表。

现在如果业务想要查询用户维度的数据,希望查询userId=222的数据,现在问题来了:以下这个语句可以查出数据吗?

SELECT * FROM order WHERE userId = 222

答案是可以,但是需要扫描所有库的所有表,因为无法根据userId路由到具体某一张表,这样时间成本会非常高,这种场景怎么办呢?

这就要用到数据异构的思想。数据异构核心是用空间换时间,简单一句话就是一份数据按照不同业务需求保存多份,这样做是因为存储硬件成本不是很高,而互联网场景对响应速度要求很高。

对于上述需要使用userId进行查询的场景,我们完全可以新建库和表,数量和结构与订单库表完全一致,唯一不同点是ShardingKey改用userId,这样就可以使用userId查询了。

现在又引出一个新问题,业务不可能每次都将数据写入多个数据源,这样会带来性能问题和数据一致行为。怎么解决老库和新库数据同步问题?我们可以使用阿里开源的canal组件解决这个问题,看一张官网介绍canal架构图:在这里插入图片描述

canal组件的主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费服务,工作原理如下:

(1) canal伪装成为MySQL slave模拟交互协议向master发送dump协议

(2) master收到canal发送的dump请求,开始推送binlog给canal

(3) canal解析binlog并发送到存储目的地,例如MySQL、Kafka、Elasticsearch

canal组件下游可以对接很多其它数据源,这样给业务提供了更多选择。我们可以像上述实例中新建用户维度订单表,也可以将数据存在ES中提供运营检索能力等等。

七、热


我们来分析这样一个场景:社交业务有一张用户关系表,主要记录谁关注了谁。其中有一个明星粉丝特别多,如果以userId作为分片,那么其所在分片数据量就会特别大。

不仅分片数据量特别大,而且可以预见这个分片访问频率也会非常高。此时数据量大并且访问频繁,很有可能造成系统压力。

7.1 热点概念

我们将访问行为称为热点行为,将访问对应的数据称为热点数据。我们通过实例来分析。

在电商双11活动中百分之八十的访问量会集中在百分之二十的商品上。用户刷新、添加购物车、下单被称为热点行为,相应商品数据就被称为热点数据。

在微博场景中大V发布一条消息会获得大量访问。用户对这条消息的浏览、点赞、转发、评论被称为热点行为,这条消息数据被称为热点数据。

在秒杀场景中参与秒杀的商品会获得极大的瞬时访问量。用户对这个商品的频繁刷新、点击、下单被称为热点行为,参与秒杀的商品数据被称为热点数据。

我们必须将热点数据进行一些处理,使得热点访问更加流畅,更是为了保护系统免于崩溃。我们从发现热点数据、处理热点数据来展开分析。

7.2 发现热点数据

我们把发现热点数据分为两种方式:静态发现和动态发现。

静态发现:在开始秒杀活动之前,参与商家一定知道哪些商品参与秒杀,那么他们可以提前将这些商品报备告知平台。

在微博场景中,具有影响力的大V一般都很知名,网站运营同学可以提前知道。技术同学还可以通过分析历史数据找出TOP N数据。对于这些可以提前预判的数据,完全可以通过后台系统上报,这样系统可以提前做出预处理。

动态发现:有些商品可能并没有上报为热点商品,但是在实际销售中却非常抢手。在微博场景中,有些话题热度突然升温。这些数据成为事实上的热点数据。对于这些无法提前预判的数据,需要动态进行判断。

我们需要一个热点发现系统去主动发现热点数据。大体思路是首先异步收集访问日志,再统计单位时间内访问频次,当超过一定阈值时可以判断为热点数据。

7.3 处理热点问题

(1) 热点行为

热点行为可以采取高频检测方式,如果发现频率过高则进行限制。或者采用内存队列实现的生产者与消费者这种异步化方式,消费者根据能力处理请求。

(2) 热点数据

处理热点数据核心主要是根据业务形态来进行处理,我一般采用以下方案配合执行:

(1) 选择合适ShardingKey进行分库分表

(2) 异构数据至其它适合检索的数据源例如ES

(3) 在MySQL之前设置缓存层

(4) 尽量不在MySQL进行耗时操作(例如聚合)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

算法刷题(PDF)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
理成了PDF或者Word文档(含详细答案解析)**

[外链图片转存中…(img-t9SVJPpU-1712531074351)]

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

[外链图片转存中…(img-5f0vfQmd-1712531074351)]

算法刷题(PDF)

[外链图片转存中…(img-GxzTCdX3-1712531074352)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值