一文搞懂MySQL数据库分库分表
mhr18 2024-12-06 17:56 15 浏览 0 评论
如果数据量过大,大家一般会分库分表。分库需要注意的内容比较少,但分表需要注意的内容就多了。
工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过分表。最近手里有个项目,预估数据量会很大,分表方案是选项之一,趁着这次机会,把分表的内容整理一下。
这次要讲的主要是水平分库分表,其它种类的分库、分表比较容易理解。后面如果不详细说明,都指水平分库分表。
1.基础知识
1.1分库分表定义
1.1.1分库
垂直分库:按照业务模块进行切分,将不同模块的表切分到不同的数据库中。
如电商系统有电商数据库,按照业务模块可以分为用户库、商品库、订单库,这些都可以当做独立数据库,不需要放到一起。好处是既能独立变更,又能隔绝相互影响。
1.1.2分表
垂直分表:也就是“大表拆小表”,基于列字段进行的。一般是因为表设计不合理,需要进行拆分。
如一张表存放学生、老师、课程、成绩信息,最好拆分为学生表、课程表、成绩表。
水平分表:针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。
水平分库分表:将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。
1.2分区与分片的区别
分表时经常能看到两个名词:分区和分片。这两个词都是指将大表的数据分成多块,但两者还是有本质区别的。
Sharding(分片) 的思想从分区的思想而来,但数据库分区基本上是数据对象级别的处理,比如表和索引的分区,每个子数据集上能够有不同的物理存储属性,还是单个数据库范围内的操作,而 Sharding 是能够跨数据库,甚至跨越物理机器的。
MySQL5.1提供的分区(Partition)功能确实可以实现表的分区,但是这种分区是局限在单个数据库范围里的,它不能跨越服务器的限制。
我们在分表的时候,一般使用的是分片方案,即数据存放在多个物理机器。
1.3分片策略
分片规则一般有如下:
1.3.1按照哈希切片
- mod-long:用于分区列为数值的hash分区分片列 id=分区列值 mod 分片数
- mod-long-by-hash:用于分区列为字符串的hash分区分片列id=hash(分区列值) mod 分片数
1.3.2按照范围切片
- range:建表时创建分区规则,根据分区规则就可以确定分区列的值在哪个分区上一般分区列为时间或者数值,如date_range:
0: 1000000
1: 2000000
2: 3000000
3: 4000000
4: maxvalue
如果分区列值为1500000,则数据放到1号分片上。
2.分库分表中间件
需要使用者感知不到这是分片表,使用时需要和正常表一样,一般需要引入中间件。
操作分片表一般有三种方式:
2.1客户端分片
所谓的客户端分片即在使用数据库的应用层直接操作分片逻辑,分片规则需要在同一个应用的多个节点间进行同步,每个应用层嵌入一个操作切片的逻辑实现。如当当网的Sharding JDBC。
2.2代理分片
代理分片就是在应用层和数据库层之间添加一个代理层,把分片的路由规则配置在代理层,代理层对外提供与JDBC兼容的接口给应用层,在业务实现之后,在代理层配置路由规则即可。如Mycat就是基于此种解决方案来实现的。
2.3支持事务的分布式数据库
支持分布式事务的框架,目前有OceanBase、TiDB框架,这些框架将可伸缩特定和分布式事务的实现包装到了分布式数据库内部实现,对使用者透明,使用者不需要直接控制这些特性,但是对事务的支持不如关系型数据,适合大数据日志系统、统计系统、查询系统、社交网站等。
2.4说明
支持事务的分布式数据库算另一种选型了,和MySQL已经没有关系。
对于客户端分片和代理分片,目前工作过的两家公司用的都是代理方式,一家用的是MyCAT,一家用的Dbatman。客户端分片方式没有接触过。这两种的区别为:
3.分布式事务
分片意味数据分布在多台物理机器上,引入分布式事务问题。我们将单表的数据切片后存储在多个数据库甚至是多个数据库实例中,所以依靠数据库本身的事务机制不能满足需要,这时就需要用到分布式事务来解决。关于分布式事务的相关内容可以看分布式系统与一致性协议。
这里不细讲分布式事务如何处理,后面会单独写篇文章。我们聊一下分布式事务会对操作MySQL产生什么影响。
既然知道引入了分布式事务问题,那么操作MySQL的时候,肯定不能和单表一样进行操作。不同中间件能力不一样,所以需要单独分析,我以Dbatman为例,阐述使用上的区别。
1.分片版本不维护自增与主键唯一,业务可自行维护唯一键
- 意味不同分片的主键id会重复
2.不支持跨分片事务写,可以跨分片事务读
- 如果确保事务操作的内容在一个分片内,就不是分布式事务,和单机行为一致
- 一个事务涉及多个分片叫跨节点事务,单分片事务支持
3.update和insert必须带分片列
总结一下就是操作同一个分片没影响,操作不同分片需要看中间件支持不支持。
如果使用中间件,即使同一个分片,尽量不要用特殊的SQL,有些中间件可能无法支持,如insert not exists。
4.是否选择分库分表
选择做分库分表,考虑的几个要素是:
- 空间方面:单个物理实例无法支撑数据存储需求,单台物理机无法继续通过加盘的方式扩容
- 主库性能:受限于单个主库的CPU/内存/磁盘IOPS的影响,接近或者达到上限后,需要拆分
- 容灾方面:减少单个主库宕机对于写入的影响。
针对以上3点,我们还可以多考虑一下,有没有更合适的方案
1.空间方面:
- 删除历史数据清空空间
- 修改存储模型降低对于MySQL磁盘的占用
- 改用空间压缩比更高的存储引擎
2.主库性能:
- 可以通过读写分离的方式,降低对于写库的读请求量,从而提升对于写入的支撑。
- 优化数据写入模型,减少批量写入(削峰)
3.容灾方面:
- 如果业务对于读高可用要求比较高,一般建议是做读写分离,将重要的请求路由至读库。读库数量一般会比写库多N个,在代理层面会做容灾的自动切换。
- 从集群整体的角度看,分库分表实际上是会扩大故障率,假设单台物理机的SLA是99.99%,那么2台物理机的SLA就是99.98(约数), 10台物理机的SLA就只剩下99.90%了。平均每年的故障时间也会从52分钟提升到525分钟。所以在有些场景下,单个节点故障可能会导致代理整个不可用,从而放大故障的影响范围。
5.设计
现在项目需求为:
- 生成唯一码,码值为整数
- 码值需要批量插入数据库
- 对码的更新操作都是单条处理,而且对码值进行操作需要进行记录
- 最终数量不定,长远看数据量会很大
基于上面的需求,做如下设计:
- 以码值为主键,自己控制主键唯一
- 码表使用range进行分片,如分片范围为01亿,1亿2亿
- 码表的操作记录表同样使用range进行分片,分片范围和码表一致
通过这种设计能够实现需求。
但计算后发现,单表能存百亿条数据,而且索引设计比较合理,业务逻辑相对简单,无高并发请求,单表好像也可以搞。
总结
正常情况下,我们一般需要做水平分库分表,这就涉及到分布式事务,一定要考虑清楚是否能满足自己的需求、想用的SQL语句是否都能支持,考虑一下是否还有别的方案。
关于中间件的实现原理,了解的不是很深,后面有时间的话,可以学习一下。
资料
- MySQL 分库分表方案,总结的非常好!
- MySQL之分库分表(MyCAT实现)
- Mysql分库分表实战(一)——一文搞懂Mysql数据库分库分表
- MySql分表、分库、分片和分区知识
- 数据库分片(Sharding)与分区(Partition)的区别(转)
- 数据库分库分表中间件对比(很全)
- 分库分表中间件
- 分库分表:中间件方案对比
- XA 分布式事务原理
最后
大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)
我的个人博客为:https://shidawuhen.github.io/
往期文章回顾:
招聘
- 字节跳动|内推大放送
- 字节跳动|今日头条广州服务端研发工程师内推
- 字节跳动|抖音电商急招上海前端开发工程
- 字节跳动|抖音电商上海资深服务端开发工程师-交易
- 字节跳动|抖音电商武汉服务端(高级)开发工程师
- 字节跳动|飞书大客户产品经理内推咯
- 字节跳动|抖音电商服务端技术岗位虚位以待
- 字节跳动招聘专题
设计模式
- Go设计模式(15)-门面模式
- Go设计模式(14)-适配器模式
- Go设计模式(13)-装饰器模式
- Go设计模式(12)-桥接模式
- Go设计模式(11)-代理模式
- Go设计模式(10)-原型模式
- Go设计模式(9)-建造者模式
- Go设计模式(8)-抽象工厂
- Go设计模式(7)-工厂模式
- Go设计模式(6)-单例模式
- Go设计模式(5)-类图符号表示法
- Go设计模式(4)-代码编写优化
- Go设计模式(4)-代码编写
- Go设计模式(3)-设计原则
- Go设计模式(2)-面向对象分析与设计
- Go设计模式(1)-语法
语言
- 再也不怕获取不到Gin请求数据了
- 一文搞懂pprof
- Go工具之generate
- Go单例实现方案
- Go通道实现原理
- Go定时器实现原理
- Beego框架使用
- Golang源码BUG追查
- Gin框架简洁版
- Gin源码剖析
架构
- 分页复选设计的坑
- 支付接入常规问题
- 限流实现2
- 秒杀系统
- 分布式系统与一致性协议
- 微服务之服务框架和注册中心
- 浅谈微服务
- 限流实现1
- CDN请求过程详解
- 常用缓存技巧
- 如何高效对接第三方支付
- 算法总结
存储
- MySQL开发规范
- Redis实现分布式锁
- 事务原子性、一致性、持久性的实现原理
- InnoDB锁与事务简析
网络
- HTTP2.0基础教程
- HTTPS配置实战
- HTTPS连接过程
- TCP性能优化
工具
- GoLand实用技巧
- 根据mysql表自动生成go struct
- Markdown编辑器推荐-typora
读书笔记
- 《毛选》推荐
- 原则
- 资治通鉴
- 敏捷革命
- 如何锻炼自己的记忆力
- 简单的逻辑学-读后感
- 热风-读后感
- 论语-读后感
- 孙子兵法-读后感
思考
- 对写博客的一些思考
- 晚上打119的经历
- 为动员一切力量争取胜利而斗争
- 反对自由主义
- 实践论
- 评价自己的标准
- 2020博客总结
- 服务端团队假期值班方案
- 项目流程管理
- 对项目管理的一些看法
- 对产品经理的一些思考
- 关于程序员职业发展的思考
- 关于代码review的思考
相关推荐
- redis 7.4.3更新!安全修复+性能优化全解析
-
一、Redis是什么?为什么选择它?Redis(RemoteDictionaryServer)是一款开源的高性能内存键值数据库,支持持久化、多数据结构(如字符串、哈希、列表等),广泛应用于缓存、消...
- C# 读写Redis数据库的简单例子
-
CSRedis是一个基于C#的Redis客户端库,它提供了与Redis服务器进行交互的功能。它是一个轻量级、高性能的库,易于使用和集成到C#应用程序中。您可以使用NuGet包管理器或使用以下命令行命令...
- 十年之重修Redis原理
-
弱小和无知并不是生存的障碍,傲慢才是。--------面试者总结Redis可能都用过,但是从来没有理解过,就像一个熟悉的陌生人,本文主要讲述了Redis基本类型的使用、数据结构、持久化、单线程模型...
- 高频L2行情数据Redis存储架构设计(含C++实现代码)
-
一、Redis核心设计原则内存高效:优化数据结构,减少内存占用低延迟访问:单次操作≤0.1ms响应时间数据完整性:完整存储所有L2字段实时订阅:支持多客户端实时数据推送持久化策略:RDB+AOF保障数...
- Magic-Boot开源引擎:零代码玩转企业级开发,效率暴涨!
-
一、项目介绍基于magic-api搭建的快速开发平台,前端采用Vue3+naive-ui最新版本搭建,依赖较少,运行速度快。对常用组件进行封装。利用Vue3的@vue/compiler-sfc单文...
- 项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!
-
项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!老铁们!是不是每次面试完都感觉自己像被大厂面试官婉拒的渣男?明明刷了三个月题库,背熟八股文,结果一被问项目就支支吾吾,简历写得像大学生课程设计?...
- 谷歌云平台:开发者部署超120个开源包
-
从国外相关报道了解,Google与Bitnami合作为Google云平台增加了一个新的功能,为了方便开发人员快捷部署程序,提供了120余款开源应用程序云平台的支持。这些应用程序其中包括了WordPre...
- 知名互联网公司和程序员都看好的数据库是什么?
-
2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...
- 腾讯云发布云存储MongoDB服务
-
近日,著名安全专家兼Shodan搜索引擎的创建者JohnMatherly发现,目前至少有35000个受影响的MongoDB数据库暴露在互联网上,它们所包含的数据暴露在网络攻击风险之中。据估计,将近6...
- 已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有
-
前言程序员,立之根本还是技术,一个程序员的好坏,虽然不能完全用技术强弱来判断,但是技术水平一定是基础,技术差的程序员只能CRUD,技术不深的程序员也成不了架构师。程序员对于技术的掌握,除了从了解-熟悉...
- 面试官:举个你解决冲突的例子?别怂!用这个套路……
-
面试官:举个你解决冲突的例子?别怂!用这个套路……最近收到粉丝私信,说被问到:团队技术方案有分歧怎么办?当场大脑宕机……兄弟!这不是送命题,是展示你情商+技术判断力的王炸题!今天教你们3招,用真实案例...
- 面试碰到MongoDB?莫慌,跟面试官这样吹MongoDB 复制集
-
推荐阅读:吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点阿里一线架构师分享的技术图谱,进阶加薪全靠它十面字节跳动,依旧空手而归,我该放弃吗?文末会分享一些MongoDB的学...
- SpringBoot集成扩展-访问NoSQL数据库之Redis和MongoDB!
-
与关系型数据库一样,SpringBoot也提供了对NoSQL数据库的集成扩展,如对Redis和MongoDB等数据库的操作。通过默认配置即可使用RedisTemplate和MongoTemplate...
- Java程序员找工作总卡项目关?
-
Java程序员找工作总卡项目关?3招教你用真实经历写出HR抢着要的简历!各位Java老哥,最近刷招聘软件是不是手都划酸了?简历投出去石沉大海,面试邀请却总在飞别人的简历?上周有个兄弟,13年经验投了5...
- Java多租户SaaS系统实现方案
-
嗯,用户问的是Java通过租户id实现的SaaS方案。首先,我需要理解用户的需求。SaaS,也就是软件即服务,通常是指多租户的架构,每个租户的数据需要隔离。用户可能想知道如何在Java中利用租户ID来...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)