吴灿锦,吉林财经大学2019级本科生,曾作为长春鹰迅网络科技有限责任公司CEO,带领鹰迅公司团队在“互联网 +"和"挑战杯"等竞赛中斩获3个国家级,11个省部级奖项。目前在上市公司从事Java开发相关工作已经接近两年了,参与了两个千万级用户的分布式系统的开发和维护工作,在做项目期间,对Mysql优化,分库分表,多线程,分布式锁,分布式事务,Redis缓存,RabbitMQ,xxl-job,ElasticSearch,SpringCloud微服务框架以及前端的Vue框架都有比较深入的研究,积累了丰富的实践经验和良好的职业履历。
ElasticSearch是一款开源的分布式搜索与分析引擎,专为处理海量数据而生。它凭借高性能、实时响应和强大的可扩展性,轻松应对全文搜索、数据分析及复杂聚合等任务。在大数据领域,ElasticSearch可以构建实时搜索与分析应用,也可以完成数据中台的搭建。
1. 近实时(Near Realtime):NRT 指的是 Elasticsearch 的数据写入后,不会立即被搜索到,而是需要一定的延迟时间。这主要是因为 Elasticsearch 在写入数据时,会进行一系列的内部处理,如分词、建立索引等。通常,这个延迟时间非常短,可能是几百毫秒到几秒。实现近实时搜索体验。
2. 集群(Cluster):集群是由一个或多个 Elasticsearch 实例(或称为节点)组成的集合。这些节点通常分布在不同的机器上,但它们共享相同的集群名称,从而形成一个逻辑上的整体。集群提供了高可用性和扩展性,能够自动均衡分片等。当在集群中添加或删除节点时,Elasticsearch 会自动重新分配数据和索引,以确保集群的稳定性和性能,默认集群名为“elasticsearch”。3. 节点(Node):节点在 Elasticsearch 中,一个 Elasticsearch 实例称为一个节点。节点可以部署在一台独立的机器上,也可以与其他节点共享同一台机器。节点之间通过网络进行通信,共同处理和存储数据,以实现分布式搜索和分析的功能。4. 索引(Index):ElasticSearch中的核心概念,相当于数据库中的表,用于存储多个文档,索引库里存储结构相似的文档数据。每个索引具有独特的名称,名称长度不能超过255个字节。5. 文档(Document):ElasticSearch中的数据记录,通常以JSON格式存储。文档是es中的最小数据单元。一个document就像数据库中的一条记录。6. 映射(Mapping):定义了索引中文档的结构和字段类型,类似于数据库中的表结构。通过映射,可以指定字段的数据类型、是否进行分词等约束条件。7. 字段(Field):文档中的属性或数据项,类似于数据库中的列。每个文档都由多个字段组成,字段定义了文档的结构和内容。8. 类型(Type):目前,在Elasticsearch中,通常建议每个索引只包含一个类型,即_doc,ES官方将在ES9.0版本中彻底删除type9. 分片(shard):index数据过大时,将index里面的数据,分为多个shard,分布式的存储在各个服务器上面。可以支持海量数据和高并发,提升性能和吞吐量,充分利用多台机器的cpu。10. 副本(replica):在分布式环境下,任何一台机器都会随时宕机,如果宕机,index的一个分片没有,导致此index不能搜索。所以,为了保证数据的安全,我们会将每个index的分片经行备份,存储在另外的机器上。保证少数机器宕机es集群仍可以搜索。能正常提供查询和插入的分片我们叫做主分片(primary shard),其余的我们就管他们叫做备份的分片(replica shard)。es6默认新建索引时,5分片,2副本,也就是一主一备,共10个分片。所以,es集群最小规模为两台。11. DSL(Domain Specific Language):ElasticSearch提供的查询和索引操作的JSON风格语法。通过DSL,用户可以构建复杂的查询语句,实现数据的检索、过滤、聚合等操作。
正向索引和倒排索引在数据库和信息检索系统中都起着关键的作用。正向索引,即传统的索引方式,通过遍历全表来查找符合条件的数据,把符合条件的数据放入结果集中。然而,随着数据量的增加,这种逐行扫描的方式会导致查询速度显著下降。特别是在进行模糊查询时,如果百分号(%)放在查询条件的左侧,会导致索引失效,进一步降低查询效率。为了解决这些问题,倒排索引应运而生。倒排索引的核心思想是将文档与词条进行关联,从而能够快速定位到包含特定词条的文档。
1. 文档:文档是指待检索的数据记录,每一条数据都可以视为一个文档,例如一个用户信息、一篇文章或一个网页等。2. 词条:词条则是对文档内容或用户搜索查询进行分词处理后得到的具备具体含义的词语或短语。分词器是实现这一步骤的关键工具,它能够将文本切分为多个有意义的词条。
第一步,使用分词器对文档集合进行分词处理。分词器会将每个文档切分为若干个词条,并将这些词条以及对应的文档ID存储到倒排索引表中。这样,倒排索引表就建立起了词条与文档之间的关联关系。第二步,当用户输入关键字进行搜索时,系统首先会对用户输入的关键字进行分词处理,得到多个词条。然后,系统会根据这些词条去倒排索引表中查询相应的文档ID。通过文档ID,系统可以快速定位到包含这些词条的文档,并将其从索引库中提取出来。最后,系统将查询结果响应给客户端,完成整个搜索过程。通过倒排索引,我们可以显著提高搜索效率,尤其是在处理大规模数据集和复杂查询时。倒排索引的优化还可以进一步提高搜索性能和准确性,例如通过引入权重、频率和位置信息等因素来改进索引结构。
1. 拉取elasticsearch镜像。
docker pull elasticsearch:7.12.1
2. 要想让es和kibana容器互联,就要创建一个docker网络。
docker network create es-net
3. 使用docker单点部署elasticsearch。
安装好了之后在浏览器中输入:http://ip:9200 即可看到Elasticsearch的响应结果:
Kibana是一个开源的数据可视化工具,与Elasticsearch紧密集成。它提供搜索、查看和交互Elasticsearch索引中数据的功能,支持丰富的图表、表格和地图等可视化形式,帮助用户直观理解大量数据,快速创建和分享动态仪表盘。1. -e ELASTICSEARCH_HOSTS=http://es:9200"`:设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch。2. --network es-net:加入一个名为es-net的网络中,与elasticsearch在同一个网络中。
IK分词器是一款专门为中文文本设计的分词工具,用于将文本拆分成有意义的词或短语单元。在搜索引擎中,IK分词器可以帮助创建倒排索引并优化搜索匹配,提升搜索效率和准确性。具体说法就是创建倒排索引时对文档分词;当用户搜索时,对输入的内容分词。
安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看。说明plugins目录被挂载到了:/var/lib/docker/volumes/es-plugins/_data 这个目录中,把ik分词器放到plugins目录后,就输入docker restart es重启es容器。
3. 重启es之后就可以就可以使用IK分词器的模式了。
IK分词器支持自定义词典优化。通过config目录的IkAnalyzer.cfg.xml,可添加拓展词典增加专业词汇,或停用词典去除无意义或敏感词,提高分词准确性。随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“鹰迅公司”,“吴灿锦” 等。所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。
2. 在IKAnalyzer.cfg.xml配置文件下面内容。
在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑。
步骤1:IKAnalyzer.cfg.xml配置文件内容添加stopword.dic。
步骤2:在 stopword.dic 添加停用词,停用词要在扩展词条里面。步骤3:重启es,然后重新发起请求,就会发现停用词条不会出现在响应结果中了。
3.1.1、索引库和mapping
索引库在Elasticsearch中的确类似于关系型数据库中的表,而mapping则相当于表的结构,为索引库中的每个字段设定了数据类型、属性及其他约束。
在向Elasticsearch中存储数据之前,需要先创建索引库并为其定义mapping。mapping不仅定义了字段的数据类型,还指定了字段的索引行为、分词器以及字段之间的关系等。常见的mapping属性有:type,index,analyzer和properties等。3.1.2、type
1. 对于字符串,可以选择text类型用于全文搜索,它支持分词操作;或者选择keyword类型用于精确匹配,它不会对字段值进行分词。2. 对于数值数据,可以选择long、integer等类型。6. 以及geo_point类型用于存储地理坐标点。3.1.3、index
index:指定字段是否应该被索引。默认情况下,字段是会被索引的,这意味着它们可以被搜索。如果设置为false,则该字段将不会被索引,从而节省存储空间和索引构建时间。3.1.4、analyzer
analyzer:用于指定字段的分词器。对于text类型的字段,分词器决定了如何将文本分割成可搜索的词汇单元。选择适合的分词器对于提高搜索效果至关重要。3.1.5、properties
properties:当字段类型为object时,使用properties来定义该对象的子字段及其数据类型和属性。这允许在Elasticsearch中创建嵌套的文档结构。除了以上常见的属性,还有其他一些属性可以用于进一步优化mapping,例如:store:指定是否单独存储字段的原始值。默认为false,表示不存储原始值,只存储索引数据。如果设置为true,则原始值会被存储起来,可以在检索时直接获取,但会增加存储空间的消耗。null_value:当字段的值为null时,可以指定一个默认值来代替null进行索引。这有助于处理缺失值的情况,确保索引的完整性和准确性。dynamic:控制是否允许动态添加新字段。默认情况下,Elasticsearch允许在插入文档时动态添加新字段到mapping中。如果设置为false,则禁止动态添加字段,所有字段必须在创建索引时预先定义。对于下面的json文档,可以理解成数据库表中的行。索引库需要存储上面的json文档,就可以根据文档的属性定义mapping映射。1. age、weight、isMarried和score这四个字段分别被设置为integer、float、boolean和float类型,以存储相应的数据。同时,这些字段都设置了index为true,意味着它们都将被索引,从而可以参与搜索和查询操作。
2. info字段被设计为text类型,适用于全文搜索。为了更准确地处理中文文本,这里使用了ik_smart分词器进行分词。此外,为了支持精确值搜索(比如整体匹配字段内容),还为其添加了一个名为keyword的子字段,类型为keyword。这样,在需要精确匹配info字段内容时,可以使用info.keyword进行查询。
3. email字段被定义为keyword类型,通常用于存储不需要分词的字符串数据。由于这里不需要对email字段进行搜索,因此将index设置为false,避免不必要的索引开销。
4. name字段是一个对象类型,用于存储复合结构的数据。它包含firstName和lastName两个子字段,这两个子字段都是keyword类型,适用于精确匹配和过滤操作。同样,这两个子字段的index都设置为true,以确保它们可以被索引并参与搜索。
倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改已经的mapping结构。虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。
文档都会有一个唯一标识,我们把它叫做id (文档ID) 类似于数据库的一行都会有一个主键来作为唯一标识一样。
根据Restful风格,新增是post,查询是get,不过查询一般都需要条件,这里我们把文档id带上。
1. 修改全部:直接覆盖原来的文档,实际上当有存在的ID的时候,修改根据指定的id删除文档,然后新增一个相同id的文档。根据id删除文档时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。修改部分:增量修改是只修改指定id匹配的文档中的部分字段。match_all:用于检索索引中的所有文档。这通常用于测试或需要获取索引中所有数据的场景。