ElasticSearch架构反向思路

简介: 我分析一个系统的设计思路,往往不是一开始就去看看这个系统的设计文档或者源代码,而是去看系统的基本介绍,特别是框架类的功能详细介绍,然后根据介绍可以大概了解这样一个系统用来解决什么问题,有哪些特色,然后基于自己对这些问题的想法,根据自己的经验来同样设计一个系统,看包含哪些内容,使用哪些架构模式和思路,然后带着自己设计的东西再去看另一个系统的设计思路,可能再更加清楚,也会反思自己的设计是否哪些地方存在问题,可以加以改进。

我曾经在多个场合说过,我分析一个系统的设计思路,往往不是一开始就去看看这个系统的设计文档或者源代码,而是去看系统的基本介绍,特别是框架类的功能详细介绍,然后根据介绍可以大概了解这样一个系统用来解决什么问题,有哪些特色,然后基于自己对这些问题的想法,根据自己的经验来同样设计一个系统,看包含哪些内容,使用哪些架构模式和思路,然后带着自己设计的东西再去看另一个系统的设计思路,可能再更加清楚,也会反思自己的设计是否哪些地方存在问题,可以加以改进。

最近正好准备玩ElasticSearch,本来在2013年就想玩这个,但由于工作原因耽误了,现在又翻出来看看有什么好玩的,下面就详细地记录了我对ElasticSearch的反向架构思考。顺便补充一句,目前用来研究的ElasticSearch的版本号是6.3

先来看看一份对ElasticSearch比较典型的介绍:

Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
 
但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
 
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
 
不过,Elasticsearch不仅仅是Lucene和全文搜索,我们还能这样去描述它:
 
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。
 
上手Elasticsearch非常容易。它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它开箱即用(安装即可使用),只需很少的学习既可在生产环境中使用。
 
随着你对Elasticsearch的理解加深,你可以根据不同的问题领域定制Elasticsearch的高级特性,这一切都是可配置的,并且配置非常灵活。

幸亏以前使用过Lucene做IDE底层项目模型关系的管理,对Lucene还算比较熟悉,否则还得先去看看Lucene的功能和用法。

从上面的介绍可以看出几个关键内容:

  1. Lucene在做索引的时候本身就有存储功能,所以存储这个东西是天然就有的,反而不用花时间考虑。
  2. 性能是一个比较关键的东西,特别是要做实时引擎,怎么保证高性能。
  3. ElasticSearch是一个分布式的系统,那么必然存在多结点通讯,协作等问题,比如使用ZooKeeper之类的系统进行注册和协同,当然也保不齐他自己玩一套。
  4. 既然是分布式系统,那么数据存储就不可能完全单机化,也就是存在Sharding的情况,如何Sharding,如何同步,在查找结果的时候,如何聚合。
  5. 分布式系统,只要涉及到数据更新,必然存在数据不一致问题,怎么解决。
  6. 由于索引本身原因,一旦出现Sharding,就很难做联合的查询,这个应该不能实现的,至少说不可能很简单得实现。
  7. 有一个网络层或者说对外服务接口层,用来进行交互,看介绍,支持多种协议,比如Client直接调用,或者是Restful风格。
  8. 参考服务接口层,还允许很多地方进行配置,那么很显然,应该是使用了类似于插件的技术来支持很多功能。

我的习惯是从使用者角度来倒推系统架构

  1. 对外服务,称为Interface,这个其实还相对简单,应该提供两个基本功能,即BuildIndex(不一定要区分Create和Update,但Delete肯定要有)和Query(应该基于主Key和Condition两种查询),把这两个基本接口设计好,然后在上面加不同的封装或者通过Netty之类网络架构提供Rest服务,也可能基于Stub类似的机制提供RPC调用。
  2. 查询功能,是采用SQL还是Query模型的方式,我更倾向于后者,因为关联查询等很多功能是无法提供的,SQL校验会是比较麻烦的事情。
  3. 不管是BuildIndex还是Query,肯定要找到一台机器或者多台机器进行处理,由于这是一个分布式系统,而且还支持Sharding,那么可以肯定,需要分组,即Group,一个Group中包括若干个Node,用来支持服务。
  4. 怎么分组,正常可能是分两级,一种是基于模型定义的,比如对于某一些数据,象商品,用户这些数据可能分成一类数据对应一个Group来处理,这种处理比较直观,也简单。也就是说每一类模型会对应一个Group,而一个Group可能对着多个模型,特别是数据相对较少的时候。还有一种就是Sharding,通常来说,是对一类数据,根据某一个或者几个字段(Field),进行条件分组,也就说在这种分组情况下,每个Node的数据都是不全的,需要将多个Node合并在一起,才会形成完整的数据集。这两种分组都需要支持的。
  5. 对于BuildIndex和Query,当系统分成多个Group的时候,肯定要有一个Router的概念,即一个BuildIndex或者Query服务来的时候,得找到相应的Group(应该是Group下的Node),因为Lucene中的Document和Term特性,应该需要设计一个类似于数据库中的Table模型,一个Group负责处理多个Table。在BuildIndex和Query请求里,1. 必须带有Table的准确定义,比如User,Item等。
    按照前面的思考,Group是肯定应该存在的,但是每个Group否需要一个MasterNode呢?
  6. 当一个Query请求定义清楚后,会以路由的方式找到一个Group,如果数据量不大的话,一个Group中的Node应该是数据对等的,那么请求落到任何一个Node上都可以得到相应的结果。如果数据量很大,出现Sharding,就分两种情况,一种是Query中的条件,能够符合Sharding的定义条件,那么落到任何一个Node上以后,通过转发的方式,总是可以拿到请求,应该有两种实现方式,一是请求发到某个Node上以后,由Node分析后,将可以导向的Node返回,由请求方再次将指定的Node发送请求,二是任意Node直接向可以导向的Node转发请求,并拿到结果后返回给请求方,第二种对客户端友好,但如果数据量大的话,可能不太合适。还有一种情况就是,如果Query中的条件不能够符合Sharding定义,那么就出现类似于数据库查询的FullScan,由收到的Node将请求转发给相应的Node,构成全量搜索,然后由该Node合并后,返回。如果这样看,最好的方式还是Node统一处理,对请求方更友好一些,也更一致。
  7. 当BuildIndex的时候,必然是发给一个Node,由其完成Index后,再同步给其它Node,此时同步,是有一个MasterNode还是没有好呢?感觉设计一个MasterNode可能使得逻辑更简单。即大的Group里,MasterNode主要负责协作和BuildIndex同步,而Query则可以尽可能地落到DataNode侧。
  8. 虽然有了MasterNode,但仍然是可以将BuildIndex请求发给DataNode,由DataNode转发给MasterNode,这样会更加简单和友好。
  9. 考虑到BuildIndex和Query会有不同步的情况,那么怎么减少这种不一致性呢?如果由MasterNode或者指定的一个DataNode进行BuildIndex的时候,对其它Node的Query都会产生数据不一致性问题。假设由MasterNode给其它DataNode全部上锁,此时查询性能急速下降,这种方法不是非常建议,容易形成堵塞,不过如果数据很少更新,而且对数据一致性有较高要求,也可以支持,那里可能得在这个地方允许用户配置一致性优先还是性能优先了。如果是后者的话,按照我对Lucene的了解,此时每个DataNode最好有一个DiskStore和一个MemoryStore,查询时将两者合并查询,这样在保证高性能的情况下可以减少不一致性。或者更灵活一点,允许在BuildIndex的时候允许指定是否加锁,但这样可能会增加复杂度,需要再思考一下。
  10. 同样是数据不一致问题,除了上面的内容以外,还需要使用Log,这样MasterNode先记录Log,然后进行Index,同时分发给DataNode,DataNode也是先记录Log,这样一旦出现问题,可以随时在启动时从Log处Redo。
  11. 维护和管理功能:动态扩容,Reindex(扩容时肯定要用到),启动时先与多个DataNode同步Log,再根据Log进行Redo,保证数据的一致性。
  12. 插件化设计没什么难点,不管是类似于OSGi,还是说直接写一个Plugin的接口,然后加一个PluginManager都可以解决问题。但关键是Plugin需要在哪些情况下调用,以便让开发者可以更多的加入自己的定制。我猜可能有以下几个点:网络请求的Before和After处理(比如支持不同的数据模型,不同的安全检查等,记录日志,流量控制等),启动后的After处理(比如对Log进行Check,以便Redo),BuildIndex和Query的Before和After处理(其实就可以通过这个扩展来处理数据同步的问题)。
  13. 上面说的插件化设计并不难,但是否使用统一的Plugin接口,还是分开,需要考虑一下,毕竟可以提供扩展点的地方太多了。如果是我设计,大概是三大级继承,最顶层的有一个Plugin或者Extension的接口,提供Name,Desription,Dependecy等内容的定义,这个和Equinox都类似,其实不带任何业务支持的,第二层是业务级别的,比如说网络请求的,日志处理的,第三层就是具体实现了。再多就有点复杂了,有一个最顶层接口的好处是,在Eclipse里,查下继承关系,就得到所有实现了,方便分析代码,如果只设计二和三层,哈哈,就有得找了。

基于以上分析,可以列出来几个基本的元素和服务:

  1. Node+Group+MasterNode+DataNode
  2. Table+Field+Key+Condition
  3. BuildIndex+Query
  4. Log
  5. Plugin

下面是大致的架构域图:

_

还有几个难点,需要再考虑一下:

  1. Query可能会有Paging的需要,那么一旦出现Sharding的话,需要将多个DataNode的结果Merge后,进行Sort,再计算Paging后返回。这个对性能的要求比较高,特别是当页面翻到几十页的时候,性能损失非常大,如何处理?还是说技术层面上不做解决,直接让业务方来自行规划。
  2. 因为ElasticSearch是基于Lucene的,而Lucene并不提供事务操作,比如先行锁再Update,因此一旦出现冲突时,因为网络延时等原因,有可能后面的数据覆盖前面的数据,这种情况怎么考虑,是加一个时间版本号还是忽略这种情况?
  3. 另外ElasticSearch对数据一致性不可能提供太好的解决方案,因此最好还是将一些非核心业务数据进行查询,比如日志,就不会出现修改,再比如电商中的商品表,修改相对并不频繁,但如果商品表里包含商品数量,那么就挂了,所有必须减少将频繁更新的数据放入搜索。
  4. 有点记不清楚Lucene的存储机制了,是否支持类似于数据库的Update语句,只更新部分数据。如果不支持,那么ElasticSearch是否需要支持呢?如果是我,应该不会支持,做太多的事情更容易出错。
  5. 当MasterNode当掉,显然可以通过选举或者别的方法找到一个新的MasterNode,但如果一个MasterNode或者DataNode收到一个BuildIndex请求后,再当掉,最好是通知Client失败,由Client发起重试。由于所有BuildIndex请求都是发给MasterNode来处理的,那么就相对简单了,如果MasterNode失败后重新加入Group,由于此时它不再是Master,就可以丢弃这个日志,保证数据一致性。这块的细节会比较多,记录Log,然后如何Redo,如何Sync,如何抛弃,都需要深入分析。不在这里折腾了。
相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
5月前
|
SQL 运维 数据挖掘
森马服饰从 Elasticsearch 到阿里云 SelectDB 的架构演进之路
森马引入阿里云 SelectDB 替换原 Elasticsearch + 业务库混合架构,统一分析 16+ 核心业务,打通 BI 组件,大幅简化数据同步链路和分析系统架构。实现复杂查询 QPS 提升 400%,响应时间缩短至秒级,亿级库存流水聚合查询缩短至 8 秒内的显著收益,有效驱动森马全渠道运营效率持续增长与业务创新。
149 0
森马服饰从 Elasticsearch 到阿里云 SelectDB 的架构演进之路
|
存储 分布式计算 大数据
大数据-169 Elasticsearch 索引使用 与 架构概念 增删改查
大数据-169 Elasticsearch 索引使用 与 架构概念 增删改查
212 3
|
存储 JSON 数据库
Elasticsearch 分布式架构解析
【9月更文第2天】Elasticsearch 是一个分布式的搜索和分析引擎,以其高可扩展性和实时性著称。它基于 Lucene 开发,但提供了更高级别的抽象,使得开发者能够轻松地构建复杂的搜索应用。本文将深入探讨 Elasticsearch 的分布式存储和检索机制,解释其背后的原理及其优势。
775 5
|
存储 索引
Elasticsearch分布式架构
【11月更文挑战第2天】
232 1
|
12月前
|
搜索推荐 API 定位技术
一文看懂Elasticsearch的技术架构:高效、精准的搜索神器
Elasticsearch 是一个基于 Lucene 的开源搜索引擎,以其强大的全文本搜索功能和快速的倒排索引技术著称。它不仅支持数字、文本、地理位置等多类型数据,还提供了可调相关度分数、高级查询 DSL 等功能。Elasticsearch 的核心技术流程包括数据导入、解析、索引化、查询处理、得分计算及结果返回,确保高效处理大规模数据并提供准确的搜索结果。通过 RESTful API、Logstash 和 Filebeat 等工具,Elasticsearch 可以从多种数据源中导入和解析数据,支持复杂的查询需求。
625 0
|
12月前
|
存储 负载均衡 监控
揭秘 Elasticsearch 集群架构,解锁大数据处理神器
Elasticsearch 是一个强大的分布式搜索和分析引擎,广泛应用于大数据处理、实时搜索和分析。本文深入探讨了 Elasticsearch 集群的架构和特性,包括高可用性和负载均衡,以及主节点、数据节点、协调节点和 Ingest 节点的角色和功能。
532 0
|
存储 监控 分布式数据库
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现
本文介绍了百亿级数据存储架构的设计与实现,重点探讨了ElasticSearch和HBase的结合使用。通过ElasticSearch实现快速检索,HBase实现海量数据存储,解决了大规模数据的高效存储与查询问题。文章详细讲解了数据统一接入、元数据管理、数据一致性及平台监控等关键模块的设计思路和技术细节,帮助读者理解和掌握构建高性能数据存储系统的方法。
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现
|
8月前
|
安全 Java Linux
Linux安装Elasticsearch详细教程
Linux安装Elasticsearch详细教程
1479 64
|
7月前
|
JSON 安全 数据可视化
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
Kibana 是 Elastic Stack(原 ELK Stack)中的核心数据可视化工具,主要与 Elasticsearch 配合使用,提供强大的数据探索、分析和展示功能。elasticsearch安装在windows上一般是zip文件,解压到对应目录。文件,elasticsearch8.x以上版本是自动开启安全认证的。kibana安装在windows上一般是zip文件,解压到对应目录。elasticsearch的默认端口是9200,访问。默认用户是elastic,密码需要重置。
3698 0
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
476 5