分库分表解决方案

news2024/9/20 6:32:27

前言
因为每个学校学生用餐人数太多,一天订单20万量增长,而且学校使用也在不停的增多,公司最近在搞分库分表,数据分离到不同的库中或表中, 所以这段时间了解过数据库的分库分表,也读过很多大神写的博文,基本上知道个大概,也在实际的应用中掌握分库分表的技术
下面总结一下从以下几个方面说起:
1、服务和数据库的演化过程
3、分库分表有哪几种方式。
4、分库分表有哪些问题
5、目前市面有的一些开源产品,技术,它们的优缺点是什么(只说ShardingJdbc和MyCat)

分库分表详解
下面我们以一个商城系统为例逐步讲解数据库是如何一步步演进。

** 分库**

单架构应用单数据库
早期的项目比如商城购买项目,基本上都是单体架构应用系统,一个系统中包含多个基础功能模块,比如用户模块、订单模块、库存模块等

在这里插入图片描述
所有模块在一个系统中,所有和功能模块关联的表也在一个数据库中,通常一个数据库中会存在非常多的表,早期用户数据量不多,使用单体架构足于满足需求。

** 为服务架构应用单数据库**
早期数据量小可能没有多大问题,后期业务量,系统分成了不同的很多功能模块,系统不停地迭代更新,代码量也会越来越大,单体架构已经不能满足需求,当用户量变大系统的访问压力也逐步的增加,项目功能模块就必须拆分。系统拆分按照功能模块拆分成Portal 服务、用户服务、订单服务、库存服务等

微服务架构单一数据库设计存在的问题:

1、微服务提供多个类型服务,但单一数据库的传统设计会产生紧密耦合,无法做为独立部署服务。

如果有多个服务访问同一数据库,则需要在所有服务间协调数据模式的更改,在现实工作中,这会导致额外的工作,延迟部署更新。

2、使用这样的设计很难对单个服务进行扩展,因为你只能选择扩展单一数据库。

3、使用单一数据库,对提高应用程序性能成为挑战。当使用单一共享数据库,在一段时间过后,我们最终会有着一个数据庞大的表,让数据检索变得很困难,我们必须连接多个大表格,方能获取所需的数据。

4、在绝大多数情况下,我们将数据使用关系存储到数据库。而使用关系数据库会限制一些服务。在有些情况下,NoSQL数据存储可能更适合你,能够降低集中式数据存储的紧密耦合。

** 微服务架构多数据库**

随着业务量的加大,数据库访问成为了瓶颈,这个时候多个服务共享一个数据库基本不可行了
,应该做到每个微服务都应该有属于自己的数据库,它仅包含与微服务本身相关的数据。这样就可以允许我们独立部署单个服务。单数据库的能够支撑的并发量是有限的,拆成多个库可以使服务间不用竞争,提升服务的性能。

在这里插入图片描述

如上图,从一个大的数据中分出多个小的数据库,每个服务都对应一个数据库,这就是系统发展到一定阶段必须要做的分库操作,如果只拆分服务应用不拆分数据库,不能解决根本问题,整个系统也很容易达到瓶颈。

** 分表**
上面我们说了数据库分库,接下来讲讲数据库分表
那为什么要分表呢,什么情况下需要分表呢?

当一个数据库被创建之后,随着时间的推移和业务量的增加,数据库中表以及表中的数据量就会越来越多,就有可能出现两种弊端:
第一种: 数据库的存储资源是有限的,其负载能力也是有限的,数据的大量积累肯定会导致其处理数据的能力下降。
第二种:数据量越多,那么对数据的增删改查操作的开销也会越来越大,所以,当出现如上两种情况,分库分表势在必行。

分库分表的类型和特点:
从维度来说分成两种,一种是垂直,一种是水平。
垂直切分:基于表或字段划分,表结构不同。我们有单库的分表,也有多库的分库。
水平切分:基于数据划分,表结构相同,数据不同,也有同库的水平切分和多库的切分。

垂直切分如下图:

水平切分如下图:

垂直分表有两种,一种是单库的,一种是多库的。
  单库垂直分表
    单库分表,比如:订单表,按照字段进行拆分,常规的方案是冷热分离(将使用频率高字段放到一张表里,剩下使用频繁低的字段放到另一张表里)。
  多库垂直分表
    多库垂直分表就是把原来存储在一个库的不同的表,拆分到不同的数据库。
  
当我们只是对原来的一张表做了分库的处理,如果业务系统的数据还是有一个非常快的增长速度,比如说订单下单数据库的订单表,数据量达到了几个亿,这个时候硬件
限制导致的性能问题还是会出现,所以从这个角度来说垂直切分并没有从根本上解决单库单表数据量过大的问题。在这个时候,我们还需要对我们的数据做一个水平的切分。

水平切分
  当我们的订单表数量已经到达数千万甚至上亿的时候,单表的存储容量和查询效率都会出现问题,我们需要进一步对单张表的数据进行水平切分。水平切分的每个数据库的表结构都是一样的,只是存储的数据不一样,比如每个库存储 1000 万的数据。水平切分也可以分成两种,一种是单库的,一种是多库的。
 单库水平分表
  水平拆分表就是按照表中的记录进行分片,举个例子,目前订单表 orders 有 2000w 数据,根据业务的增长,估算一年之后会达到1亿,同时参考阿里云 RDS for MySQL 的最佳实践,单表不建议超过 500w,1亿数据分20个子表就够了。
  
那根据什么来进行拆分呢?

按主键ID拆分数据很均匀,通过ID查询 orders 的场景几乎没有,业务访问 orders 大部分场景都是根据 user_id来过滤的,而且 user_id 的唯一性又很高(一个 user_id 对应的 orders 表记录不多,选择性很好),按照 user_id 来作为 Sharding key能满足大部分业务场景,拆分之后每个子表数据也比较均匀

这样就可以将 orders 表拆分成20个子表,看实际业务量和需求需要拆分成多少张表。

多库水平分表
  上面介绍了单表水平分表方案,接下来多库分表,意思是将拆分后的表存储在不同的 数据库中。
举个例子,交易数据库的订单表 有2亿多数据,数据库实例遇到了写入瓶颈,普通的 insert 都需要50ms,时常也会收到 CPU 使用率告警,这时就要考虑分库了。根据业务量增长趋势,计划扩容一台同配置的数据库实例,将订单表拆分20个子表,每个 数据库10个表。

常见的增删改查方式,比如查询方式:查询的时候要先通过定义的分区字段比如userId哈希定位到是哪个数据库后在哈希定位到具体的表,这样解决了订单表 太大的问题。

一般我们说的分库分表都是跨库的分表。既然分库分表能够帮助我们解决性能的问题。那我们在项目设计的时候是不是可以先给它们发几个库或者表呢,其实不然,在我们分库分表的过程中带来了很多的问题,分库分表之后带来了很多的复杂性,比如以前正常的sql使用分库分表以后有些地方需要改动。

拆分以后带来的问题有:
1、跨库关联查询

在单库未拆分表之前,我们可以很方便使用 join 操作关联多张表查询数据,但是经过分库分表后两张表可能都不在一个数据库中,如何使用 join进行关联用户信息表查询数据,因为数据在不同的数据库表中,我们不能直接使用join去关联的啊。

有以下几种方案可以解决:

1.1、字段冗余
一种典型的反范式设计,利用空间换时间,为了性能而避免join查询。例如:订单表保存userId时候,也将用户名称性别等需要查询的字段冗余保存一份,这样查询订单详情时就不需要再去查询用户表了。

1.2、全局表(广播表)
比如系统中所有模块都可能依赖的一些表,为了避免跨库join查询,可以将这类表在每个数据库中都保存一份。这些数据通常很少会进行修改,所以也不担心一致性的问题。

1.3、ER 表(绑定表)
关系型数据库中,如果可以先确定表之间的关联关系,并将那些存在关联关系的表记录存放在同一个分片上,那么就能较好的避免跨分片join问题。在1:1或1:n的情况下,通常按照主表的ID主键切分
    
1.4、系统层组装
在系统层面,分两次查询,第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。

2、 分布式事务
以客户下单为例:假如用户下单需要经过写入订单表,明细表,库存表,在此期间如果几个动作不是同时成功或者同时失败,就会出现数据一致性的问题。如果是在一个数据库里面,我们可以用本地事务来控制,但是在不同的数据库里面就不行了。所以分布式环境里面的事务,我们也需要通过一些方案来解决。
常用解决方案有:基于可靠消息(MQ)的解决方案、两阶段事务提交、柔性事务等。

3、排序、分页、函数计算问题
在使用 SQL 时 order by, limit 等关键字需要特殊处理,一般来说采用分片的思路:
先在每个分片上执行相应的函数,然后将各个分片的结果集进行汇总和再次计算,最终得到结果。

4、全局主键避免重复问题
MySQL数据库里面字段有一个自增的属性,Oracle订单表也有 Sequence 序列。如果是一个数据库,那么可以保证 ID 是不重复的,但是水平分表以后,每个表都按照自己的规律自增,肯定会出现 ID 重复的问题,因此需要单独设计全局主键,以避免跨库主键重复问题。有一些常见的主键生成策略:

4.1、UUID
4.2、基于数据库自增单独维护一张 ID表
4.3、号段模式
4.4、Redis 缓存
4.5、雪花算法(Snowflake)
4.6、百度uid-generator
4.7、美团Leaf
4.8、滴滴Tinyid

5、 多数据源和读写数据源的解决方案
分库分表之后可能会面临从多个数据库或多个子表中获取数据,一般的解决思路有:客户端适配和代理层适配。
业界常用的中间件有:
shardingsphere(前身 sharding-jdbc)
Mycat

ShardingJdbc和MyCat的区别以及优缺点?
区别:
MyCat是一个基于第三方应用中间件数据库代理裤架,客户端所以的jdbc请求都必须要先交给MyCat,再有MyCat转发具体的真实服务器中。

ShardingJdbc是一个Jar形式,在本地应用层重写jdbc原生的方法,实现数据库分片形式。

MyCat属于服务器数据库中间件,而ShardingJdbc是一个本地数据库中间件框架。

从设计理念上看确实有一定的相似性,主要流程都是SL解析→>SL路由→>SQL改写→>SQL执行→结果归并。但是架构设计是不同的。MyCat是基于Proxy,它复写了MySQL协议,将MyCat Server 伪装成一个MySQL数据库,而ShardingJdbc是基于JDBC的扩展,是以jar包的形式提供轻量级服务的。

ShardingJdbc的优缺点:
优点:1、程序自动完成,数据源方便管理;2、不需要维护、因为没有中间件;3、理论支持任何数据库(sql标准)。

缺点:1、存在代码入侵性;2、加大开发成本;3、不能做到动态添加数据源,添加数据源还需要重启程序;4、程序开发完后,运维人员参与不了。

MyCat的优缺点

优点:1、数据添加不会影响到程序;2、应用层不需管理数据库层方面,由代理层去管理;3、添加数据源不需要重启程序。

缺点:1、程序依赖的中间件,提高维护工作;2、容易出现高可用问题;3、中间件导致切换数据库变的困难;2、增加了proxy,程序性能下降。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/142230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

elasticsearch 7.9.3知识归纳整理(五)之es的索引生命周期管理

es的索引生命周期管理 一、常见概念及命令 1.1、概念 ILM定义了四个生命周期阶段: Hot:正在积极地更新和查询索引。 Warm:不再更新索引,但仍在查询。 cold:不再更新索引,很少查询。信息仍然需要可搜索&…

【蓝桥杯基础题】2021年省赛填空题—卡片

👑专栏内容:蓝桥杯刷题⛪个人主页:子夜的星的主页💕座右铭:前路未远,步履不停 目录一、题目背景二、题目描述三、题目分析1.检查思路2.思路优化四、代码汇总1.C语言代码2. C代码3.运行结果五、总结1.枚举思…

“强鹰”会议纪要发布,不会停止加息?风险资产恐将承压

美联储发布了去年12月的会议纪要,详细揭露了货币政策制定者对经济和加息路径的最新研判,继续展现偏鹰的论调和立场。 纪要显示,美联储官员致力于抗击通货膨胀,并预计在取得更多进展之前利率将继续上升,并维持“一段时间…

82.Zabbix之Linux服务器agent监控(不需要联网)

Zabbix版本:6.2.3 官网上下载对应的agent

C#中的多线程(一)

一、多线程的术语 在学习多线程之前需要先理解有关多线程的术语。 CPU(中央处理器)或内核/核心是实际执行程序的硬件单元。许多现代CPU都支持同时多线程(Intel称之为超线程),即使一个CPU能表现为多个「虚拟」CPU。进…

Linux安装xFormers教程

参考文章:手把手教你在linux中手动编译并安装xformers 作者:青空朝颜モ出处:bilibili 官方安装方法 官方仓库传送门:https://github.com/facebookresearch/xformers.git 官方给了两种方式安装xFormers,这里给出官方仓…

数字化转型之数字化和业务化论证

引言 数据业务化的本质是数据的产品化、商业化与价值化。主要强调产品化、新业务和专业化运作,也就是以数据为主要内容和生产原料,打造数据产品,按照产品定义、研发、定价、包装和推广的套路进行商业化运作,把数据产品打造成能为企业创收的新兴业务。 数字化是信息技术发…

NodeJs中使用Express开发web项目

文章目录1. web开发模式1.1 服务端渲染的Web开发模式1.2 前后端分离的Web开发模式1.3 如何选择web开发模式2. 身份认证2.1 Session认证机制2.1.1 cookie2.1.2 cookie认证2.1.3 在Express中使用Session认证2.1.4 Session认证的局限性2.2 JWT认证机制2.2.1 JWT组成部分2.2.2 在No…

mysql优化实战

空气质量小时索引顺序先站点后时间 索引情况 根据时间范围查询索引失效 EXPLAIN SELECT station_code, station_name, data_time, aqi, pm25, pm10, o3, no2, so2, co, primary_pollutant, create_date FROM wuhaiyizhangtu.t_air_pollution where data_time between 2022-1…

Node.js 中 session验证登录

在前一篇内容中讲到这个cookie实现验证登录,cookie是存储在客户端的,而session是存储在服务器的,相比较session的安全性会更高,session对象存储特定用户会话所需要的属性以及配置信息,服务通过session对象将用户的信息…

【力扣刷题】day3-4. 寻找两个正序数组的中位数

力扣刷题笔记day3 4. 寻找两个正序数组的中位数 题意 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 输入:nums1 [1,3], nums2 …

【通讯录管理系统】C++全栈体系(六)

通讯录管理系统 第一章 系统需求 通讯录是一个可以记录亲人、好友信息的工具。 本教程主要利用C来实现一个通讯录管理系统 系统中需要实现的功能如下: 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、…

人工智能算法模型--Alpha-Beta剪枝算法学习笔记

⬜⬜⬜ 🐰🟧🟨🟩🟦🟪 (*^▽^*)欢迎光临 🟧🟨🟩🟦🟪🐰⬜⬜⬜ ✏️write in front✏️ 📝个人主页:陈丹宇jmu &a…

【华为机试真题详解】不含 101 的数【2022 Q4 | 100分】

文章目录前言题目描述输入描述输出描述示例 1示例2题目解析参考代码前言 《华为机试真题详解 Python实现》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可…

逻辑漏洞渗透与攻防(五)之权限类逻辑漏洞

目录 权限类逻辑漏洞 平行权限跨越 基于用户身份ID 基于对象ID 基于文件名 垂直权限跨越 未经授权访问 权限类逻辑漏洞 越权漏洞又分为平行越权,垂直越权和交叉越权。 平行越权:权限类型不变,权限ID改变,垂直越权&#xff1…

SQL ORDER BY 关键字

ORDER BY 关键字用于对结果集进行排序。 SQL ORDER BY 关键字 ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。 ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 DESC 关键字。 SQL ORDER BY 语法 SELECT c…

太适合小白了!11招,高手都在用的数据分析招式!

阅读本文大概需要3分钟菜鸟独白用Python来玩转数据分析实在是太爽了,因为有强大的Pandas来处理数据非常方便,我个人对数据分析情有独钟,探索数据的秘密非常好玩!前段时间写过一篇小白学数据分析入门招式,但是进阶的部分…

蓝桥杯基础练习合集九 1.回文词2.猜数字游戏的提示3.生成元4.环状序列5.刽子手游戏

目录 1.回文词 2.猜数字游戏的提示 3.生成元 4.环状序列 5.刽子手游戏 1.回文词 问题描述 输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。所谓回文串,就是反转以后和原串相同,如abba和madam。所有镜像串&…

docker 安装mysql5.7

拉取镜像 非常快 因为上一篇安装的是阿里云的centos7并且配置了阿里云的镜像加速 docker pull mysql:5.7 拉取成功检验 启动镜像 docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASS…

软件测试行业未来职业规划是什么

随着软件工程活动的不断演化,软件测试岗位已经成为了软件开发中极其重要的一个环节,因而市场对于软件测试人才的需求也在日益扩大。相信不少想入行软件测试的小伙伴都难免会有这样的疑问,软件测试行业究竟怎么样?职业发展应该如何…