3个点说清楚分库分表扩容问题

简介: 3个点说清楚分库分表扩容问题

前言

像我这样的菜鸟,总会有各种疑问,刚开始是对 JDK API 的疑问,对 NIO 的疑问,对 JVM 的疑问,当工作几年后,对服务的可用性,可扩展性也有了新的疑问,什么疑问呢?其实是老生常谈的话题:服务的扩容问题。
image

正常情况下的服务演化之路

让我们从最初开始。
单体应用 每个创业公司基本都是从类似 SSM 和 SSH 这种架构起来的,没什么好讲的,基本每个程序员都经历过。
RPC 应用 当业务越来越大,我们需要对服务进行水平扩容,扩容很简单,只要保证服务是无状态的就可以了,如下图:
image

当业务又越来越大,我们的服务关系错综复杂,同时,有很多服务访问都是不需要连接 DB 的,只需要连接缓存即可,那么就可以做成分离的,减少 DB 宝贵的连接。如下图:
image

我相信大部分公司都是在这个阶段。Dubbo 就是为了解决这个问题而生的。
如果你的公司产品很受欢迎,业务继续高速发展,数据越来越多,SQL 操作越来越慢,那么数据库就会成为瓶颈,那么你肯定会想到分库分表,不论通过 ID hash 或者 range 的方式都可以。如下图:
image

这下应该没问题了吧。任凭你用户再多,并发再高,我只要无限扩容数据库,无限扩容应用,就可以了。
这也是本文的标题,分库分表就能解决无限扩容吗?
实际上,像上面的架构,并不能解决。
其实,这个问题和 RPC 的问题有点类似:数据库连接过多!!!
通常,我们的 RPC 应用由于是使用中间件进行访问数据库,应用实际上是不知道到底要访问哪个数据库的,访问数据库的规则由中间件决定,例如 sharding JDBC。这就导致,这个应用必须和所有的数据库连接,就像我们上面的架构图一样,一个 RPC 应用需要和 3 个 mysql 连接,如果是 30 个 RPC 应用,每个 RPC 的数据库连接池大小是8 ,每个 mysql 需要维护 240 个连接,我们知道,mysql 默认连接数是 100,最大连接数是 16384,也就是说,假设每个应用的连接池大小是 8 ,超过 2048 个应用就无法再继续连接了,也就无法继续扩容了。
注意,由于每个物理库有很多逻辑库,再加上微服务运动如火如荼, 2048 并没有看起来那么大。
也许你说,我可以通过前面加一个 proxy 来解决连接数的问题,实际上,代理的性能也会成为问题,为什么?代理的连接数也是不能超过 16384 的,如果并发超过 16384,变成 163840,那么 proxy 也解决不了问题。
怎么办?让我们再看看上面的架构图:
image

我们发现,问题是出在“每个 RPC 应用都要连所有的库”,导致扩容应用的同时,每个数据库连接数就要增加。就算增加数据库,也不能解决连接数的问题。
那怎么办呢?
欢迎大家关注我的公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。

单元化

单元化,听起来高大上,通常在一些 XXX 大会上,分享“关于两地三中心”,“三地五中心”,“异地多活”等等牛逼的名词的时候,单元化也会一起出现。
这里我们不讨论那么牛逼的,就只说“数据库连接数过多” 的问题。
实际上,思路很简单:我们不让应用连接所有的数据库就可以了。
假设我们根据 range 分成了 10 个库,现在有 10 个应用,我们让每个应用只连一个库,当应用增多变成 20个,数据库的连接不够用了,我们就将 10 个库分成 20 个库,这样,无论你应用扩容到多少个,都可以解决数据库连接数过多的问题。
注意:做这件事的前提是:你必须保证,访问你这个应用的 request 请求的数据库一定是在这个应用的。s
换个说法,当用户从 DNS 那里进来的时候,就知道自己要去那个应用了,所以,规则在 DNS 之前就定好了,虽然这有点夸张,但肯定在进应用之前就知道要去哪个库了。
所以,这通常需要一个规则,例如通过用户 ID hash,由配置中心广播 hash 规则。这样,所有的组件都能保持一致的规则,从而正确的访问到数据库。如下图:
image

到这里,我们终于解决了无限扩容的问题。

总结

本文从单体应用开始,逐步讲述了一个正常后台的演进历程,知道了分库分表并不能解决“无限扩容” 的问题,只有单元化才能解决这问题。而单元化则带来更多的复杂性。但是好处不言而喻。
单元化带来的更多的思路。
有了单元化,解决了无限扩容的问题,但是我们还没有考虑单点的问题,即服务的可用性。要知道,我们这里的数据库都是单点的。

最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!

相关文章
|
12月前
|
设计模式 Java 程序员
Java 设计模式之工厂模式:对象创建的艺术(含 UML 图解)
本文详解Java工厂模式三大形态:简单工厂、工厂方法与抽象工厂,结合UML图解与代码实例,剖析其核心思想——“创建与使用分离”。通过计算器、日志系统、电子设备等案例,深入讲解各模式的实现原理、适用场景及优缺点,并对比选择策略。最后揭示工厂模式在JDK和主流框架中的实际应用,帮助开发者掌握对象创建的艺术,提升代码扩展性与可维护性。(238字)
1141 5
|
7月前
|
Java 区块链 开发工具
模拟个人所得税APP,模拟计算Tezos智能合约
该项目基于Tezos区块链开发,旨在提供智能合约与自动化计算服务,主要技术栈包括智能合约编程语言与相关区块链开发工具。
995 0
|
7月前
|
存储 API 调度
养“虾”更高效:OpenClaw多Agent协同搭建+阿里云/本地部署+百炼api对接及避坑指南
2026年,OpenClaw(俗称“龙虾”,曾用名Clawdbot)的核心价值已从单一智能体执行升级为多Agent协同作战。单Agent模式在面对长流程、多任务场景时,极易出现上下文爆炸、任务排队、风格串味等问题,而多Agent团队通过“分工明确、隔离运行、协同调度”的模式,能完美解决这些痛点——就像一个专业团队,每个成员各司其职,在编排者的统筹下高效完成复杂任务。本文将从**多Agent团队搭建核心逻辑**、**阿里云+本地多系统部署步骤**、**阿里云百炼Coding Plan API配置**、**常见问题解答**四大板块出发,搭配可直接执行的代码命令和实操案例,实现OpenClaw从部署
1287 3
|
SQL 算法 Java
MySQL分库分表:应对海量数据的策略
本文深入解析MySQL分库分表策略与实战技巧,涵盖分片键选择、算法对比、数据迁移、全局ID生成及跨分片查询处理等内容,助你构建可扩展的海量数据架构,提升系统性能与可用性。
|
关系型数据库 MySQL Java
MySQL 分库分表 + 平滑扩容方案 (秒懂+史上最全)
MySQL 分库分表 + 平滑扩容方案 (秒懂+史上最全)
|
安全 物联网 API
核验身份证的一致性API的实战指南
随着网络空间安全问题日益突出,实名制成为保障安全与秩序的重要手段。探数API的身份证实名认证工具通过姓名和身份证号核验用户身份真实性,并返回扩展信息,广泛应用于各行业。本文介绍了其实现功能、调用流程及代码示例,同时解答了关于个人信息安全等常见疑问。接入该API不仅满足合规要求,更能提升用户信任,降低运营风险,共同构建安全高效的数字未来。
1447 1
|
消息中间件 存储 NoSQL
MQ的顺序性保证:顺序队列、消息编号、分布式锁,一文全掌握!
【8月更文挑战第24天】消息队列(MQ)是分布式系统的关键组件,用于实现系统解耦、提升可扩展性和可用性。保证消息顺序性是其重要挑战之一。本文介绍三种常用策略:顺序队列、消息编号与分布式锁,通过示例展示如何确保消息按需排序。这些方法各有优势,可根据实际场景灵活选用。提供的Java示例有助于加深理解与实践应用。
1367 2
|
存储 前端开发 JavaScript
React 文件上传组件 File Upload
本文介绍了如何在 React 中实现文件上传组件,包括基本的概念、实现步骤、常见问题及解决方案。通过 `<input type="file">` 元素选择文件,使用 `fetch` 发送请求,处理文件类型和大小限制,以及多文件上传和进度条显示等高级功能,帮助开发者构建高效、可靠的文件上传组件。
1233 3
|
SQL 存储 缓存
聊聊分库分表后非Sharding Key查询的三种方案~(建议收藏)
聊聊分库分表后非Sharding Key查询的三种方案~(建议收藏)
2097 0
|
JavaScript IDE Java
bugly崩溃排查3:观察是谁调用了崩溃函数
bugly崩溃排查3:观察是谁调用了崩溃函数
403 0