数据库高并发和高可用方案

news2024/11/17 9:33:25

依旧主要参考沈剑大佬的多篇博文,以及数位网友的优秀分享,文末是完整参考。

1、高可用方案(HA,High Availability)

缓存是通过双写和双读主备、或者利用缓存的集群数据同步,故障自动转移来实现的

数据库的读是通过读写分离(MHA,Master High Availability),分库冗余多份来实现的;写是通过主从双备,keepalived+virtual IP 自动故障转移来实现的。

2、高并发方案

读多写少,读并发高就主从分离,写并发高就水平分库,如果读写请求并发都很大,那就先水平分库,然后对每个库进行按照主从集群部署。解决读并发高还有一个方案是用缓存。

2.1 读写分离,主从复制,分组架构

三个名词代指同个架构模型。

主从复制(也称 AB 复制)指的是将一个MySQL 主服务器的数据复制到一个或多个MySQL从服务器(从服务器)。也常被称为分组架构、读写分离架构。

主库提供数据库写服务,从库提供数据库读服务。一般是一主多从。

读写分离架构在解决高可用问题时一般被简称为 MHA(Master High Availability)。

2.1.1 读写分离架构的优势

  • 读写分离,使数据库能支持更大的读并发和吞吐量。由于写库单独拥有一个独立的库,所以也能一定程度上提高写性能
  • 读写数据库相互独立,通过消除读写锁冲突提升数据库写性能
  • 通过冗余从库实现数据的“读高可用”
  • 有利于架构的扩展,通过增加从库数量可以明显提高读性能。

2.1.2 mysql 主从复制过程(异步)

master 开启 binlog 功能,binlog 日志文件用于记录数据库的读写增删。 需要开启3个线程,master IO线程,slave开启 IO线程 SQL线程,

1、MySQL master 将数据变更写入二进制日志( binary log,就是我们常说的 binlog)

2、Slave 通过IO线程连接master,并且请求某个bin-log,position之后的内容。

3、MASTER服务器收到slave IO线程发来的日志请求信息,io线程去将bin-log内容,position返回给slave IO线程。

4、slave服务器收到bin-log日志内容,将bin-log日志内容写入relay-log中继日志,创建一个master.info的文件,该文件记录了master ip 用户名 密码 master bin-log名称,bin-log position。

5、slave端开启SQL线程,实时监控relay-log日志内容是否有更新,解析文件内容,生成SQL语句,在slave数据库中执行。

2.2 分库分表

2.2.1 水平切分(也被称为分片架构)

2.2.1.1 分片架构的优势
  • 线性提升数据库写性能,需要注意的是,分组架构是不能线性提升数据库写性能的
  • 降低单库数据容量

一句话总结,分片解决的是“数据库数据量大,写操作有瓶颈”问题,所实施的架构设计。

常见的水平拆分方式有范围法和哈希法两种。两种路由和拆分方式都非常简单。有各自的优势和缺点:

2.2.1.2 按照范围水平拆分

好处是

(1)能保持数据原有的顺序;

(2)能够准确控制每台服务器存储的数据量,从而使得存储空间的利用率最大。

(3)比较容易扩展,不需要移动现有数据,可以随时加一个uid[2kw,3kw]的数据服务;

不足是:

(1)请求的负载不一定均衡,一般来说,新注册的用户会比老用户更活跃,大range的服务请求压力会更大;

2.2.1.3 按照哈希水平拆分

好处:

(1)数据量分布均衡性较好;

(3)服务器请求负载均匀性较好;

不足:

不容易扩展,扩展一个数据服务,hash方法改变时候,可能需要进行数据迁移;但是可以通过一致性哈希来一定程度上缓解这个问题。分片数量成倍扩展,迁移成本也还行,不需要移动全部的数据。

一致性哈希参考:一致性哈希算法原理详解

2.2.1.4 哈希+范围混合分片

先做哈希,然后对哈希结果做范围分片(或者先范围分片再哈希分片),一种折中方案,数据和请求量都较为均衡。

2.2.2 垂直切分

分成垂直分表和垂直分库。

2.2.2.1 垂直分表:

将表中使用频率低或者字段长度较大的字段放到扩展表。这是因为,数据库会以行(row)为单位,将数load到内存(buffer)里,在内存容量有限的情况下,长度短且访问频度高的属性,内存能够load更多的数据,命中率会更高,磁盘IO会减少,数据库的性能会提升。

2.2.2.2 垂直分库:

直接按照业务将一个库拆成两个独立的库,可以降低单库的数据量。与业务结合比较紧密,并不是所有业务都能够进行垂直切分的。

2.3 读写分离 + 分库分表

读写分离和分库分表的结合体,性能更加强大,但是架构也更加复杂。

3、问题

问:读写分离跟水平分库的区别

  • 单个服务器的数据量不一样:主从分离每个服务器上存储的数据量相同,都是全集;水平分库后每个服务器上存储的数据量是总量的1/n,每个服务器的数据没有交集,所有服务器的数据的并集是全集。
  • 目标和作用不一样:读写分离是为了扩展读性能,主要是解决读并发高问题,因为写库单独拥有一个独立的库,所以也能一定程度上提高写性能;水平分库主要扩展写性能,主要解决写并发问题,扩展之后读写性能都能提高。
  • 应用场景不一样:读多写少,读并发高就主从分离,写并发高就水平分库,如果读写请求并发都很大,那就先分库,然后对每个库进行按照主从集群部署。解决读并发高还有一个方案是用缓存。

问:主从分离有什么问题吗?

写仍然是单点,所以要做主从双备,辅助 keepalived+virtual IP 自动故障转移来实现高可用。

问:数据库架构如何选型

  • 业务初期用单库
  • 读压力大,读高可用,用分组
  • 数据量大,写线性扩容,用分片
  • 属性短,访问频度高的属性,垂直拆分到一起

问:水平切分,到底是分库还是分表?

:强烈建议分库,而不是分表,因为:

  • 分表依然公用一个数据库文件,仍然有磁盘IO的竞争
  • 分库能够很容易的将数据迁移到不同数据库实例,甚至数据库机器上,扩展性更好

问:平常流量不高,但由于业务问题,会出现瞬时高并发怎么解决

通过 MQ 消息队列来削峰填谷降流。

问:水平分库后,业务接入代码需要改动吗?数据访问层需要改动吗

如果以前的单库和现在的分片库都是通过代理来访问的话,那只需要切换数据源代理即可,业务层不感知分片。

数据访问层可能需要增加一些分片路由的代码,以及一些多库遍历聚合数据的代码,可以考虑抽取出一个数据库中间件专门来干这个事,减少对数据访问层的代码改动。

问:水平分库后,非 patition key的查询怎么办?如何同时查询多个库的数据?怎么做join或者全表查询操作?怎么保证事务特性?

patition key 走 db 或者 cache,非 patition key 走搜索

问:高并发指的只并发处理还是并行处理

一般一直并行处理的能力,吞吐量。比如某服务能同时处理10个请求,但是每个请求执行 5s,那么每秒的吞吐量只有 2 个,所以我们一般称并发能力为 2,吞吐量为 2,QPS 为 2。

问:分库带来的分布式事务怎么做的?

解法一:分表而不是分库,这样就没有分布式事务的问题了,但是不建议分表。

问:水平分库后,根据用户名登录,此时不知道uid,只知道用户名,怎么知道查哪个分片库?非 partition key 属性的查询?

1、全库扫描法

缺点:需要扫描所有的分片库,聚合数据,效率低下(其实细想一下其实效率还行,如果用户名每个分片库都有索引的话,单库查询很快,而遍历所有的库的话可以多线程并发遍历来加快速度)

2、用户名跟主键建立映射关系(假设用户名具有唯一性):索引法

建立用户名映射到主键的映射表或者把映射关系存在缓存中,映射表需要存在同一个库里,如果量太大,单个缓存实例存不下,可以通过用户名对缓存进行水平分片。

缺点:需要多查一次数据库或者缓存

3、用户名跟 hash 规则产生关系,也称为基因法

设计函数通过用户名生成用来决定 hash 分片的位数的几个bit。比如hash分片是对 8 取模,那么根据用户名需要生成 3 个bit,将这三个比特位作为主键的最后三位,这样就能根据用户名计算出用户所在分片了。

缺点:① 需要提前容量规划,否则如果刚开始8个分片,用户名生成了3个bit,但是后来扩容到了16个分片,这时根据用户名又无法确定分片了,如果刚开始根据用户名生成6个比特位,那就算扩展到 64 个分片,也还是能通过用户名确定分片。② 设计用户名生成比特位时,需要设计均匀分布,否则会导致分库数据库不均衡。

注:如果用户名是唯一且不可修改的,那么可以同时用上面的三种方式,如果用户允许修改,那么只能用前 2 中方式。

4、直接根据用户名来生成整个主键

缺点:有uid生成冲突风险,且需要设计末尾几个 bit 均匀分布,否则会导致分库数据库不均衡。

参考:用uid分库,uname上的查询怎么办?

类似的业务场景还有订单ID的生成(使用用户ID基因),保证同一个用户的所有订单在同一个分表。

问:多个非 partition key 上的查询怎么办

选择其中一个不会发生修改的字段可以用基因法打入 partition key,其他的可以用映射索引法

问:patition key上的批量查询怎么做的

比如用户列表 uid 上的IN查询,通过 patition key 查询,但是每次返回多行记录,难点是 partition key 值有多个,不一定都在同一个分片库里。

法一:数据访问层访问所有库,把结果集进行合并

法二:数据访问层分析路由规则,按需访问

数据访问层对每个 uid 进行路由分析,只访问对应的分片库然后进行数据聚合。

问:水平分库后,跨库分页怎么做

业界难题-“跨库分页”的四种方案

问:水平分库后,需要用用户名进行模糊查询 、时间范围查询

根据用户名关键词或者时间范围等查 ES

问:通常多大的数据量需要分库?

没有复杂查询,5kw 到 1亿 条数据。复杂查询,1kw-2kw。

问:数据库分表,索引如何工作

分表不分表,对索引没有影响,哪个属性上有在线查询,哪个属性索引

问:分片后,怎么生成唯一主键

参考“分布式id生成器”

问:水平分库后,需要使用数据库中间件来实现分库的路由吗

可以用数据库中间件来屏蔽分库细节,也可以自己 hash 实现路由到指定的分库。

问:什么时候需要分布式事务

同时修改多个库的数据

问:主从分离中写库有多个,

建议遵循一主多从,一个写库,多个从库,如果单点写有瓶颈,可以水平扩展多个写库,但是每个分片写库都需要配置多个从库,这样从库可以随时取代主库,读始终高可用。

读操作需要路由到指定集群,然后路由到指定读库实例。写操作需要路由到指定集群的指定写库。

如果需要多主多从,最好每个写库都保留全量的数据,通过路由将请求路由到不同的写库,写库之间需要互相同步数据。

多分片主多从有哪些缺陷:

1、写库只包含部分数据,但是读库包含全部数据,数据不对等

问:缓存在主从分离架构中的作用是什么,为什么有了很多读库还需要缓存

缓存用来存储高频访问的数据,不是数据库中所有的数据都会被加载到缓存,只有某几类数据中的高频且修改频率低的数据才会被加载到缓存,提高服务的响应速度,降低延迟,降低数据库的压力。从库供业务方请求不在缓存中的数据,比如热点数据发生变更从缓存中淘汰了,或者大部分数据压根就没存在缓存中。

问:数据库主从切换会丢数据吗

有可能会。

有两种可能导致丢数据

  • 正常来说如果如果主库数据还没完全同步到从库,主库就发生宕机的话,是会丢数据的。还在找不丢数据的方案。
  • 脑裂,2个主库,老主库因为网络连接不上LB,没有被设置为只读,也没有断开老连接,仍能接收写请求,导致这部分数据丢失。

丢失的数据是怎么找回来

binlog 存在定时备份,通过恢复备份的 binlog 人工介入找回丢失的数据。

半同步复制,但是当出现网络波动等情况时,半同步复制会退化为异步复制,也坑无法保证数据至少在一个从库上完成同步。

怎么避免丢数据

不使用主从切换,而是主库做双主热备,keepalived+虚拟ip

切换前设置主库为只读,阻塞写入。

想了解更多,参考:MySQL 主从切换异常导致数据丢失

问:单库宕机重启会丢数据吗

不会,重启时会再次执行保存好的redo log日志,恢复还没有刷盘的写操作。

问:数据库切换时是否会主动断开连接?

切换时可以自定义是否主动断开连接,当前切换逻辑中没有选择断开连接,长连接也不会主动断开。

比如对于 MHA,可以通过修改对应脚本实现切换时断开连接。

问:分库和分表选择的依据是什么,什么时候应该分表,什么时候应该分库

根据当前的瓶颈点来选择究竟是分库还是分表。

由于单个表数据量太大导致单个 sql 延迟高,分表

由于数据库整体请求量达到单个实例 qps 上限,且因为 qps 太高导致数据库或者数据行加锁冲突严重,请求延迟增加,则分库,这样可以降低单个数据库的数据量且每秒请求量,通过水平分库提高整体请求量。

问:主从 binlog 消息是推还是拉

在基于位点的主从关系中,一开始创建主备关系时, 由备库需要开始同步的 binlog 文件位置,主库从该位置开始发送 binlog 至从库。而主备复制关系搭建完成以后,只要主库有生成新的日志,会立刻主动发给备库。

提示:主从用于 binlog 传输的 IO 线程通过 TCP 建立了长连接,所以可以持续发送数据。

4、完整参考

依旧强推沈剑大佬的公众号“架构师之路”

典型数据库架构设计与实践 | 架构师之路

用uid分库,uname上的查询怎么办?

究竟为什么要引入数据库中间件

多对多业务,数据库水平切分架构一次搞定

多key业务,数据库水平切分架构一次搞定

12 | 写多读少:MySQL 如何优化数据存储方案?

MySQL 主从切换异常导致数据丢失

无损半同步复制下,主从切换后数据一致吗?

24 | MySQL是怎么保证主备一致的?

业界难题-“跨库分页”的四种方案

Mysql 主从复制

mysql 主从复制原理及步骤。

Mysql主从架构-主库宕机如何恢复业务

Golang面经

双机集群(HA)系统简称

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

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

相关文章

06-PS中的四种蒙版

Photoshop中的蒙版就是遮罩的意思,主要作用就是将其所在的图层,把不同的明暗度转化成相应的透明度。黑色为完全透明,灰色为半透明,白色为完全不透明。添加蒙版有便于灵活修改,不影响图层原貌。PS蒙版有四类&#xff1a…

【状态估计】基于二进制粒子群优化 (BPSO) 求解最佳 PMU优化配置研究【IEEE30、39、57、118节点】(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Mybatis与微服务注册

目录 一,Springboot整合MybatisPlus 创建商品微服务子模块 二,SpringBoot整合Freeamarker 三、SpringBoot整合微服务 &gateway&nginx 整合微服务之商品服务zmall-product 创建并配置网关gateway服务 安装配置SwitchHosts 安装配置Windo…

【大数据hive】hive 函数使用详解

一、前言 在任何一种编程语言中,函数可以说是必不可少的,像mysql、oracle中,提供了很多内置函数,或者通过自定义函数的方式进行定制化使用,而hive作为一门数据分析软件,随着版本的不断更新迭代&#xff0c…

代码随想录第58天(动态规划):● 392.判断子序列 ● 115.不同的子序列

一、判断子序列 题目描述: 思路和想法: 这道题目还是最长公共子序列的拓展,只是这里进行删除的一定是t字符串,当不相等时,dp[i][j] dp[i][j - 1];其余基本一致。当最长公共子序列个数等s.size()时&#x…

Leetcode力扣秋招刷题路-0050

从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 50. Pow(x, n) 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。 示例 1: 输入:x 2.00000, n 10 输出&am…

N字形变换-力扣6-java

一、题目描述将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:P A H NA P L S I I GY I R之后,你的输出需要从左往右逐行读…

大神之路-起始篇 | 第11章.计算机科学导论之【数据压缩】学习笔记

欢迎关注「全栈工程师修炼指南」公众号点击 👇 下方卡片 即可关注我哟!设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习!涉及 企业运维、网络安全、应用开发、物联网、人工智能、大数据 学习知识“ 花开堪折直须折,莫待无花空折…

【深度学习】卷积神经网络

1 卷积神经网络(CNN)可以做什么? 检测任务分类与检索超分辨率重构:将图像训练的更清晰医学任务等无人驾驶人脸识别 2 用GPU:图像处理单元 比CPU块一百倍以上 3 卷积神经网络与传统神经网络的区别 传统神经网络&…

从证券软件开发到大数据开发,薪资涨幅一倍多,我经历了什么?

点击上方 "大数据肌肉猿"关注, 星标一起成长点击下方链接,进入高质量学习交流群今日更新| 1052个转型案例分享-大数据交流群分享学习群一位同学的大数据转型经历,他17年毕业后培训了几个月去了杭州一家证券公司做外包,用的是古老的…

有限元分析学习一

系列文章目录 有限元分析学习一 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、有限元方法的简单介绍1.1 有限元的基础概念1.2 有限元软件发展历史1.3 有限元软件二、弹性力学的简单介绍2.1.…

【Spring】注解实现IOC操作,你理解了吗?

作者:狮子也疯狂 专栏:《spring开发》 坚持做好每一步,幸运之神自然会驾凌在你的身上 专栏推荐:写文章刚刚起步,各个专栏的知识点后续会补充完善,不断更新好文,希望大 家支持一下。 专栏名字El…

jetson nano(ubuntu)安装ninja

文章目录安装环境安装环境 jetson nano 系统:4.6.1 安装re2c apt-get install re2c检查re2c是否安装成功 re2c --version ![在这里插入图片描述](https://img-blog.csdnimg.cn/847c19f15c2646bda44f6ae73b78509a.png#pic_center)下载ninja源代码 git clone https:/…

和在字节上班的兄弟聊过后,才知道原来年薪40W的测试有这么多?

最近脉脉职言区有一条讨论火了: 哪家互联网公司薪资最‘厉害’? 下面的评论多为字节跳动,还炸出了很多年薪40W的测试工程师 我只想问一句,现在的测试都这么有钱了吗? 前几天还有朋友说,从腾讯跳槽去了字…

(干货教程)在VSCode并使用chatgtp插件编写CC++语言程序

(干货教程)在VSCode并使用chatgtp插件编写CC语言程序 下载并安装VSCODE 第1步,下载VSCODE https://code.visualstudio.com/Download 第2步,安装VSCODE 安装过程较简单,这里省略。 安装好后效果如图&#xff1a…

(C语言)数据的存储

问:1. 数据类型有哪五大类?2. 数据类型的作用是什么与什么?3. 整型又可以具体分为哪五个?为什么字符char也归属于整型?4. 浮点型又可以具体分为哪两类?5. 构造类型就是什么?具体分为哪四类&…

2.4.8 PCIe——物理逻辑层——REFCLK

一、概述 pcie的参考时钟由板级输入,提供给IP内PHY层的PLL使用,由PLL产生core_clk和pipe_clk。 二、REFCLK产生方式 Serdes 所用时钟由 PHY 模块内的PLL生成,PLL的参考时钟可以由common clock(外部背板提供)、separ…

栈和队列的OJ练习题

前言 俗话说:熟能生巧,我们在学习完知识,一定要运用,不运用那么他过段时间就忘了,所以大家还是要认真的看一些题 (1)有效的括号 思路:我们可以用栈的知识 将左括号入栈,右括号出栈顶元素然后匹配…

【8】AMBA_SOC项目自学IC验证项目-仿真平台脚本使用讲解

仿真平台文件介绍和脚本使用说明 1、项目路径:2、文件夹说明:3、仿真运行命令:第一步:进入项目路径第二步:设置环境第三步:运行仿真第四步:查看波形1、项目路径: 位置:/tool/project/axi 2、文件夹说明: a、env就是放的我们uvm环境相关的env文件; b、out就是我们…

deque容器,const_iterator

目录 1.deque构造函数,容器中数据不修改的方法,const_iterator​编辑 2.deque赋值,,assign 3.deque大小的操作,empty,size,resize 4.deque容器插入和删除,push_back,push_front,pop_back,pop_front,insert,clear,era…