mysql 平滑扩容_数据库秒级平滑扩容架构方案

一、缘起

(1)并发量大,流量大的互联网架构,一般来说,数据库上层都有一个服务层,服务层记录了“业务库名”与“数据库实例”的映射关系,通过数据库连接池向数据库路由sql语句以执行:

1c17221a2ebaec65ae3e54a8f5347800.png

如上图:服务层配置用户库user对应的数据库实例物理位置为ip(其实是一个内网域名)。

(2)随着数据量的增大,数据要进行水平切分,分库后将数据分布到不同的数据库实例(甚至物理机器)上,以达到降低数据量,增强性能的扩容目的:

aa9983a71199a1a76c488b9e01fe2dd0.png

如上图:用户库user分布在两个实例上,ip0和ip1,服务层通过用户标识uid取模的方式进行寻库路由,模2余0的访问ip0上的user库,模2余1的访问ip1上的user库。

关于数据库水平切分,垂直切分的更多细节,详见《一分钟掌握数据库垂直拆分》 。

(3)互联网架构需要保证数据库高可用,常见的一种方式,使用双主同步+keepalived+虚ip的方式保证数据库的可用性:

965867d6470834085c9417e8c7dd3105.png

如上图:两个相互同步的主库使用相同的虚ip。

1e378ac74c2c511633f7542365b7562a.png

如上图:当主库挂掉的时候,虚ip自动漂移到另一个主库,整个过程对调用方透明,通过这种方式保证数据库的高可用。

关于高可用的更多细节,详见《究竟啥才是互联网架构“高可用”》。

(4)综合上文的(2)和(3),线上实际的架构,既有水平切分,又有高可用保证,所以实际的数据库架构是这样的:

2ce7f1c5c653c4f1d5d3e2b1e2c9674f.png

提问:如果数据量持续增大,分2个库性能扛不住了,该怎么办呢?

回答:继续水平拆分,拆成更多的库,降低单库数据量,增加库主库实例(机器)数量,提高性能。

最终问题抛出:分成x个库后,随着数据量的增加,要增加到y个库,数据库扩容的过程中,能否平滑,持续对外提供服务,保证服务的可用性,是本文要讨论的问题。

二、停服务方案

在讨论平滑方案之前,先简要说明下“x库拆y库”停服务的方案:

(1)站点挂一个公告“为了为广大用户提供更好的服务,本站点/游戏将在今晚00:00-2:00之间升级,届时将不能登录,用户周知”

(2)停服务

(3)新建y个库,做好高可用

(4)数据迁移,重新分布,写一个数据迁移程序,从x个库里导入到y个库里,路由规则由%x升级为%y

(5)修改服务配置,原来x行配置升级为y行

(6)重启服务,连接新库重新对外提供服务

整个过程中,最耗时的是第四步数据迁移。

回滚方案:

如果数据迁移失败,或者迁移后测试失败,则将配置改回x库,恢复服务,改天再挂公告。

方案优点:简单

方案缺点:

(1)停服务,不高可用

(2)技术同学压力大,所有工作要在规定时间内做完,根据经验,压力越大约容易出错(这一点很致命)

(3)如果有问题第一时间没检查出来,启动了服务,运行一段时间后再发现有问题,难以回滚,需要回档,可能会丢失一部分数据

有没有更平滑的方案呢?

三、秒级、平滑、帅气方案

2ce7f1c5c653c4f1d5d3e2b1e2c9674f.png

再次看一眼扩容前的架构,分两个库,假设每个库1亿数据量,如何平滑扩容,增加实例数,降低单库数据量呢?三个简单步骤搞定。

(1)修改配置

2eb2c25267aa6d7d7227c350f8b80463.png

主要修改两处:

a)数据库实例所在的机器做双虚ip,原来%2=0的库是虚ip0,现在增加一个虚ip00,%2=1的另一个库同理

b)修改服务的配置(不管是在配置文件里,还是在配置中心),将2个库的数据库配置,改为4个库的数据库配置,修改的时候要注意旧库与辛苦的映射关系:

%2=0的库,会变为%4=0与%4=2;

%2=1的部分,会变为%4=1与%4=3;

这样修改是为了保证,拆分后依然能够路由到正确的数据。

(2)reload配置,实例扩容

b64a2aae9776115e4774abaae148ce37.png

服务层reload配置,reload可能是这么几种方式:

a)比较原始的,重启服务,读新的配置文件

b)高级一点的,配置中心给服务发信号,重读配置文件,重新初始化数据库连接池

不管哪种方式,reload之后,数据库的实例扩容就完成了,原来是2个数据库实例提供服务,现在变为4个数据库实例提供服务,这个过程一般可以在秒级完成。

整个过程可以逐步重启,对服务的正确性和可用性完全没有影响:

a)即使%2寻库和%4寻库同时存在,也不影响数据的正确性,因为此时仍然是双主数据同步的

b)服务reload之前是不对外提供服务的,冗余的服务能够保证高可用

完成了实例的扩展,会发现每个数据库的数据量依然没有下降,所以第三个步骤还要做一些收尾工作。

(3)收尾工作,数据收缩

4466adc5e541f67388f7df22d8ca11d9.png

有这些一些收尾工作:

a)把双虚ip修改回单虚ip

b)解除旧的双主同步,让成对库的数据不再同步增加

c)增加新的双主同步,保证高可用

d)删除掉冗余数据,例如:ip0里%4=2的数据全部干掉,只为%4=0的数据提供服务啦

这样下来,每个库的数据量就降为原来的一半,数据收缩完成。

四、总结

682ad72771bb710a5e6e9426fd20bfd4.png

该帅气方案能够实现n库扩2n库的秒级、平滑扩容,增加数据库服务能力,降低单库一半的数据量,其核心原理是:成倍扩容,避免数据迁移。

迁移步骤:

(1)修改配置

(2)reload配置,实例扩容完成

(3)删除冗余数据等收尾工作,数据量收缩完成

以上内容均来自微信公众号“架构师之路”胡剑老师的文章,欢迎关注。

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

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

相关文章

IoT -- (九) IoT通讯技术选型与模型设计

IoT时代的无线通讯技术 “世界上最遥远的距离就是没有网络”,网络通讯是IoT的基础,常见的无线网络通讯技术有:WiFi、NFC、ZigBee、Bluetooth、WWAN(Wireless Wide Area Network,包括GPRS、3G、4G、5G等)、…

SSM中PageHelper的使用步骤与com.github.pagehelper.PageHelper3系列与5系列的区别

SSM中PageHelper的使用步骤 一. 在pom.xml导入依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.2</version></dependency>二. 交给IOC管理 在SqlSessionFactory…

@requestbody和@requestparam作用

1、什么都不写 GET 可以自动封装为对象模型&#xff0c;没有的数值自动为0值 POST 请求体里面放了数据&#xff0c;但是还是使用了RequestParam里的数据 总结&#xff1a; 在不使用注解的情况下&#xff0c;相当于默认使用了RequestParam里的数据 &#xff08;这种理解是错…

@RequestBody的使用

提示&#xff1a;建议一定要看后面的RequestBody的核心逻辑源码以及六个重要结论本文前半部分的内容都是一些基 本知识常识&#xff0c;可选择性跳过。 声明&#xff1a;本文是基于SpringBoot&#xff0c;进行的演示说明。 基础知识介绍&#xff1a; ​ RequestBody主要用来接…

@RequestBody 和 @RequestParam可以同时使用

RequestParam和RequestBody这两个注解是可以同时使用的。 网上有很多博客说RequestParam 和RequestBody不能同时使用&#xff0c;这是错误的。根据HTTP协议&#xff0c;并没有说post请求不能带URL参数&#xff0c;经验证往一个带有参数的URL发送post请求也是可以成功的。只不过…

mysql索引使增删变慢_mysql优化之索引篇

mysql&#xff0c;对it打工人&#xff0c;这个几乎是必备的技能之一。mysql可以解决我们平时工作中的大量的、有关增删查改的问题。所以想深入了解mysql&#xff0c;我觉得关键在于他的增删查改背后的算法&#xff0c;开搞。面对增删查改等问题&#xff0c;直接通过场景来看吧场…

POST、GET、@RequestBody和@RequestParam区别

RequestParam 注解RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中。 RequestParam可以接受简单类型的属性&#xff0c;也可以接受对象类型。 RequestParam有三个配置参数&#xff1a; required 表示是否必须&#xff0c;默认为 true&#xff0c;必须。de…

centos安装mysql卡住_CentOS 6.4安装MySQL的过程中出现的bug

在CentOS 6.4下安装MySQL&#xff0c;下载一个源码包&#xff0c;感觉很简单&#xff0c;tar&#xff0c;./configure&#xff0c;make&#xff0c;make install 经典四步&#xff0c;弄这个也不是第一次了&#xff0c;但今天就是老出错&#xff0c;首先是./configure中&#x…

SpringMVC接受List的几种方式

说到SpringMVC接受List参数&#xff0c;可能有人会说这个是个坑&#xff01;下面我来跟大家说怎么补这个坑。下面我分几种情况来讲&#xff1a; 一、只接收一个List 1、form表单提交 controller代码&#xff1a; ResponseBody RequestMapping("test") public voi…

mysql怎么加固_mysql安装及加固

mysql安装查看是否安装mysql我们先看一下有没有安装mysqlyum list installed mysql | grep mysql本地只安装了php链接mysql的库&#xff0c;没有安装mysql如果有安装&#xff0c;可以使用安装的或者卸载了重新安装添加yum源去mysql官网查找下面我就来安装下yum源sudo rpm -ivh …

RabbitMQ保姆级教程

文章目录 前言一、MQ是什么&#xff1f; 1.1 AMQP 二、在Linux安装RabbitMQ 2.1 安装2.2 RabbitMQ启动命令2.3 开启RabbitMQ 后台管理界面 2.3.1 登录rabbitMQ UI界面 2.3 Docker启动RabbitMQ2.4 常见消息模型2.5 生产者(Producer) / 消费者(Consumer)2.6 工作队列模式(Work Q…

spring mysql 连接池配置_SpringBoot数据库连接池常用配置

关注公众号&#xff1a;程序猿王国 持续更新&#xff0c;每日分享在配置文件中添加配置如下(我使用的是多数据源)&#xff1a;spring.datasource.primary.urljdbc\:mysql\://localhost\:3306/test?useUnicode\true&characterEncoding\utf-8spring.datasource.prim…

交换机到底是啥?

1、交换机 交换机个人资料&#xff1a; 1.证件照 注&#xff1a;copy 百度百科 我的博客/交换机到底是啥&#xff1f; 这东西乍一看有点像月光宝盒&#xff0c;是不是。 2.个人简介 交换机&#xff08;Switch&#xff09;意为“开关”是一种用于电&#xff08;光&#xff0…

unity3d 动态合批设置_Unity3D SkinnedMeshRenderer合批优化

最近做了性能优化相关的工作&#xff0c;其中一些是关于战斗模块的渲染的。主要是对场景中使用的基于SkinnedMeshRenderer的网格进行了一些合批优化(降DC)&#xff0c;记录如下。项目使用的Unity版本为5.6.4p1。游戏中的战斗模块是这样的&#xff1a;战斗逻辑由服务器承担&…

java类的加载顺序_java类加载先后顺序

这里讲的不是类加载机制,是类的加载先后顺序。话不多说了&#xff0c;先设定以下场景:package com.jingdong;public class A {public static void main(String[] args){System.out.println(Ib.b);B bnew B();b.ibTest();}}public class B implements Ib{private D d;private C …

MyBatis:模糊查询的4种实现方式

1、根据姓名模糊查询员工信息 1.1、方式一 步骤一&#xff1a;编写配置文件 步骤二&#xff1a;测试 步骤三&#xff1a;分析 此种方式需要在调用处手动的去添加“%”通配符。 1.2、方式二 说明&#xff1a; 使用方式一可以实现模糊查询&#xff0c;但是有一点不方便的地…

java 阻塞 socket_java socket非阻塞I/O

1 非阻塞(Nonblocking)体系结构在这一部分&#xff0c;我将从理论的角度来解释非阻塞体系的结构及其工作原理。这部“喜剧”(当然&#xff0c;如果你喜欢的话也可以称做戏剧)的“人物”如下&#xff1a;●服务器端&#xff1a;接收请求的应用程序。●客户端&#xff1a;向…

java mod函数的使用方法_java 数学计算的具体使用

java.lang.Math 库提供了常用的数学计算工具常量final double E 2.7182818284590452354; // 自然对数底数final double PI 3.14159265358979323846; // 圆周率final double DEGREES_TO_RADIANS 0.017453292519943295; // 角度转弧度final double RADIANS_TO_DEGREES 57.295…

java的debug模式_java第六章:debug模式介绍及大量实例练习

1.Debug模式1.1什么是Debug模式【理解】是供程序员使用的程序调试工具&#xff0c;它可以用于查看程序的执行流程&#xff0c;也可以用于追踪程序执行过程来调试程序。1.2Debug模式操作流程【应用】如何加断点选择要设置断点的代码行&#xff0c;在行号的区域后面单击鼠标左键即…

注解RequestMapping中的URI路径最前面到底需不需要加斜线?

注解RequestMapping中的URI路径最前面到底需不需要加斜线? 您有没有这样的困惑&#xff1a;在协同开发过程中&#xff0c;使用RequestMapping&#xff0c;或者是GetMapping&#xff0c;或者是PostMapping这类注解时&#xff0c;有的程序员加了斜线&#xff0c;有的程序员没有…