高性能架构—存储高性能

[复制链接]
发表于 2026-1-14 23:52:31 | 显示全部楼层 |阅读模式
1 📊关系型数据库

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

将数据库的读写操纵分散到差别节点

具体逻辑实现如下:

  • 数据库服务器搭建主从集群,一主一从、一主多从都可以
  • 主机负责读写操纵,从机只负责读操纵
  • 主机通过复制将数据同步到主机,每台服务器都存储了全部的业务数据
  • 业务服务器将写操纵发给主机,读操纵发给从机
注意主从集群不是主备集群,两者有本质上的差异,主从代表一种职务关系,主备代表一种更换关系
读写分离逻辑并不复杂,但是要应对数据复制操纵延长带来的复杂度,大概会导致网络分区或延长带来的数据不划一,常见的办理办法如下:

  • 写操纵后的读操纵发送给主机
  • 从机读失败后,再读一次主机——二次读取
  • 关键业务读写指向主机,非关键业务可以接纳读写分离
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方案如下:

  • K-V存储:办理关系型数据库无法存储数据布局——Redis代表
  • 文档数据:办理关系型数据库schema束缚标题——MongoDB
  • 列式数据库:办理大数据场景下I/O标题——HBase
  • 全文搜刮引擎:办理全文搜刮性能标题——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 🎯缓存

某些情况下,单纯靠存储体系的性能的提升是不敷的,如了局景

  • 须要颠末复杂的盘算得出的数据,比如统计体系的pv和uv,用户同时在线数量,如果实时用MySQL来count(*) ,而且使用一张表实时纪录,性能无法包管
  • 读多写少的数据,存储体系故意无力,比如微博,某位大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上
    • 缓存击穿:和缓存雪崩雷同,但是是单个缓存逾期
    • 缓存热门:某一热门数据导致缓存扛不住


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表