介绍Elasticsearch(以下简称ES)是我想写很久的系列,因为它是我离开老家前刚刚接触的最后一项新技术俱乐部。子业务商品搜索改造,商品数据从MySQL迁移到ES。先说说当时为什么会有场景需要参考ES。上面说到是商品库的搜索改造。之前这个子业务规模小,用的人不多,使用场景也比较单一,所以我们只是觉得放在数据库里没问题,因为正常的需求也能满足。当我们需要在数据库中搜索时,很简单,直接做一个模糊查询就可以了selectidfromitemwhereitemNamelike%xxx%但是如果你搜索的关键词有点不对,你可能匹配不到这个产品,比如产品叫:“麻烦我死了,我打不过”和你的搜索关键词是:“恼火”是匹配不上的,其实在意思上还是有些关联的吧?搜索到的用户也是可以接受的,而且随着业务的发展,可能需要搜索产品名称和描述中的关键词,其实这种场景多写一些业务代码就可以满足,但是如果出现了呢?是越来越多的条件?就是业务发展往往是指数级的,当时我们从几十万到几百万用了一年的时间,但是从百万到十亿用了几个月,而且数据量还在增长,不仅业务状况不尽如人意,但是性能并不能通过增加索引来解决。文中先介绍几种主流的数据库存储方式:行存储:同一行的数据物理存储在一起。常见的行数据库系统包括:MySQL、Postgres和MSSQLServer。存储结构:行存储数据库在某些场景下的查询效率:列存储:不同列的值分开存储,同一列的数据存储在一起常见的列式数据库有:Vertica、Paraccel(ActianMatrix、AmazonRedshift)、SybaseIQ、Exasol、Infobright、InfiniDB、MonetDB(VectorWise、ActianVector)、LucidDB、SAPHANA、GoogleDremel、GooglePowerDrill、Druid、kdb+、Hbase、clickhouse。以下几种存储数据库在某些场景下的查询效率:最近接触了Clickhouse,它是一种列式存储。之所以这么快,有以下三个原因:Input/output是针对分析查询的,通常只需要读取表小列的一部分。在列式数据库中,您只能读取所需的数据。例如,如果您只需要读取100列中的5列,这将帮助您减少至少20倍的I/O消耗。由于数据总是打包成批读取,压缩非常容易。同时,数据按列分开存储,也更容易压缩。这进一步减小了I/O的大小。由于I/O减少,这将有助于系统缓存更多数据。注意:这里列出的两个只是为了比较一些特殊场景下效率低下的情况,也是为了以后es的速度和数据结构做铺垫。事实上,像Clickhouse这样的数据库只适用于某些特定场景,大部分场景还得是基于行的。数据库。如果大家有兴趣,我可以稍后来Clickhouse分享(虽然我还在看)。接下来说说另一种存储结构:文档其实在某种程度上和列式文档有一定的相似之处。是的,大家回头看看就知道了{"name":"name""size":24"sex':"male"}上面我介绍了几种常用的存储结构来说明es的场景,以及es的一些优点,我们都知道数据库有索引,而且速度也很快,那么es是怎么存储数据的,它的索引又是怎么样的呢?倒排索引,顾名思义就是通过Value找到key,其实不是和我们传统的根据key查找value的方式一样,比如上面的数据,我们可以看到es会创建如下索引:NameinvertedindexSizeinvertedindexSexinvertedindex可以看到有Term和Term两个概念所有倒排列表中的PostingList,Posting列表是一个int数组,里面存放的是所有匹配某个term的文档id,如何根据value找到key呢,比如我想找到所有的genders的话是男孩,Sex倒排索引的Posting列表可以告诉我是id为1和3的人,然后通过Name这个词,可以看出1的人是aobing,3的人是egg,依此类推。所有信息。Es的查询速度是很快的,但是目前看来用Term的形式搜索好像还不快?为什么?这将引出接下来的两个概念,TermDictionary和TermIndex。术语词典:这个很容易理解。正如我上面所说,它由各种术语组成。为了方便查找词条,es对所有词条进行了排序,采用二分法查找。TremIndex:它的存在是为了优化术语词典。想一想,那么多词条,光靠排序是排不出来的。如果想快速的放到内存中,但是es的数据量级往往非常大,那么放到Disk中呢?磁盘寻址会很慢,那么如何减少磁盘的寻址开销呢?TermIndex其实和新华字典是一样的。每个字母以什么开头,然后按照拼音排序。这就是三者的关系,非常经典的一张图,基本上学es的人应该都看过。TermIndex存储了一些前缀和映射关系,可以大大减少随机磁盘读取的次数。巧妙压缩有没有发现这个设计很巧妙呢?而且es的检索速度比mysql快很多。当你使用MySQL的时候,你会发现索引其实和TremDictionary是一样的,只不过es多了一个Index。一层筛选,少随机次数。另外要提的一点是Term索引在磁盘上的存储结构。这个在我的历史文章里已经写过了,我当时就踩了他的坑。鉴于篇幅,今天就简单介绍一下。大家可以把FST理解为一种压缩技术。最简单的方法是压缩字节。上面说了Term索引放不下内存,那压缩呢?我不会展开细节。下面这篇文章解释的很详细,因为这是一门科普,后面会出一篇文章介绍集群的细节和压缩。链接:https://cs.nyu.edu/~mohri/pub/fla.pdf接下来介绍es中一些我认为很重要的概念:在nearreal-time(NRT)ES中写入的数据将是先写入到内存bufferr中(数据在buffer中是查不到的),然后默认每秒刷新一次到os缓存中。在操作系统中,磁盘文件其实有一个东西叫做oscache,操作系统缓存,也就是说数据在写入磁盘文件之前,会先进入oscache,在操作系统层面先进入一个内存缓存。只要buffer中的数据被刷新并flush到os缓存中,就意味着可以搜索到数据了。默认是1秒刷新一次,所以es是准实时的,因为写入的数据1秒后才能看到。为什么要这样设计?我们来看看如果不这样设计会发生什么:如果写入缓存,然后直接刷到硬盘,其实会消耗很多资源,会去硬盘写入后立即读取,并发量将难以增加。可想而知,写几万QPS的时候,还要查询磁盘。多么灾难级的场面。es是怎么做到的?数据被写入缓冲区,然后每秒刷新到缓存中。这个时候就可以搜索到,所以准实时,不实时就是这一秒的差距。这种设计可以降低磁盘压力。缩减不说,写入和查询都不受影响,并发上去。分词文本分析(Analysis)是将全文转换成一系列词(term/token)的过程,也称为分词。当文档被索引时,可以为每个术语创建倒排索引。倒排索引的过程是通过分析器将文档一个一个地划分为term,每个term指向包含该term的文档集合。分词是es的一个核心功能,但是它默认的分词其实对中文并不友好。比如我搜索China,它可能会同时搜索Chinese和Chinese,但是China是一个词汇,不应该这样划分。现在可以用机器学习算法来分词,也有一些中文分词插件,比如ik分词器。他内置的分词器在英文场景下更容易使用。裂脑问题实际上存在于集群中部署的机器上。假设现在es集群有两个节点,节点1是对外提供服务的master节点,节点2是副本分片节点。现在由于网络原因两个节点都断开了,你会发现什么呢?主节点发现自己是主节点,继续对外提供服务,副本节点发现没有主节点。如果不可用,他也被迫成为主节点(狗头)。对于调用者来说,很难发现差异,除非对比数据,而且我之前在生产环境中也出现过脑裂的情况,而且是用户反馈,因为有时候他在搜索的时候可以搜索到产品一句话,有时候不行,因为请求是在不同的节点上命中的。我们一般怎么解决呢?elasticsearch.yml中有一个配置:discovery.zen.minimum_master_nodes这个参数决定了master选择过程中需要通信多少个节点。默认为1,设置原则为集群节点数/2+1个。如果你的集群有三个节点,那么这个参数设置为3/2+1=2,那么一个挂了,另外两个可以通信,所以你可以选择一个master,如果你的集群有三个节点,这个参数还是2,但是如果发现只有一个节点和自己通信,就不会选举master了。但这也有缺点。当只有两个节点时,挂一个相当于服务不可用。因此,最好保证集群的节点数在三个以上。Elasticsearch的选举算法是基于Bully选举算法。简单来说,在Bully算法中,每个节点都有一个编号,只有编号最大的存活节点才能成为主节点。Bully算法的具体过程如下:当任一进程P发现master没有响应请求时,发起一次选举。选举过程如下:(1)P进程向所有编号比它大的进程发送选举消息;(2)如果没有人响应,则P获胜,成为master;(3)如果编号较大的进程响应,响应者接管选举工作,P的工作完成。在任何时刻,一个进程只能接收到比它小的进程的选举消息。当消息到达时,接收方向发送方发送一个OK消息,表明它正在运行并接管工作。最终除了一个进程之外的所有进程都放弃了,而这个进程就是新的协调器,然后它向所有其他进程发送一条胜利消息,通知它们新的协调器已经诞生。其实ELK提到ES,经常被ELK三兄弟提到。最后再说一下另外两个兄弟。L代表Logstash,Logstash是一个具有实时管道能力的开源数据收集引擎。Logstash可以动态统一来自不同来源的数据,并将数据规范化到您选择的目的地。Logstash管道有两个必需元素:输入和输出,以及一个可选元素:过滤器。输入插件使用来自源的数据,过滤插件根据您的期望修改数据,输出插件将数据写入目的地。K是Kibana。Kibana是Elasticsearch的一个开源分析和可视化平台,用于搜索和查看交互存储在Elasticsearch索引中的数据。使用Kibana,您可以通过各种图表进行高级数据分析和展示。Kibana使大数据更易于理解。操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard),实时显示Elasticsearch查询动态。设置Kibana非常简单,无需编码或额外的基础设施,您可以在几分钟内完成Kibana安装并启动Elasticsearch索引监控。综上所述,这只是简单介绍了es的一些基础知识,还没有讲到它的压缩算法、聚类、分片、副本复制等,下篇文章再介绍。
