高性能架构—存储高性能

1 📊关系型数据库

存储技术飞速发展,关系型数据的ACID特性以及强大的SQL查询让其成为各种业务系统的关键和核心存储系统。
很多场景下的高性能设计最核心的就是关系型数据库的设计,很多数据库厂商再优化和提升单个数据库服务器的性能方面做了很多技术优化和改进。但是单个服务器已经无法满足业务需求,要考虑以下方式:读写分离分库分表分散访问压力和存储压力

1.1 读写分离

将数据库的读写操作分散到不同节点

在这里插入图片描述

具体逻辑实现如下:

  1. 数据库服务器搭建主从集群,一主一从、一主多从都可以
  2. 主机负责读写操作,从机只负责读操作
  3. 主机通过复制将数据同步到主机,每台服务器都存储了所有的业务数据
  4. 业务服务器将写操作发给主机,读操作发给从机

注意主从集群不是主备集群,两者有本质上的差异,主从代表一种职务关系,主备代表一种替换关系

读写分离逻辑并不复杂,但是要应对数据复制操作延迟带来的复杂度,可能会导致网络分区或延迟带来的数据不一致,常见的解决办法如下:

  1. 写操作后的读操作发送给主机
  2. 从机读失败后,再读一次主机——二次读取
  3. 关键业务读写指向主机,非关键业务可以采用读写分离

1.2 分库分表

分散存储压力,主要分为分库、分表

1.2.1 业务分库

指的是按照业务模块将数据分散到不同的数据库,模块间要互相用数据时,可以通过远程调用来获取其他模块的数据

在这里插入图片描述

带来的问题
  • join操作问题:不同的数据库的表是没办法直接join操作的
  • 事务问题:不同的数据库服务器是没办法直接保证事务的,MySQL的XA或者我们的分布式事务解决方案可以简单解决这个问题,但是性能堪忧
  • 成本问题:1台服务器拆成三个模块,1->3,如果加上主备1->6

1.2.2 分表

将业务数据分散到各个数据库中,能支撑百万甚至千万用户规模的业务,主要分为垂直分表和水平分表

在这里插入图片描述

  • 垂直分表,相当把列分开,一些列存在一个表,另一些列存在另一个表
  • 水平拆分,相当有多个相同属性业务的表,存放着不同列的数据,比如按照id大小划分,id小于多少的在一张表…
垂直分表

通常将某些不常用但是占了大量空间的数据列拆分

某些数据库下可能能提高存储和查询能力,比如Mysql将大空间的列拆出去后,一个页就能存放更多的数据,页在内存中缓存时,被命中的概率更高

水平分表

千万级别的表需要警惕,一般单表行数超过5000万行就必须进行分表了,但是有一些表可能比较复杂,1000万行就要分表也说不一定

水平分表的复杂度主要有以下几点:

路由

哪条数据该查哪张表,该存哪张表,需要路由进行计算

  • 范围路由:类似于数据range分区,某个范围的数据放在某个地方…
  • Hash路由:将某个列hash运算后取余总表数,放入对应的表中,扩容很麻烦,要重新散列(尝试虚拟一致性hash)
  • 配置路由:利用一张表存储id和路由的关系,比如记录user_id 和 table_id,通过user_id就可以获取其表的id,但是要查询两张表才能获取到数据
join操作

需要在业务代码或者数据库中间件进行多次join才能将数据合并后查询

count操作
  • count每张分表,然后进行相加
  • 新建一张表,记录统计信息table_id,count_num,每次新增和删除都会操作这张表,将count每张表的压力分散到每次删除和新增操作上
order by操作

需要在业务代码或者数据库中间件查询每个子表的数据,进行汇总排序

1.3 实现方法

读写分离需要将读/写操作分开去访问服务器,分库分表需要将不同的数据访问不同的数据库服务器,两者的分配方式都属于将不同的SQL分发到不同的库中
常见的分配方式有两种:程序代码封装中间件封装

程序代码封装

代码中抽象一个数据访问层来实现读写分离、分库分表

MVC模型举例就是相当于在mapper层和service层之间加一个中间抽象层,service通过这个抽象调用service->很像AOP
具备如下特点:

  • 实现简单,而且可以根据业务做较多定制化功能
  • 每个编程语言都要自己实现一次,无法通用。开发工作量和编程语言数量成正比
  • 数据库故障发生时,进行了主从切换,所有系统都可能要修改配置重新启动

目前开源方案有TDDL(头都大了),架构如下
在这里插入图片描述

中间件封装

在业务服务器和数据库服务器中间架一台中转站,进行转发

具备特点如下:

  • 能支持多种编程语言,因为这个这种中间件对业务服务器提供的是标准SQL接口
  • 数据库中间件要支持完整的SQL语法和数据库服务器协议,这个很复杂
  • 数据库中间件,不执行真正的读写操作,但是因为所有请求都会走这里,所以性能要求高
  • 业务服务器对数据库主从切换无感知,需要中间件探测数据库状态来提供信息

目前开源方案:mysql-proxy、MySQL Router、Atlas(基于mysql-proxy开发)

实现复杂度

  • 读写分离实现要识别SQL操作是读还是写即可(只需要判断DQL和DDL关键字)
  • 分库分表要判断操作类型,和具体操作的表、函数、order by、group by操作等,不同的操作有不同的状态

2 📇NoSQL

NoSQL的出现可以弥补关系型数据库的一些缺陷,如:无法存储数据结构,schema扩展不方便,大数据场景下I/O高,关系型数据库的全文搜索功能弱
NoSQL是Not Only SQL 不只是SQL,而不是No SQL

请牢记,NoSQL的出现不是为了取代关系型数据库,而是增强

常见的NoSQL方案如下:

  1. K-V存储:解决关系型数据库无法存储数据结构——Redis代表
  2. 文档数据:解决关系型数据库schema约束问题——MongoDB
  3. 列式数据库:解决大数据场景下I/O问题——HBase
  4. 全文搜索引擎:解决全文搜索性能问题——ElasticSearch

2.1 K-V存储

全称 Key-Value存储,Key是数据的标识,Value为数据,Redis是其中的代表,支持多种数据结构

Redis提供的很多数据类型都有很强大的功能,比如LPOP,RPUSH,LpopRpush等,如果要用关系型数据库来实现,肯定比较麻烦和复杂

缺点很明显,不支持完成的ACID事务,事务能力弱不保证原子和持久,原因如下

  • Redis指令排队时能保证原子,但是指令真正执行时并不保证原子
  • 即使Redis支持RDB后使用AOF,还是会出现AOF在某一时刻没有刷盘导致数据丢失

2.2 文档数据库

No-Schema,可以存储和读取任意的数据,无需在使用前定义字段,优势如下

  • 新增字段简单,无需取修改结构后再新增数据
  • 历史数据不会出错,即使历史数据中新增的字段的值为空,只需要代码兼容处理就行,比如Optional
  • 可以很容易存储复杂数据,JSON的格式就是一种类对象格式,属性包属性,属性包数组

缺点就是无法实现关系型数据库那样的结构化查询,比如join等

2.3 列式数据库

按照列来存储数据,和关系型数据库的行存储对应,利用列存储的优势如下

  • 同时读取多个列时效率很高,因为列都是按行存储一起,一次磁盘操作就能将一行的数据的各个列读出来
  • 能力一次行完成都某列的操作,能保证针对行数据写操作的原子性和一致性

列式数据库在某些场景下的优势很明显,不然就是劣势大于优势,比如海量数据的统计,有时候并不需要其他列只需要统计某一列,不需要读很多页就可以把数据读到内存中,节省I/O
如果发生在频繁更新多个列,很常见的关系型数据的使用场景,那么此时列存储就会变成列式,因为行写操作,写的是不连续空间

2.4 全文搜索引擎

倒排索引(反向索引、反向文档)是全文搜索引擎的技术原理基础,是一种索引方法,将词语作为索引,id作为索引值,只要找到你要找的词语,就能找到这个词语出现在哪些id的文档中

正向索引:
在这里插入图片描述

倒排索引:
在这里插入图片描述

与关系型数据库结合

我们目前使用ES这类搜索引擎,其实就是将对象的结构和数据转换为JSON后放入ES中,并且ES本身就是支持RestFul风格的语法

并且Es能基于JSON文档建立全文索引

3 🎯缓存

某些情况下,单纯靠存储系统的性能的提升是不够的,如下场景

  1. 需要经过复杂的计算得出的数据,比如统计系统的pv和uv,用户同时在线数量,如果实时用MySQL来count(*) ,并且使用一张表实时记录,性能无法保证
  2. 读多写少的数据,存储系统有心无力,比如微博,某位大v发了微博,那么千万人来读,如果用MySQL来存储,一个insert可能会带来千万次的select

缓存就是为了弥补存储系统在这些复杂业务的不足,将重复使用的数据放到内存中,一次生成多次使用

在这里插入图片描述

3.1缓存穿透

是指穿透了缓存,没有走缓存直接走数据库,具体原因可能如下

  • 访问的数据不存在,查不到以为过期了,就走数据库
    • 一般使用布隆过滤器或者缓存不存在的值解决
  • 缓存数据生成耗费大量时间或资源
    • 如果一个数据过期,第一次访问来了,发现缓存没有数据,走数据库查出来后,存入缓存,在这个期间还有其他访问来了,会造成穿透
    • 或许可以使用提前预热等方式简单解决

3.2缓存雪崩

指缓存在同一时间很多缓存过期,并且还没有从DB加载到缓存,导致大量请求在这个时刻全部打到DB上,解决方法如下

  • 更新锁:对缓存更新加锁保护,没拿到更新锁的线程要么直接返回,要么等待获取锁后重新读缓存
  • 后台更新:缓存的更新不是由用户的读取而去写缓存,而是由定时更新数据到缓存中
    • 当出现内存不够,或者时间过期,那么会出现数据不在缓存的情况,可以使用读取到空值后发送消息到消息队列,等待消息队列去同步缓存

3.3 缓存击穿

和缓存雪崩类似,但雪崩是缓存数量+请求个数两个维度给数据库带来的压力,而击穿是单个缓存失效后,大量请求带来的压力

  • 同样可以通过更新锁解决

3.4 缓存热点

热备某个数据,但是这个数据的访问量确实很大,可以将这个数据分发到多个缓存服务器上,或者像redis的读写分离,1主多从,将压力分散到其他读服务器上

📖4 总结

  • 高性能数据库集群的第一种方式是“读写分离”,将读压力分散到其他节点
    • 需要考虑复制延迟,网络分区等复杂度
    • 请求分发机制实现分为:程序代码封装和中间件封装
  • 高性能数据库集群的第二种方式是“分库分表”,既可以分散访问压力,还可以分散存储压力
    • 业务分库:业务模块将数据分散到不同的库
      • 可能出现join,事务,成本等问题
    • 分表分为垂直分表,和水平分表
      • 垂直分带来的问题就是表操作的数量要增加
      • 水平分带来的问题就是join,count,order by等操作复杂度
  • K-V存储在数据结构方面比关系型数据有优势
    • 不用管数据结构的变化——no-schema
    • 列式存储具有高压缩比可以节省存储空间,适用于大数据统计某一两个列的访问
    • 全文搜索基本原理是倒排索引
    • 全文索引适配关系型数据库,就是要将对象转换为文档结构数据,可以理解为Obj->JSON
    • 缓存穿透:没有走缓存直接走数据库,数据可能不在
    • 缓存雪崩:同一时间很多缓存过期,并且还没有从DB加载到缓存,导致大量请求在这个时刻全部打到DB上
    • 缓存击穿:和缓存雪崩类似,但是是单个缓存过期
    • 缓存热点:某一热点数据导致缓存扛不住

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

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

相关文章

Java Web应用升级故障案例解析

在一次Java Web应用程序的优化升级过程中,从Tomcat 7.0.109版本升级至8.5.93版本后,尽管在预发布环境中验证无误,但在灰度环境中却发现了一个令人困惑的问题:新日志记录神秘“失踪”。本文深入探讨了这一问题的排查与解决过程&…

激光切割机适用材质有哪些

激光切割机是一种利用激光束对各种材料进行高精度、高速度切割的机器设备。其适用材质广泛,包括但不限于以下两大类: 一、金属材料 不锈钢:激光切割机较容易切割不锈钢薄板,使用高功率YAG激光切割系统,切割不锈钢板的…

大厂面试真题-说一下Mybatis的缓存

首先看一下原理图 Mybatis提供了两种缓存机制:一级缓存(L1 Cache)和二级缓存(L2 Cache),旨在提高数据库查询的性能,减少数据库的访问次数。注意查询的顺序是先二级缓存,再一级缓存。…

死锁的成因与解决方案

目录 死锁的概念与成因 栗子 死锁的情况 哲学家问题 如何避免死锁 必要条件 死锁的解决方案 总结 死锁的概念与成因 多个线程同时被阻塞,他们中的其中一个或者全部都在等待某个资源的释放,导致线程无限期被阻塞,程序无法停止 栗子 我和美女a出去吃饺子,吃饺子要醋和酱油…

高中教辅汇总【35GB】

文章目录 一、资源概览二、资源亮点三、获取方式 一、资源概览 这份教辅资源汇总,精心搜集了高中各学科的海量教辅资料,总容量高达35GB,覆盖了语文、数学、英语、物理、化学、生物、历史、地理、政治等所有必修及选修科目。从基础知识点到难…

ros2 自定义工作空间添加source

新建一个工作空间:ros2 create pkg~~~~~~~~~~~~ colcon build之后 ,在install文件夹里面有一个 setup,bash文件 将这个文件添加到 bashrc gedit .bashrc 这样 在一个新终端中可以直接运行ros2 run package name (包名) 可执行…

针对考研的C语言学习(2019链表大题)

题目解析: 【考】双指针算法,逆置法,归并法。 解析:因为题目要求空间复杂度为O(1),即不能再开辟一条链表,因此我们只能用变量来整体挪动原链表。 第一步先找出中间节点 typedef NODE* Node; Node find_m…

鸿蒙NEXT开发-自定义构建函数(基于最新api12稳定版)

注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

基于Word2Vec和LSTM实现微博评论情感分析

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝,拥有2篇国家级人工智能发明专利。 社区特色…

css动态边框

参考&#xff1a; Clip-path实现按钮流动边框动画_在线clip-path-CSDN博客 https://www.5axxw.com/questions/simple/9ju5yt#google_vignette <div class"bottom-top-item-centent bottom-top-item-left"><vue-seamless-scroll :data"listLeftData&q…

【算法】链表:206.反转链表(easy)

系列专栏 《分治》 《模拟》 《Linux》 目录 1、题目链接 2、题目介绍 3、解法&#xff08;快慢指针&#xff09; 解题步骤&#xff1a; 关键点&#xff1a; 复杂度分析&#xff1a; 4、代码 1、题目链接 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; …

如何用JavaScript编写一个简单的计数器

在网页开发中&#xff0c;计数器是一种常见的功能&#xff0c;它可以帮助我们记录点击次数、显示时间等。下面我将介绍如何在HTML页面中使用JavaScript实现一个基本的计数器。如图&#xff1a; 1、 创建HTML结构 首先&#xff0c;我们需要创建一个基础的HTML结构来容纳我们的计…

自动驾驶系列—深度剖析自动驾驶芯片SoC架构:选型指南与应用实战

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

物联网将如何影响全球商业?

互联网使人们能够交流&#xff0c;企业能够全天候不间断地跨洋跨洲持续运营。它重塑、颠覆并催生了新的产业&#xff0c;改变了人类与世界互动的方式。互联网曾经仅仅是一种方便、快捷、廉价的向世界各地发送信息的方式&#xff0c;而现在&#xff0c;只需打开或关闭任何连接到…

【C++】树形结构的关联式容器:set、map、multiset、multimap的使用

&#x1f33b;个人主页&#xff1a;路飞雪吖~ ✨专栏&#xff1a;C/C 目录 一、set的简单介绍和使用 &#x1f31f;set的介绍 &#x1f525;注意&#xff1a; &#x1f320;小贴士&#xff1a; &#x1f31f;set的使用 ✨set的构造 ✨set的迭代器 ​编辑 ✨set的容量 …

Html--笔记01:使用软件vscode,简介Html5--基础骨架以及标题、段落、图片标签的使用

一.使用VSC--全称&#xff1a;Visual Studio Code vscode用来写html文件&#xff0c;打开文件夹与创建文件夹&#xff1a;①选择文件夹 ②拖拽文件 生成浏览器的html文件的快捷方式&#xff1a; &#xff01;enter 运行代码到网页的方法&#xff1a; 普通方法&#xff1a…

Vue3实现动态菜单功能

文章目录 0.效果演示1.搭建Vue3项目1.1 vite 脚手架创建 Vue3 项目1.2 设置文件别名1.3 安装配置 element-plus1.4 安装配置路由2.登录页面3.后台管理页面3.1 搭建后台框架3.2 左侧菜单栏3.3 header 用户信息3.4 主要内容3.5 footer4.配置静态路由5.记录激活菜单5.1 el-menu 绑…

yub‘s Algorithmic Adventures_Day3

yub’s Algorithmic Adventures_Day3 有序数组的平方 link&#xff1a;977. 有序数组的平方 - 力扣&#xff08;LeetCode&#xff09; 非递减顺序 一个数列中的元素从左到右依次不减&#xff0c;或者说不降序排列. 比如&#xff1a;1233445&#xff0c;12345. 思路分析 如果…

二分查找算法专题(1)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 二分查找算法的介绍 704. 二分查找 34. 在排序数组中查找元素的第一个和 最后一个位置 35. 搜索插入位置 69. x的平…

Java网络通信—UDP

0.小记 1.udp通信不需要建立socket管道&#xff0c;一边只管发&#xff0c;一边只管收 2.客户端&#xff1a;将数据&#xff08;byte&#xff09;打包成包裹&#xff08;DatagramPacket&#xff09;&#xff0c;写上地址&#xff08;IP端口&#xff09;&#xff0c;通过快递站&…