传统关系型数据库(mysql),缓存(redis),elasticsearch
说明
- @author JellyfishMIX - github / blog.jellyfishmix.com
- LICENSE GPL-2.0
存储介质
- 存储介质有一个重要指标 IO(input/output 读写性能/速度)。
内存(ram) 与硬盘
- 硬盘的优点是数据写入后重启/断电不会丢失,可以实现持久化存储,且成本低容量大。缺点是 IO 性能差。
- 内存(ram) 优点是 IO 性能好,缺点是成本高容量小,重启/断电所有存储数据会消失,是不能用作持久化存储的,持久化存储必须用硬盘。
IO 性能
- 传统的关系型数据库(例如 mysql),存储基于硬盘(机械硬盘/SSD 固态硬盘)。机械硬盘由于需要靠物理磁针转动读取数据,IO 性能差。SSD 固态硬盘虽然取消了物理磁针的设计,但本质仍然是硬盘,IO 性能仍然是比内存差。
- 内存(ram) 比机械硬盘 IO 速度快 400 倍左右。
- 内存(ram) 比 SSD 固态硬盘快 30-100 倍左右。
- 内存与硬盘读取速度对比
成本
- 机械硬盘大概 0.1 RMB/GB,SSD 固态硬盘大概 0.4-1+ RMB/GB。内存大概 23 RMB/GB(2022.11 参考价格)。
- 一般游戏本 16GB 内存,1000 GB 机械硬盘或 512 GB SSD 固态硬盘。可以参考这个配置 ram 和硬盘容量对比,感受两者容量与成本的差距。
互联网应用面对的 QPS
- QPS(query per second),每秒请求次数,简单地可以理解为每秒有多少次查询请求。
- 互联网三高(高并发, 高性能, 高可用),toC 应用流量高的几十万 QPS。
关系型数据库(例如 mysql)
- 关系型数据库(例如 mysql,后面用 mysql 代指关系型数据库),由于基于硬盘储存,IO 性能差,单台数据库承受四五千 QPS 压力已经很高了。
- 且由于关系型数据库的特点(例如要支持 ACID(事务的特性)),mysql 很难靠提高机器数量来扩展负载能力。mysql 一台主库负责写入,个位数几台从库负责读取,通过提高机器数量来扩展最多就这样了。为了便于理解,这里先不考虑分库分表等设计。
- 关系型数据库擅长的是数据持久化,并不擅长提供高的 IO 性能。
- 仅靠 mysql 不足以应对互联网三高(高并发、高性能、高可用)。toC 流量高的几十万 QPS。
缓存
- 缓存基于内存存储,IO 性能好。
- toC 或高 QPS 的应用,通常会在 mysql 前面加缓存(例如 redis)。查询的数据如果缓存中有,则直接从缓存中返回(称为命中缓存),不再查询 mysql,减少了对 mysql 的 IO 压力。
- 目前缓存常见的数据结构是 key-value,从缓存中读取时,不是输入多个搜索条件来获得匹配的结果,而是输入一个 key 获得一个 value。每份缓存数据是 value,其标识是 key。
- 如果缓存中没有或数据已过期(未命中缓存),则走兜底逻辑查询 mysql。
- 给缓存设定一定过期时间,并且维护好缓存与数据库一致性,当 mysql 中数据更新时,与缓存做同步(对缓存做更新)。当然引入缓存所带来的缓存与数据库数据一致性问题,也是对技术的挑战。
- 通过引入缓存,把大部分 QPS 负载压力拦截在缓存层面,大大减轻了对 mysql 的压力。同时由于缓存的 IO 性能好,提高了查询的速度,加快了响应时间。
- 由于内存容量有限,一次性缓存所有数据是不可能的,缓存通常只存储高频热点数据(借助 LRU 算法)。
- 缓存设计的一个重要的指标是命中率,关于命中/未命中的概念在上面介绍了。缓存命中率与硬件无关,与编码设计有关(key 的设计,缓存刷新机制等)。
- 为了便于理解,缓存雪崩,缓存击穿,缓存穿透,缓存预热,本地缓存/集中式缓存等概念这里就不提了。
elasticsearch
引入 elasticsearch 的原因
- 尽管前面有了缓存,但是缓存未命中时,还是要走兜底逻辑查询 mysql。在 QPS 很高的情况下,未命中的 QPS 累加起来对 mysql 的压力也是很大的。
- 可以在缓存与 mysql 中间引入一层 elasticsearch,elasticsearch 查询的性能很强,专为搜索场景而生,定位是搜索引擎。当然引入 elasticsearch 所带来的 elasticsearch 与 mysql 数据一致性问题也是对技术的挑战。
- elasticsearch 支持复杂的查询条件和丰富的查询函数,对搜索的支持友好。对比起来,mysql 对复杂的查询条件支持不好,例如多表聚合查询性能差,模糊搜索性能差。
elasticsearch 适用场景
- elasticsearch 适用场景网上有很多介绍,这里只提我了解范围内的。我了解的: qunar 的订单中心,网易新闻的搜索,京东养车的门店列表,车型与车品适配关系就是用 elasticsearch 做查询的。
- elasticsearch 支持根据经纬度查询,有距离计算函数支持,可以做附近门店这样的场景。
- 支持按照自定义脚本对数据项算分,达到对搜索结果做排序的效果。新闻等搜索, 门店列表, 商品列表等场景排序规则可以通过这个功能实现。
- logstash 日志收集 + elasticsearch 检索 + kibana 可视化界面,这是一套 elasticstack 生态提供的日志解决方案,也是很多互联网公司的日志解决方案,日志收集 + 日志分析 + 可视化界面交互。
elasticsearch 的成本
- elasticsearch 的存储基于内存+硬盘。成本比缓存便宜,比 mysql 贵。
- elasticsearch 能存储大量数据,elasticsearch 集群容纳几十 TB (1 TB = 1024 GB)数据是没问题的。对比起来,mysql 单表千万行数据量(大概几十 GB)就很大了,这张表的性能就比较差了,所以 mysql 有了分库分表的设计,这里就不提了。
elasticsearch 的缺点
- elasticsearch 强大的查询性能与对查询友好的支持,基于其复杂的索引机制。但是由于写入时要维护复杂的索引,因此写入性能差。不适合做高频写入的场景。
- 实时计算场景不适合直接用 elasticsearch,因为实时计算不是简单地查询持久化的数据,需要另做优化。