过去三十年,我们从企业应用开始,经历了 PC 互联网、移动互联网的爆发式发展,到如今的产业互联网。在这些不同时代,一直变化的是应用形态,不变的是核心数据的价值。
对于核心数据的存储,首选的方案是使用数据库存储,从互联网初期开始,开源关系型数据库 MySQL 成长成为了数据库存储的第一选择,关系型数据库解决了数据的快速建模,高可靠存储和快速查询,但是关系数据库中的高效查询主要依赖二级索引,如果出现索引无法命中的情况就会出现慢查询,降低客户体验。
由于本身二级索引的实现,这种慢查询在数据库自身中无法彻底解决,只能去优化自身索引结构或者依赖其他系统来实现查询加速,以便减少慢查询对产品能力和可用性的影响。
下面我们以一个社交网络的场景案例来看看如何实现数据库查询加速。
场景
比如在一个社交类型的应用中,需要存储每个用户的状态信息,比如ID、昵称、当前位置、是否在线、手机号码、好友数、签名、隐私特征、标签等等。这类数据具有下列特征:
-
数据规模较大:千万到数十亿之间。
-
数据高可靠:需要保证数据不丢失。
-
高效更新:每个用户的状态值都是需要持续更新,需要高吞吐和高时效性的更新能力。
-
低延迟的灵活查询:需要支持多种字段的随意组合查询,任意列的排序等。
-
高吞吐圈选:当运营的时候需要找出符合某类特征的客户,这时候就需要高吞吐的用户圈选能力。
针对上述的这些要求,只使用单一的数据库系统是很难满足需求的,比如灵活查询和高吞吐圈选等,所以一般的解决方案都是引入搜索系统,比如 Solr、ES 或者自研的搜索系统来实现查询加速:
这种架构使用 MySQL 存储数据,然后使用 Canal 实时同步 MySQL的数据到下游的 ES 中,Canal 作为通道,ES 作为数据查询加速系统。另外,LogStash 也能同步数据,但是是批量方式,做不到实时同步。
这种可以基本满足上述的需求,但是存在两个问题,一是:
-
系统选型匹配度低:Solr、Elasticsearch 是搜索系统,而非数据库系统。数据库系统需要侧重于数据可靠性(不丢不错)和准确性,而搜索系统侧重于相关性和近似结果,这个会导致系统最本质能力和最核心保障点上的差异。
二是在 Elasticsearch 侧会存在一些痛点:
-
异构接口:MySQL 的接口是 SQL,ES 的接口是 Json API ,不同的访问接口给开发带来复杂度和研发周期变长的副作用。
-
能力不对等:对于数据更新操作,ES 存在部分 Update 场景下性能衰减的情况,这个时候 ES 的写入性能会低于 MySQL,这个能力不对等会导致数据堆积在 MySQL,无法被 ES 消费,导致数据无法被用户可见,影响业务。
-
ES运维难度大:ES属于搜索系统,能用起来并不代表可以运维好,如果要运维好需要非常强的专业能力,否则很难解决性能突然衰减、各种 Full GC、负载飙高、压力不均、雪崩、慢查询、打爆系统等等各种问题。
-
慢查询的困扰:使用 ES 的过程中,总会遇到慢查询等性能问题,导致慢查询的原因很多,比如:
-
没使用或者无法使用 Routing 功能导致读放大严重,影响查询性能。
-
Schema 设计不合理,比如数字用字符串做范围查询&