前言
“这个世界已然被数据淹没。多年来,我们系统间流转和产生的大量数据已让我们不知所措。 现有的技术都集中在如何解决数据仓库存储以及如何结构化这些数据。 这些看上去都挺美好,直到你实际需要基于这些数据实时做决策分析的时候才发现根本不是那么一回事。Elasticsearch是一个分布式、可扩展、实时的搜索与数据分析引擎。无论你是需要全文搜索,还是结构化数据的实时统计,或者两者结合,Elasticsearch不仅仅只是全文搜索,我们还将介绍结构化搜索、数据分析、复杂的人类语言处理、地理位置和对象间关联关系等”。 -- Elasticsearch: 权威指南 » 前言
上边一段摘录自Elasticsearch: 权威指南
,告诉了我们ES拥有的超强能力。这个系列文章主要是根据在工作中的实战总结,最终目的是探讨一下如何根据现有的业务需求平滑的迁移到ES(使用java技术栈),去弥补关系型数据库的局限性,提高我们的处理数据的能力。
本系列暂时规划为四个部分
- 第一部分:谈谈为什么我们需要使用ES,以及相关基本概念
- 第二部分:我们讨论Mysql -> ES数据的迁移策略、技术选型,以及在各种场景下选择的同步策略。
- 第三部分: 我们将实现spring boot与ES的集成,以及使用ES提供的API去“翻译sql”
- 第四部分:我们以前边的技术基础,去尝试解决一个现实中RDBMS单表数据量千万级,同时还有多表join的情况下如何使用ES去解决这个令人头痛的难题。
话不多说,我们先来看为什么需要使用ES。
一、为什么需要 Elasticsearch
1、快,就是快
我们使用ES最主要的原因就是因为ES速度快。特别是当数据量到达千万级以上的时候,关系型数据库单表无论是通过增加索引、分库分表来优化,最终能够优化的效果往往不如人意(且分库分表复杂度较高),而ES可以轻松hold住千万、亿级数据量。
为了达到这样的速度,ES使用了有限状态转换器实现了用于全文检索的倒排索引,实现了用于存储数值数据和地理位置数据的BKD树,以及用于分析的列存储。并且由于ES默认就是将所有的字段全部建立索引,所以我们在查询的时候可以实时地检索到数据。
2、不只是全文检索
这一点也是我们使用ES很重要的原因,在传统关系型数据库中,我们很多使用需要采用模糊查询的方式来获取想要的数据。
select * from author where name like '%鲁迅%'.
在数据量较大的时候,就算我们在name字段上建立索引,上边的SQL也是不会走索引的(不符合最左前缀原则),将执行全表扫描,性能可想而知。 但是若在ES中实现上述的查询则很简单,由于ES采用的存储、索引策略,可以实时的查询到想要的结果。
但是这里无论是精确查询还是模糊查询,本质上来时“传统关系型数据库”的思维,ES本质上是一个搜索、分析引擎,搜索引擎从一个抽象的角度来讲,它做了三件事:收集数据、建立数据索引、相关度排名。在ES中收集数据是有我们来完成的,1、比如将关系型数据库中的数据同步到ES中;2、然后ES将同步的数据建立索引,方便之后的查询;3、最后一步也是最重要的一步,也就是相关度排名,如此大量的数据,不会是所有都拥有相同的重要程度,所以排名的好坏对于搜索引擎来说很重要,它决定了搜索质量的高低。
在ES中也是这样,我们在使用查询的时候不仅仅是将数据查询出来,ES还能将关键词检索到的数据根据相关度排名。这也更符合我们人类的思维方式,假设我们使用关键词“鲁迅”不是为了查询所有包含鲁迅关键词的文章、报道。而是希望把大家都认为有关鲁迅这个人最重要的作品、个人背景、人生经历、历史评价等等信息根据相关度排序检索出来。
所以这也是传统关系型数据库不能提供的功能,它”似乎“更能懂得我们真正想要的结果。
3、完整的生态系统
ElasticSearch是Elastic公司的核心技术栈,他们还包括Logstash、Filebeat、Kibana等等。
我们可以使用ES提供的技术栈,实现各种目的,比如典型的采用ELK + Filebeat搭建一套分布式日志采集系统,将各个微服务的日志通过Filebeat收集推送到Logstash管道做处理,然后logstash推送给ES,最终Kibana展示,查询日志。
4、可扩展性
对于大多数的数据库而言,通常需要对应用程序进行非常大的改动,才能利用上横向扩容的新增资源。 与之相反的是,ElastiSearch天生就是分布式的 ,在ES集群中,我们可以随时增加、摘除节点,集群将会重新平均分布所有的数据。它知道如何通过管理多节点来提高扩容性和可用性。 这也意味着你的应用无需关注这个问题。
当然,任何技术都有其合适的应用场景,ES不支持事务、同时更适合查多改少的场景,所以我们在选择技术栈的时候需要注意这些限制。
二、核心概念
无论我们是在开发、维护ES集群的时候,弄清楚ES中的核心概念都是重要的,下面我们采用“从小到大”的方式来介绍ES的核心概念。
1、字段(Fields)
字段是ES中最小的独立单元数据,每一个字段有自己的数据类型(可以自己定义覆盖ES自动设置的数据类型),我们还可以对单个字段设置是否分析、分词器等等。
核心的数据类型有string、Numeric、DateDate、Boolean、Binary、Range等等,复杂类型有Object、Nested,详细的可以参考官方的介绍
2、文档(Documents)
在ES中文档的概念相当于RDBMS中的一行数据,不同的是在ES中文档的存储是直接使用json格式存储的(也就是可以嵌套),而不是像RDBMS中把数据"压平"了存储,这一点也是Nosql和关系型数据库比较大的区别。
下面是一个文档的例子
{
"_id": 3,
“_type”: [“your index type”],
“_index”: [“your index name”],
"_source":{
"age": 28,
"name": ["daniel”],
"year":1989,
}
}
3、映射(Mapping)
”Mapping is the process of defining how a document, and the fields it contains, are stored and indexed.“
也就是Mapping是定义文档和字段如何存储和索引,使用Mapping可以定义下面这些信息
- 哪些字段应该作为全文索引
- 哪些字段包括numbers, dates, geolocations.
- 时间类型的格式
- 定义规则控制动态增加字段的mapping
4、索引(Index)
在ES中是最大的数据存储概念,它是由许多具有相同特征的文档组成的一个集合。 由于在ES7.0之后逐渐废除Type类型,所以Index从”数据库“的概念变成了实际上的”表“概念,我们可以把它近似地当成RDBMS中的表,但是要注意Index只是一个逻辑上的概念,真实的数据是分开存储在各个分片中的。
5、分片(Shards)
这里需要多说几句,搞清楚分片对于理解ES集群(扩容、容错、路由)原理是很重要的。
首先,每个分片都是一个Lucene索引实例,我们可以将其视作一个独立的搜索引擎,它能够对Elasticsearch集群中的数据子集进行索引并处理相关查询。
分片分为两种:主分片(Primary Shard)、副本分片(Replica Shard)
-
主分片:由于所有的数据都会在主分片中存储,所以主分片决定了文档存储数量的上限,但是一个索引的主分片数在创建时一旦指定,那么主分片的数量就不能改变,这是因为当索引一个文档时,它是通过其主键(默认)Hash到对应的主分片上(类似于RDBMS分库分表路由策略),所以我们一旦修改主分片数量,那么将无法定位到具体的主分片上。在mapping时我们可以设置
number_of_shards
值,最大值默认为1024。 -
副本分片:我们可以为一个主分片根据实际的硬件资源指定任意数量的副本分片,上边已经说过,每个分片都可以处理查询,所以我们可以增加副本分片的资源(相应硬件资源提升)来提升系统的处理能力。同样,在mapping时,可以通过
number_of_replicas
参数来设置每个主分片的副本分片数量
但是要注意,为了容错(节点主机宕机导致数据丢失),主分片和副本分片不能在同一个节点上,防止节点宕机导致部分数据丢失。
6、实例和节点(Instances and Nodes)
”A node is a running instance of Elasticsearch which belongs to a cluster”
节点也就是运行的ES实例,它隶属于某一个集群。通常来说,我们在一个服务器上边部署一个节点,但有时候为了测试集群,也可以在单台服务器上启动多个节点来测试。假设当我们启动一个节点想加入已经存在的一个集群中时,可以在配置文件中配置改集群的名称,以及通信的ip + port
,ES会自动通过“单点传送”的方式来自动发现集群并尝试加入这个集群。
节点分为下面几种类型:
- Master-eligible node:负责管理和配置集群,例如增加、删除节点相关动作。
- Data node:文档实际上就存储在数据节点,负责执行相关的操作, 例如CRUD、搜索、聚合等等操作
- Coordinating node:用于处理请求的路由、查询结果集的汇总、智能负载均衡..
- Ingest node:用于文档在indexing之前进行预处理
- Machine learning node:主要用于机器学习的任务,但是需要
Basic License
。
关于ES节点的详细介绍,可以参考官方文档
7、集群(Cluster)
- 在ES中,集群是由一个或多个ES节点组成的,每个集群都有一个唯一的名称/标识符,用作节点加入集群的依据。
- 每一个集群中有一个Master节点,若是这个Master节点挂了,集群可以用其他的节点代替。 在ES中还支持跨集群复制、跨集群检索等等功能,详细的可以参考Cross-cluster replication,Search across clusters
在上边的两节,我们知道了ES拥有的超强数据处理能力,也了解了ES一些基础的概念。因为网上关于ES使用的倒序索引原理分析已经比较多了,我这里就不在重新描述其中的细节了,具体原理推荐大家一篇文章参考:时间序列数据库的秘密 (2)——索引