| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 分库分表常见问题和解决方案 -> 正文阅读 |
|
[大数据]分库分表常见问题和解决方案 |
MySQL出现的性能问题
Mysql常见的优化手段
大数据表优化方案对于大数据表的优化最直观的方式就是减少单表数据量,所以常见的解决方案是:
详解分库分表分库分表是非常常见针对单个数据表数据量过大的优化方式,它的核心思想是把一个大的数据表拆分成多个小的数据表,这个过程也叫(数据分片),它的本质其实有点类似于传统数据库中的分区表,比如mysql和oracle都支持分区表机制。 分库分表是一种水平扩展手段,每个分片上包含原来总的数据集的一个子集。这种分而治之的思想在技术中很常见,比如多CPU、分布式架构、分布式缓存等等,像前面我们讲redis cluster集群时,slot槽的分配就是一种数据分片的思想。 如图6-1所示,数据库分库分表一般有两种实现方式: 垂直拆分垂直拆分有两种,一种是单库的垂直拆分,另一种是多个数据库的垂直拆分。 单库垂直分表单个表的字段数量建议控制在20~50个之间,之所以建议做这个限制,是因为如果字段加上数据累计的长度超过一个阈值后,数据就不是存储在一个页上,就会产生分页的问题,而这个问题会导致查询性能下降。 所以如果当某些业务表的字段过多时,我们一般会拆去垂直拆分的方式,把一个表的字段拆分成多个表,如图6-2所示,把一个订单表垂直拆分成一个订单主表和一个订单明细表。 多库垂直分表多库垂直拆分实际上就是把存在于一个库中的多个表,按照一定的纬度拆分到多个库中,如图6-3所示。这种拆分方式在微服务架构中也是很常见,基本上会按照业务纬度拆分数据库,同样该纬度也会影响到微服务的拆分,基本上服务和数据库是独立的。 水平拆分垂直拆分的方式并没有解决单表数据量过大的问题,所以我们还需要通过水平拆分的方式把大表数据做数据分片。 水平切分也可以分成两种,一种是单库的,一种是多库的。 单库水平分表如图6-4所示,表示把一张有10000条数据的用户表,按照某种规则拆分成了4张表,每张表的数据量是2500条。 当天表:只存储当天的数据。 当月表:我们在夜间运行一个定时任务,前一天的数据,全部迁移到当月表。用的是insert intoselect,然后delete。 历史表:同样是通过定时任务,把登记时间超过30天的数据,迁移到history历史表(历史表的数据非常大,我们按照月度,每个月建立分区)。 费用表: 消费金融公司跟线下商户合作,给客户办理了贷款以后,消费金融公司要给商户返费用,或者叫提成,每天都会产生很多的费用的数据。为了方便管理,我们每个月建立一张费用表,例如fee_detail_201901…fee_detail_201912。 但是注意,跟分区一样,这种方式虽然可以一定程度解决单表查询性能的问题,但是并不能解决单机存储瓶颈的问题。 多库水平分表多库水平分表,其实有点类似于分库分表的综合实现方案,从分表来说是减少了单表的数据量,从分库层面来说,降低了单个数据库访问的性能瓶颈,如图6-5所示。 常见的水平分表策略哈希取模分片哈希分片,其实就是通过表中的某一个字段进行hash算法得到一个哈希值,然后通过取模运算确定数据应该放在哪个分片中,如图6-6所示。这种方式非常适合随机读写的场景中,它能够很好的将一个大表的数据随机分散到多个小表。 hash取模的问题hash取模运算有个比较严重的问题,假设根据当前数据表的量以及增长情况,我们把一个大表拆分成了4个小表,看起来满足目前的需求,但是经过一段时间的运行后,发现四个表不够,需要再增加4个表来存储,这种情况下,就需要对原来的数据进行整体迁移,这个过程非常麻烦。 一般为了减少这种方式带来的数据迁移的影响,我们会采用一致性hash算法。 一致性hash算法按照范围分片按范围分片,其实就是基于数据表的业务特性,按照某种范围拆分,这个范围的有很多含义,比如:
如图6-7所示,表示按照数据范围进行拆分。 分库分表实战假设存在一个用户表,用户表的字段如下。 用户端: 前台访问量较大,主要涉及两类请求:
运营端: 主要是运营后台的信息访问,需要支持根据性别、手机号、注册时间、用户昵称等进行分页查询,由于是内部系统,访问量较低,对可用性一致性要求不高。 根据uid进行水平分表由于99%的请求是基于uid进行用户信息查询,所以毫无疑问我们选择使用uid进行水平分表。那么这里我们采用uid的hash取模方法来进行分表,具体的实施如图6-9所示,根据uid进行一致性hash取模运算得到目标表进行存储。
如何实现全局唯一ID
分布式ID的特性
数据库自增方案在数据库中专门创建一张序列表,利用数据库表中的自增ID来为其他业务的数据生成一个全局ID,那么每次要用ID的时候,直接从这个表中获取即可。
在应用程序中,每次调用下面这段代码,就可以持续获得一个递增的ID。
其中,replace into是每次删除原来相同的数据,同时加1条,就能保证我们每次得到的就是一个自增的ID。
优点:
缺点:
UUIDUUID的格式是: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 8-4-4-4-12共36个字符,它是一个128bit的二进制转化为16进制的32个字符,然后用4个 - 连接起来的字符串。 UUID的五种生成方式:
在Java中,提供了基于MD5算法的UUID、以及基于随机数的UUID。
缺点:
雪花算法SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。雪花算法比较常见,在百度的UidGenerator、美团的Leaf中,都有用到雪花算法的实现。 如图6-11所示,表示雪花算法的组成,一共64bit,这64个bit位由四个部分组成。
那么我们为什么需要这个序列号,设想下,如果是同一毫秒同一台机器来请求,那么我们怎么保证他的唯一性,这个时候,我们就能用到我们的序列号, 目的是为了保证同一毫秒内同一机器生成的ID是唯一的,这个其实就是为了满足我们ID的这个高 12位(bit)可以表示的最大正整数是2^12-1=4095,即可以用0、1、2、3、…4094这4095个数字,来表示同一机器同一时间截(毫秒)内产生的4095个ID序号。
非分片键查询我们对user_info表的分片,是基于biz_id来实现的,也就是意味着如果我们想查询某张表的数据,必须先要使用biz_id路由找到对应的表才能查询到。 那么问题来了,如果查询的字段不是分片键(也就是不是biz_id),比如本次分库分表实战案例中,运营端查询就有根据名字、手机号、性别等字段来查,这时候我们并不知道去哪张表查询这些信息。 非分片键和分片键建立映射关系第一种解决办法就是,把非分片键和分片键建立映射关系,比如login_name -> biz_id 建立映射,相当于建立一个简单的索引,当基于login_name查询数据时,先通过映射表查询出login_name对应的biz_id,再通过biz_id定位到目标表。 映射表的只有两列,可以承载很多的数据,当数据量过大时,也可以对映射表做水平拆分。 同时这种映射关系其实就是k-v键值对的关系,所以我们可以使用k-v缓存来存储提升性能。 同时因为这种映射关系的变更频率很低,所以缓存命中率很高,性能也很好。 用户端数据库和运营端数据库进行分离运营端的查询可能不止于单个字段的映射来查询,可能更多的会涉及到一些复杂查询,以及分页查询等,这种查询本身对数据库性能影响较大,很可能影响到用户端对于用户表的操作,所以一般主流的解决方案就是把两个库进行分离。 由于运营端对于数据的一致性和可用性要求不是很高,也不需要实时访问数据库,所以我们可以把C端用户表的数据同步到运营端的用户表,而且用户表可以不需要做分表操作,直接全量查表即可。 当然,如果运营端的操作性能实在是太慢了,我们还可以采用ElasticSearch搜索引擎来满足后台复杂查询的需求。 实际应用中会遇到的问题数据迁移解决方案: |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 13:24:40- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |