【进阶篇】MySQL分库分表详解

文章目录

  • 0. 前言
    • 1. 垂直分库分表
    • 2. 水平分库分表
  • 1. 理解过程及实现方案
      • 问题讨论
      • 衍生出分库分表策略
      • 借助成熟组件使用
      • 分库分表阶段完成后面临的问题
        • 1. 异地多活问题
        • 2. 数据迁移问题
        • 3. 分布式事务问题
        • 4. join查询的问题
    • 分库分表的策略实现示例
  • 2. 参考文档

在这里插入图片描述

0. 前言

假设有一个电商网站,随着用户量和订单量的增加,单一数据库难以承载如此庞大的数据量,查询速度也逐渐降低,这时就需要进行分库分表。

1. 垂直分库分表

电商网站有用户模块和订单模块,可以将用户表和订单表拆分到不同的数据库中。例如,原本在同一个数据库中的用户表(包含用户基础信息和用户扩展信息)和订单表,可以拆分为两个数据库,一个数据库存储用户的基础信息,另一个数据库存储用户的扩展信息和订单信息。

最常见的博客文章都是以电商系统作为案例,因为他是最具备代表性,电商网站的用户模块和订单模块是可以拆分到不同的数据库中的。这种拆分方式可以提高系统的可扩展性和性能。

假设有一个电商网站,它有一个数据库,其中包含两个表:用户表(User)和订单表(Order)。用户表包含用户的基础信息(如用户名、密码等)和用户的扩展信息(如用户的购物偏好、历史订单等)。订单表包含订单的详细信息(如订单号、购买的商品、数量、价格等)。

原始结构可能如下:

Database: EcommerceDBTable: User- UserID- Username- Password- Preferences- HistoryOrdersTable: Order- OrderID- UserID- Product- Quantity- Price

可以将这个数据库拆分为两个数据库:一个数据库(UserDB)存储用户的基础信息,另一个数据库(OrderDB)存储用户的扩展信息和订单信息。

拆分后的结构可能如下:

Database: UserDBTable: UserBasic- UserID- Username- PasswordDatabase: OrderDBTable: UserExtension- UserID- Preferences- HistoryOrdersTable: Order- OrderID- UserID- Product- Quantity- Price

这样,当用户的基础信息和订单信息需要进行大量的读写操作时,这两个操作可以在不同的数据库上并行进行,从而提高系统的性能。同时,由于用户的基础信息和订单信息被存储在不同的数据库中,因此,如果其中一个数据库出现问题,也不会影响到另一个数据库的正常运行,从而提高了系统的可用性。

2. 水平分库分表

假设订单表中有上百万条数据,查询和写入速度逐渐下降。此时,可以根据订单ID进行水平分表,比如订单ID为奇数的存入订单表1,订单ID为偶数的存入订单表2。这样,原本一个表需要处理的数据量就减半了,可以提高查询和写入速度。

在进行分库分表后,对于程序查询也需要做相应的调整。例如在进行水平分表后,查询某个订单信息时,需要先判断订单ID是奇数还是偶数,然后再决定查询哪个表。

Database: OrderDBTable: Order- OrderID- UserID- Product- Quantity- Price
Database: OrderDBTable: Order0- OrderID- UserID- Product- Quantity- PriceTable: Order1- OrderID- UserID- Product- Quantity- Price

在这种情况下,Order0用于存储ID为偶数的订单,Order1用于存储ID为奇数的订单。

查询和写入的伪代码可能如下所示:

def get_order(order_id):if order_id % 2 == 0:# Query Order0 tablereturn query_order_0(order_id)else:# Query Order1 tablereturn query_order_1(order_id)

这样,我们可以根据订单ID的奇偶性来决定查询或写入哪个表,从而将原本一个表需要处理的数据量减半,提高查询和写入速度。

实际的分库分表会更复杂。同时,分库分表也可能会带来一些问题,如数据一致性问题、跨库事务问题等。因此,在设计分库分表方案时,需要进行充分的考虑,并可能需要引入其他的技术(如分布式事务)来解决这些问题。

那么,让一起深入了解一下数据库知识应用实践之分库分表。

1. 理解过程及实现方案

记住一句话,不是所有系统一上来就搞分库分表,包括淘宝,京东。尤其这种超前设计,对小公司来说就是累赘,甚至隐患。不仅人才成本,资源成本,运维成本。甚至学习成本都不容小觑。所以基本上都是不断衍生到分库分表,才算是中小公司正确的技术路线和最优实践。

我们以一个场景:例如有一个电子商务网站,随着业务的发展,用户数量、商品数量和交易数量都在快速增长。原来单一的数据库已经无法满足需求,查询速度慢,系统负载高,甚至出现宕机情况。这样的情况下,为了提高系统的性能和稳定性,就需要进行数据库的分库分表。

问题讨论

分库分表的目的是为了解决单个数据库无法承受大量数据和高并发的问题。但是分库分表也会带来一些问题,例如数据一致性问题、分布式事务问题、跨库跨表查询问题、数据迁移问题等。

衍生出分库分表策略

  1. 垂直分库分表:按业务模块进行分库,将大表按照字段进行分表,例如用户库、商品库等。

  2. 水平分库分表:将数据按一定的规则分散到不同的数据库或表中,例如按用户ID的hash值分库,按订单时间分表等。

借助成熟组件使用

常见框架:

  1. MyCat:一个开源的分库分表中间件,支持自定义分片规则,可以实现读写分离、事务和SQL的完全透明。
  2. Sharding-JDBC:一款轻量级的Java框架,提供了强大的分库分表、读写分离、分布式事务和分布式序列等功能。
  3. Shardingsphere:包含了Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这三款独立的产品,可以满足不同场景下的数据分片需求。
    分库分表的复杂问题:

分库分表阶段完成后面临的问题

当技术演进到我们已经解决了分库分表基本问题,解决了并发问题,解决性能问题,接下来我们基本上面临如下几个问题。关于这些问题又需要我们继续去学习和研究尝试更多方案。此处我们不做展开。

1. 异地多活问题

在数据库地理分布、灾备等问题上,如果是多库多表的情况,数据同步和备份的复杂度将会增加。

2. 数据迁移问题

.在分库分表后,如何对旧数据进行迁移以及如何在迁移过程中保证业务的正常运行是个大问题。

3. 分布式事务问题

在传统的单体数据库中,事务是保证数据一致性的重要手段。但在分库分表的环境下,原有的事务机制不能再使用,需要引入新的分布式事务解决方案。

4. join查询的问题

在分库分表后,原本在一个库或一个表中可以做的join查询就变得困难,需要通过应用层去做关联和组合。

分库分表的策略实现示例

  1. 函数法(哈希、取模等):根据某个字段(比如用户ID)的函数结果进行分库分表。
  2. 范围法(枚举、区间):比如根据日期范围,订单ID范围等进行分库分表。
  3. 一致性哈希:在新增或减少数据库节点的时候,能够最小化数据的迁移。

我们用Java写一些伪代码方便大家理解。
假设我们有多种根据某个值(如用户ID或订单ID)来确定应将数据存储在哪个数据库的方式。我们分别用函数法,范围法和一致性哈希法三种方法模拟一下。

  1. 函数法:我们可以将用户ID除以数据库数量的余数作为数据库的索引。
public String getDatabase(int userId) {int dbCount = 2; // 假设我们有2个数据库int dbIndex = userId % dbCount;return "db" + dbIndex;
}
  1. 范围法:我们可以使用订单ID作为范围进行划分,比如订单ID小于10000的存储在一个数据库,大于等于10000的存储在另一个数据库。
public String getDatabase(int orderId) {if (orderId < 10000) {return "db0";} else {return "db1";}
}
  1. 一致性哈希:这种方法需要使用到特殊的数据结构,例如TreeMap。首先,我们将每个数据库(称为节点)添加到一个TreeMap中,然后计算键(如用户ID)的哈希值,并在TreeMap中找到该哈希值对应的数据库。如果没有找到,则返回哈希值最接近的数据库。
public class ConsistentHashing {private TreeMap<Integer, String> nodes = new TreeMap<>();public void addNode(String nodeName) {int hash = nodeName.hashCode();nodes.put(hash, nodeName);}public void removeNode(String nodeName) {int hash = nodeName.hashCode();nodes.remove(hash);}public String getDatabase(String key) {if (nodes.isEmpty()) {return null;}int hash = key.hashCode();if (!nodes.containsKey(hash)) {SortedMap<Integer, String> tailMap = nodes.tailMap(hash);hash = tailMap.isEmpty() ? nodes.firstKey() : tailMap.firstKey();}return nodes.get(hash);}
}

其实真实场景中我们大多都使用分库分表组件或者中间件,最著名的和大家最常用的sharding-jdbc就是解决这类场景的一个优秀的,轻量级的分库分表组件,虽然有很多bug或者不足,但是足以解决我们90%的问题了。后面有一个章节我会写一个详细教程关于sharding-jdbc使用详解。除了它还有一些国产的中间件也不错。如下

  1. TDDL:阿里巴巴开源的分库分表中间件,支持复杂的分库分表策略。
  2. Oceanus:网易云数据库的分库分表解决方案,支持自动分库分表、读写分离、分布式事务等功能。

2. 参考文档

  1. “MySQL分库分表方案” - InfoQ。介绍了 MySQL 的分库分表方案,并对实施这种方案的步骤进行了详细的讨论。链接:https://www.infoq.cn/article/solution-of-mysql-sub-database-and-sub-table

  2. “MySQL 分库分表实践” - 阿里云社区的一篇文章也可以参考学习。介绍了 MySQL 分库分表的实践和经验。链接:https://developer.aliyun.com/article/776687

  3. “分库分表架构设计” 详细介绍了分库分表架构的设计和实施。链接:https://www.jianshu.com/p/d7f3d3808f25

  4. ShardingSphere 是 Apache 的一个开源项目包包含了我上面说的sharding-jdbc,提供了分库分表的解决方案。链接:https://shardingsphere.apache.org/document/current/cn/overview/

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

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

相关文章

windows笔记本远程连接如何打开任务管理器?

参考素材&#xff1a; https://jingyan.baidu.com/article/8275fc86a97f5207a03cf6cd.html https://www.anyviewer.cn/how-to/ctrl-alt-delete-remote-desktop-6540.html 网上查了很多方法&#xff0c;都说ctrlaltend可以解决这个问题。 但是笔记本键盘上没有end键。 继续查了一…

【数学建模】清风数模正课5 相关性分析

相关系数 相关性分析的关键是计算相关系数&#xff0c;在本节课中将会介绍两种常用的相关系数&#xff1a;皮尔逊相关系数&#xff08;Pearson&#xff09;和斯皮尔曼相关系数&#xff08;Spearman&#xff09;。 它们可以用来衡量两个变量间相关性的大小&#xff0c;对于不同…

Android 13 - Media框架(9)- NuPlayer::Decoder

这一节我们将了解 NuPlayer::Decoder&#xff0c;学习如何将 MediaCodec wrap 成一个强大的 Decoder。这一节会提前讲到 MediaCodec 相关的内容&#xff0c;如果看不大懂可以先跳过此篇。原先觉得 Decoder 部分简单&#xff0c;越读越发现自己的无知&#xff0c;Android 源码真…

安卓 tcp 客户端

安卓 tcp 客户端 Server:8888 是Qt 写的Tcp 服务器 ip 是 192.168.2.103 port是8888 安卓手机运行 kotlin 语法的Tcp Client &#xff0c;连接&#xff0c;收发数据 效果如下图 Tcpclient package com.example.myapplicationimport android.os.Handler import android.os.Loo…

Go操作各大消息队列教程(RabbitMQ、Kafka)

Go操作各大消息队列教程 1 RabbitMQ 1.1 概念 ①基本名词 当前市面上mq的产品很多&#xff0c;比如RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。 Broker&#xff1a;表示消息队列服务实体Virtual Host&#x…

深入探讨梯度下降:优化机器学习的关键步骤(一)

文章目录 &#x1f340;引言&#x1f340;什么是梯度下降&#xff1f;&#x1f340;损失函数&#x1f340;梯度(gradient)&#x1f340;梯度下降的工作原理&#x1f340;梯度下降的变种&#x1f340;随机梯度下降&#xff08;SGD&#xff09;&#x1f340;批量梯度下降&#xf…

HTML5+CSS3+JS小实例:科技感满满的鼠标移动推开粒子特效

实例:科技感满满的鼠标移动推开粒子特效 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport&qu…

回归拟合 | 灰狼算法优化核极限学习机(GWO-KELM)MATLAB实现

这周有粉丝私信想让我出一期GWO-KELM的文章&#xff0c;因此乘着今天休息就更新了(希望不算晚) 作者在前面的文章中介绍了ELM和KELM的原理及其实现&#xff0c;ELM具有训练速度快、复杂度低、克服了传统梯度算法的局部极小、过拟合和学习率的选择不合适等优点&#xff0c;而KEL…

HFSS 3维曲线导入

HFSS 3维曲线导入 简介环境参考代码使用结果 简介 如图一所示&#xff0c;CST中可以通过导入和到出由任意点组成的曲线&#xff0c;但是HFSS中貌似不能导入&#xff08;如图二所示&#xff09;&#xff0c;如果我们要将matlab的产生的曲线的点的数据导入特变麻烦&#xff0c;特…

测试验证平台

测试验证平台 1.功能说明&#xff1a; 模拟智能终端车端数据采集及上报的功能&#xff0c;提供数据管理平台的模拟和验证功能。 2.系统组成&#xff1a; 系统示意图 功能要求&#xff1a; 本地电脑实现Imx6配置功能&#xff0c;能够通过运行不同的脚本&#xff0c;模拟不…

大规模网络爬虫系统架构设计 - 云计算和Docker部署

在大规模网络爬虫系统中&#xff0c;合理的架构设计和高效的部署方式是确保系统稳定性和可扩展性的关键。本文将介绍如何利用云计算和Docker技术进行大规模网络爬虫系统的架构设计和部署&#xff0c;帮助你构建高效、可靠的爬虫系统。 1、架构设计原则 在设计大规模网络爬虫系…

英码科技受邀亮相2023WAIE物联网与人工智能展,荣获行业优秀创新力产品奖!

8月28日-30日&#xff0c;2023WAIE 物联网与人工智能展在深圳福田会展中心顺利举办。英码科技受邀亮相本届展会&#xff0c;并现场重点展出了面向智慧交通、智慧校园、智慧应急、智慧园区等不同行业的创新AIoT产品、AI技术服务等内容&#xff0c;与生态伙伴积极探讨市场需求和问…

CentOS配置Java环境报错-bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件

CentOS配置Java环境后执行java -version时报错&#xff1a; -bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件原因是所使用的jdk的版本和Linux内核架构匹配不上 使用以下命令查看Linux架构&#xff1a; [rootlocalhost ~]# cat /proc/version Linux version 3.1…

vue3中右侧26个英文字母排列,点击字母,平滑到响应内容

效果图如下&#xff1a; 右侧悬浮 <!-- 右侧悬浮组件 --><div class"right-sort"><div v-for"(item, index) in list" :key"index" class"sort-item" :class"index activeIndex ? sort-item-active : " c…

Spring IOC的理解

总&#xff1a; 控制反转&#xff08;IOC&#xff09;&#xff1a;理论思想&#xff0c;传统java开发模式&#xff0c;对象是由使用者来进行管理&#xff0c;有了spring后&#xff0c;可以交给spring来帮我们进行管理。依赖注入&#xff08;DI&#xff09;&#xff1a;把对应的…

音频——I2S DSP 模式(五)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 DSP formatDSP A时序图逻辑分析仪抓包 DSP B时序图逻辑分析仪抓包 DSP format DSP/PCMmode 分为 Mode-A 和 Mode-B 共 2 种模式。不同芯⽚有的称为 PCM mode 有的称为 DSP m…

【Rust】001-基础语法:变量声明及数据类型

【Rust】001-基础语法&#xff1a;变量声明及数据类型 文章目录 【Rust】001-基础语法&#xff1a;变量声明及数据类型一、概述1、学习起源2、依托课程 二、入门程序1、Hello World2、交互程序代码演示执行结果 3、继续上难度&#xff1a;访问链接并打印响应依赖代码执行命令 三…

Python Opencv实践 - 轮廓检测

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/map.jpg") print(img.shape) plt.imshow(img[:,:,::-1])#Canny边缘检测 edges cv.Canny(img, 127, 255, 0) plt.imshow(edges, cmapplt.cm.gray)#查找轮廓 #c…

解决Ubuntu 或Debian apt-get IPv6问题:如何设置仅使用IPv4

文章目录 解决Ubuntu 或Debian apt-get IPv6问题&#xff1a;如何设置仅使用IPv4 解决Ubuntu 或Debian apt-get IPv6问题&#xff1a;如何设置仅使用IPv4 背景&#xff1a; 在Ubuntu 22.04(包括 20.04 18.04 等版本) 或 Debian (10、11、12)系统中&#xff0c;当你使用apt up…

【MATLAB第70期】基于MATLAB的LightGbm(LGBM)梯度增强决策树多输入单输出回归预测及多分类预测模型(全网首发)

【MATLAB第70期】基于MATLAB的LightGbm(LGBM)梯度增强决策树多输入单输出回归预测及多分类预测模型&#xff08;全网首发&#xff09; 一、学习资料 (LGBM)是一种基于梯度增强决策树(GBDT)算法。 本次研究三个内容&#xff0c;分别是回归预测&#xff0c;二分类预测和多分类预…