简介
以前虽然也学过Elasticsearch,对它也了解一点点,但是总是不能用自己的话,去描述她。这个周又学了一下,从来没有这么清楚说清楚她是干啥的、她的原理、她的本质。
她是干啥的?Elasticsearch是用来做全文搜索的。
她的原理?Elasticsearch是通过分词、倒排索引实现全文搜索。
她的本质?Elasticsearch本质是搜索,是用来做搜索的,而不是用来做存储的。
突然想起了多年前被问到过的一个面试题,也许对方只是随便一问,但是我却被问的不知所措。mysql和mongodb的区别,mysql是关系型数据库,mongodb是非关系型数据库,既然是数据库就是用来存储数据。引申mongodb,redis,hbase 三者都是nosql数据库,他们的最大区别和不同定位,Redis定位在"快",HBase定位于"大",mongodb定位在"灵活",跑题了。
可以用三个词来形容Elasticsearch:搜索、分词、倒排索引。Elasticsearch搜索功能是通过分词、倒排索引来实现的。
分词
何为分词?把一段文本,拆分成一个个的词。比如“北京故宫”这句话,经过分词处理器处理,可能会输出“北京 故宫 北京故宫”。当然不同的分词器会分出不容的词,同一个分词器,不同的分词规则,也可能会分出不同的词。也可以把新的词加入分词库。
倒排索引
何为倒排索引?由词索引(查找)到文章。比如以下文档:
文章ID | 文章内容 |
1 | 北京故宫是中国明清两代的皇家宫殿 |
2 | 位于北京中轴线的中心 |
3 | 北京故宫以三大殿为中心 |
4 | 故宫又称紫禁城 |
以上4篇文章经过分词后,就会建立关键词与文章ID的对应关系,这就是倒排索引,正排索引一般是根据ID查询文章内容,倒排索引正好与正排索引反过来了。
倒排索引
关键词 | 文章ID |
北京 | 1,2,3 |
故宫 | 1,3,4 |
北京故宫 | 1,3 |
搜索过程:关键词 --》 文章ID集合 --》文章详情。
查询速度
文档每时每刻都在不停的被生产出来,所以文档的数量会越来越多,一般都是海量级别的。但是关键词却是有限的,关键词就是汉字+词语+新造字+新造词构成的,关键词最多也就百万、千万级别的,比起海量的文档,肯定少很多,所以查询速度会很快。
搜索的关键词也是被分词过的,所以查询出来的文档肯定会有一个score的字段来标识相关度,这个也非常好理解。因为不一定是精确匹配搜索的关键词,可以根据score进行排序,score大的相关度就会高,排序也理应在前。
客户端、服务端通过http restful进行通信
创建数据索引、查询索引,索引中数据的增、删、改、查,客户端、服务器都是通过http restful的方式进行通信的。这一点跟mysql的驱动、mongodb的驱动,我觉得是有差异的。mysql是sql创建、查询数据。mongodb也是通过自己语法的sql来创建、查询数据的。
ES核心概念
1)Cluster:集群。
ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。
2)Node:节点。
形成集群的每个服务器称为节点。
3)Shard:分片。
当有大量的文档时,由于内存的限制、磁盘处理能力不足、无法足够快的响应客户端的请求等,一个节点可能不够。这种情况下,数据可以分为较小的分片。每个分片放到不同的服务器上。
当你查询的索引分布在多个分片上时,ES会把查询发送给每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。即:这个过程对用户来说是透明的。
4)Replia:副本。
为提高查询吞吐量或实现高可用性,可以使用分片副本。
副本是一个分片的精确复制,每个分片可以有零个或多个副本。ES中可以有许多相同的分片,其中之一被选择更改索引操作,这种特殊的分片称为主分片。
当主分片丢失时,如:该分片所在的数据不可用时,集群将副本提升为新的主分片。
5)全文检索。
全文检索就是对一篇文章进行索引,可以根据关键字搜索,类似于mysql里的like语句。
全文索引就是把内容根据词的意义进行分词,然后分别创建索引,例如”你们的激情是因为什么事情来的” 可能会被分词成:“你们“,”激情“,“什么事情“,”来“ 等token,这样当你搜索“你们” 或者 “激情” 都会把这句搜出来。
1.6 ES数据架构的主要概念(与关系数据库Mysql对比)
(1)关系型数据库中的数据库(DataBase),等价于ES中的索引(Index)
(2)一个数据库下面有N张表(Table),等价于1个索引Index下面有N多类型(Type)。
新版本把Type的概念去掉了,个人理解,Elastic Search本身就是搜索海量的数据,本身就需要分片才能实现完整的存储,如果一个Index又包含多个Type,每个Type肯定都是海量级别的数据,那么肯定需要更多的分片,才能处理一个Index下的所有Type数据。假如一个Index下有用户、文章两种Type,存储文章需要5个分片,存储用户需要2个分片。如果是Index-->Type-->Document,那么存储用户、文章数据可能需要5+2=7个分片,来存储这些数据,而且文章、用户要平均分配到7个分片上,查询的时候,每次都需要查询这7个分片的数据,并合并结果返回。如果是Index-->Document,那么存储用户数据需要2个分片,查询的时候,只需要查询这2个分片的数据,存储文档数据需要5个分片,查询的时候,只需要查询这5个分片的数据,,耗费的时间和计算量肯定低于7个分片。所以去掉Type的概念,个人认为会降低通信协调时间、降低计算量、提高响应时间。
(3)一个数据库表(Table)下的数据由多行(ROW)多列(column,属性)组成,等价于1个Type由多个文档(Document)和多Field组成。
(4)在一个关系型数据库里面,schema定义了表、每个表的字段,还有表和字段之间的关系。 与之对应的,在ES中:Mapping定义索引下的Type的字段处理规则,即索引如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。
(5)在数据库中的增insert、删delete、改update、查search操作等价于ES中的增PUT/POST、删Delete、改_update、查GET.
扩展阅读