从零开始学架构--存储高性能

第4章 存储高性能

4.1 关系数据库

4.1.1 读写分离

基本实现

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

读写分离需要应对复制延带来的复杂性,以Mysql为例,主从复制延迟可能达到1s,常用方法如下

  1. 写操作后的读操作指定发给数据库主机
  2. 读从机失败后再读一次主机
  3. 关键业务读写操作全部指向主机,非关键业务采用读写分离

4.1.2 分库分表

数据量过大会使单台服务器的存储能力成为系统瓶颈

  1. 数据量太大,读写性能下降,及时有索引,索引也会变得很大,性能下降
  2. 数据文件会变得很大,数据库备份和恢复需要耗费很长时间
  3. 数据文件越大,极端情况下丢数据的风险越高

常见分库分表的方案如下

方案一. 分库

业务分库指按业务模块将数据进行拆分。例如将一个电商系统的数据库,拆分为用户、商品、订单三台数据库

虽然业务分库能分散存储和访问压力,但同时带来新的问题

  1. 无法像单库进行方便的join操作
  2. 事务问题
  3. 成本问题 占用的服务器数量上升

方案二. 分表

a. 垂直分表

垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。

b. 水平分表

水平分表适合行数特别大的表,如果单表行数超过5000万(该数字可做参考)就必须分表。 水平分表会引入很多复杂性,主要表现在

  1. 路由 ,需要增加路由算法计算某条数据具体属于哪个切分后的子表
    1. 范围路由, 例如按照用户id进行分段,以1~1000w为一张子表
      1. 优点:可以随数据增加而平滑地扩充新表
      2. 缺点:数据分布不均匀
    2. Hash路由 根据某个列的值进行Hash运算,根据结果分散到不同的表中
      1. 优点:表分布比较均匀
      2. 缺点:扩充新表很麻烦,所有数据都要重分布
    3. 配置路由 用一张独立的路由表来记录记录的分布信息
      1. 优点:设计简单,扩充表灵活
      2. 缺点:必须多查询一次,影响性能;路由表过大也会成为性能瓶颈
  2. join操作 需要在代码中进行多次join,然后结果合并
  3. count()操作
    1. count()相加 在代码中处理
    2. 记录数表
  4. 排序操作 只能在代码中处理

4.1.3 实现方法

可应用Sharding-JDBC方便程序进行处理

4.2 NoSql

关系数据库缺点

  1. 存储的是行记录,无法存储数据结构
  2. schema扩展很不方便
  3. 大数据场景下I/O较高
  4. 全文搜索功能比较弱

4.2.1 K-V存储

解决关系数据库无法存储数据结构问题,以Redis为代表

4.2.2 文档数据库

最大的特点是no-schema,可以存储和读取任意的数据,目前绝大部分文档数据库存储的数据格式是JSON。 文档数据库并不能完全取代关系数据库,更多时候是作为补充。

文档数据库优势

  1. 新增字段简单
  2. 历史数据不会出错
  3. 可以很容易存储复杂数据

主要缺点

  1. 不支持事务
  2. 无法实现关系数据库的join操作

4.2.3 列式数据库

列式数据库是按照列来存储数据的数据库,传统关系数据库是按行来存储数据的。

列式数据库优势

  1. 业务同时读取多个列时效率高
  2. 能够一次性完成对一行中多个列的写操作,保证了针对行数据写操作的原子性和一致性
  3. 压缩率高,节省存储空间

缺点

  1. 随机写效率远低于行式存储的效率
  2. 高压缩率情况下数据更新效率低

一般列式存储应用在离线大数据分析和统计场景中,因为这种场景主要针对部分列进行操作,且 数据写入后就无须再更新删除

4.2.4 全文搜索引擎

基本原理为倒排索引,典型代表ES

4.3 缓存

缓存的基本原理就是将可能重复使用的数据放到内存中,一次生成,多次使用,避免每次使用都去访问存储系统

4.3.1 缓存穿透

指缓存没有发挥作用,业务系统虽然去缓存中查询数据,但缓存中没有数据,系统需要再次去存储系统中查询。 通常有2中情况

  1. 存储数据不存在

通常情况下,业务上读取不存在数据的请求量不会太大,如果出现恶意访问情况,可以直接设置一个 默认值(可以是空值)存入缓存中。

  1. 生成缓存数据需要耗费大量时间或资源

优化系统效率,识别恶意访问并禁止

4.3.1 缓存雪崩

缓存雪崩指当缓存大规模失效后引起系统性能急剧下降的情况。常见解决方案有

  1. 更新锁

对魂村更新操作进行加锁保护,保证只有一个线程能进行缓存更新,未能获取更新锁的线程要么等待 锁释放后重新读取缓存,要么返回空值或默认值

  1. 后台更新

由后台线程来更新缓存,而不是由业务线程来更新缓存,缓存本身的有限期设置为永久。

4.3.3 缓存热点

缓存热点的解决方案就是复制多分缓存,将请求分散到多个缓存服务器上,减轻缓存热点导致 的单台缓存服务器的压力

本文由博客一文多发平台 OpenWrite 发布!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值