ElasticSearch搜索技术与集群架构原理(算是白话)有问题欢迎评论

ElasticSearch(读音 饿啦谁可死蛇吃)架构原理

ElasticSearch节点类型 主要分为两种节点一种是Master(读音 吗死特) 一种是DataNode
Master节点
   在ElasticSearch启动时会选举一个Master节点 当一个节点启动时会使用Zen
    Discovery机制找到集群中其他节点并建立连接 Master节点主要负责
管理索引(创建索引、删除索引)、分配分片、维护元数据、管理集群节点状
态、不负责数据写入和查询 一个ElasticSearch集群中只有一个Master 

DataNode节点
   在ElasticSearch集群中会有N个DataNode节点  主要复制数据的写入 数据检索
   大部分ElasticSearch压力都在DataNode节点上

分片和副本机制

分片是根据索引来的 就是把一个服务器上ElasticSearch用来存储数据的那块空间分为好几块 均匀的把数据存储在这几块空间中 如果是集群的话如果有三个分片 三个机器做集群 ElasticSearch会把这三个分片设置到不同的机器上 比如分片1在机器1上 分片3在机器2上 这就叫做分片 它会有一个primary shard(主要节点)跟Replica Shard(副本节点) 一个集群中只有一个主要节点(比如分片数为3 那么主要节点是3个 es会把它们分别创建到不同的服务器上)

副本就是给这个数据做的一个备份  7.x版本默认一个分片一个副本

设置分片、副本数量

PUT /job_idx_shard_temp
{
“mappings”:{
“properties”:{
“id”:{“type”:“long”,“store”:true},
“area”:{“type”:“keyword”,“store”:true},
“exp”:{“type”:“keyword”,“store”:true},
“edu”:{“type”:“keyword”,“store”:true},
“salary”:{“type”:“keyword”,“store”:true},
“job_type”:{“type”:“keyword”,“store”:true},
“cmp”:{“type”:“keyword”,“store”:true},
“pv”:{“type”:“keyword”,“store”:true},
“title”:{“type”:“text”,“store”:true},
“jd”:{“type”:“text”}

}
},
“settings”:{
“number_of_shards”:3, // 这里表示分片分几个
“number_of_replicas”:2 // 这里表示有几个副本 这里设置的一共9个分片
}
}

// 查看分片、主分片、副本分片
GET /_cat/indices?v

ElasticSearch工作流程

ElasticSearch文档写入原理

   当我们给es发送了POST、PUT这种写入操作的请求 它首先会在集群中选择一个DataNode发送请求 被选中的那台机器
   就会被称为coordinating(协调节点)然后这个协调节点就会进行路由选择将请求发送给其他
   的DataNode(对应的某个主要节点)然后再写到副本节点上 主要节点跟副本节点都写完然后返回给我们

ElasticSearch文档检索(就是查询)

当我们给es发送查询请求时 它也是会先找一个协调节点 然后让协调节点发送广播 然后每个(分片)返回对应的文档id和节点,分片信息 协调节点进行汇总 排序 然后 协调节点想包含文档的分片发送get请求获取完返回给我们

ElasticSearch准实时搜索

当es在写入数据时 会先写入到内存上的Memory buffer (读音 卖磨瑞 八佛)然后这个缓存会生成segment文件就是一个很小很小的文件然后每过1秒钟就会把文件刷新到另一个缓存File system cahce (文件缓存) 然后这个文件缓存会每过30分钟刷新到磁盘上 为了保证数据不会丢失 es还在内存中创建了一个Translog(读音 蠢安斯老狗)这个Translog默认每个indes、delete、update或bulk请求提交一次到磁盘当segment的数据全部刷到磁盘时会清空Translog 准实时搜索就是只有当数据到了文件缓存中 才能被查询到

segment文件es会定期合并成大segment 这个阶段会物理上删除之前执行delete的数据

一点es语句

// 这个会把元数据中带java或developer的数据给查询出来
GET /es_db/_search
{
“query”: {
“match”: {
“remark”: “java developer”
}
}
}

// 这个会把元数据中同时包含这个两个单词的java或developer的数据给查询出来
GET /es_db/_search
{
“query”: {
“match”: {
“remark”: {
“query”: “java developer”,
“operator”: “and”
}
}
}
}

// 这个表示 数据中必须包含ava、architect、assistant这三个单词的百分之68的数据查询出来 100%除3等于33%也就是要满足两个单词
GET /es_db/_search
{
“query”: {
“match”: {
“remark”: {
“query”: “java architect assistant”,
“minimum_should_match”: “66%” // 这里也能写数据 比如2 就表示满足两个单词
}
}
}
}

// 这是一个组合查询 表示should数组中的条件应该要满足 也就是必须满足一个
GET /es_db/_search
{
“query”: {
“bool”: {
“should”: [
{
“match”: {
“remark”: “java”
}
},
{
“match”: {
“remark”: “developer”
}
},
{
“match”: {
“remark”: “assistant”
}
}
],
“minimum_should_match”: 2 // 这里就写的2 就表示上面的match要满足两个
}
}
}

match的底层转换 es在执行match搜索时通常都会对搜索条件进行转换

// 第一种
GET /es_db/_search
{
“query”: {
“match”: {
“remark”: “java developer”
}
}
}

转换后是:
GET /es_db/_search
{
“query”: {
“bool”: {
“should”: [
{
“term”: {
“remark”: “java”
}
},
{
“term”: {
“remark”: {
“value”: “developer”
}
}
}
]
}
}
}

// 第二种
GET /es_db/_search
{
“query”: {
“match”: {
“remark”: {
“query”: “java developer”,
“operator”: “and”
}
}
}
}

转换后是:
GET /es_db/_search
{
“query”: {
“bool”: {
“must”: [
{
“term”: {
“remark”: “java”
}
},
{
“term”: {
“remark”: {
“value”: “developer”
}
}
}
]
}
}
}

// 第三种

GET /es_db/_search
{
“query”: {
“match”: {
“remark”: {
“query”: “java architect assistant”,
“minimum_should_match”: “68%”
}
}
}
}

转换后为:
GET /es_db/_search
{
“query”: {
“bool”: {
“should”: [
{
“term”: {
“remark”: “java”
}
},
{
“term”: {
“remark”: “architect”
}
},
{
“term”: {
“remark”: “assistant”
}
}
],
“minimum_should_match”: 2
}
}
}

使用转换后的写法会提高效率 但是开发周期可能变长

boost权重 比如百度上的广告 这些广告给钱了 应该要排在前面

GET /es_db/_search
{
“query”: {
“bool”: {
“must”: [
{
“match”: {
“remark”: “java”
}
}
],
“should”: [
{
“match”: {
“remark”: {
“query”: “developer”,
“boost” : 1
}
}
},
{
“match”: {
“remark”: {
“query”: “architect”,
“boost” : 3 // 这个值越大 数据越靠前
}
}
}
]
}
}
}

dis_max实现best fields策略多字段搜索
best fields策略 就是当我们用四个关键字搜索时 会有一些只匹配了一个关键字搜索出来的数据 这些数据通常是不准确的 这个策略就表示让匹配多个关键字的排在前面 多个字段查询那个字段评分高 就使用哪个字段的评分进行排序

GET /es_db/_search
{
“query”: {
“dis_max”: {
“queries”: [
{
“match”: {
“name”: “rod”
}
},
{
“match”: {
“remark”: “java developer”
}
}
]
}
}
}

基于tie_breaker(读音 太 被个)参数优化dis_max搜索效果 上面说哪个字段评分高使用哪个排序 在某些情况下需要评分低的介入这种情况就是用tie_breaker表示一个评分低的会先乘以tie_breaker设置的值然后在比

GET /es_db/_search
{
“query”: {
“dis_max”: {
“queries”: [
{
“match”: {
“name”: “rod”
}
},
{
“match”: {
“remark”: “java developer”
}
}
],
“tie_breaker”:0.5
}
}
}

使用multi_match简化dis_max+tie_breaker
ES中相同结果的搜索也可以使用不同的语法语句来实现。不需要特别关注,只要能够实现搜索,就是完成任务!

GET /es_db/_search
{
“query”: {
“dis_max”: {
“queries”: [
{
“match”: {
“name”: “rod”
}
},
{
“match”: {
“remark”: {
“query”: “java developer”,
“boost” : 2,
“minimum_should_match”: 2
}
}
}
],
“tie_breaker”: 0.5
}
}
}

#使用multi_match语法为:其中type常用的有best_fields和most_fields。^n代表权重,相当于"boost":n。
GET /es_db/_search
{
“query”: {
“multi_match”: {
“query”: “rod java developer”,
“fields”: [“name”, “remark^2”],
“type”: “best_fields”,
“tie_breaker”: 0.5,
“minimum_should_match” : “50%”
}
}
}

cross fields搜索 这个会额外带operator参数用来标记搜索条件怎么在多个字段中匹配

GET /es_db/_search
{
“query”: {
“multi_match”: {
“query”: “java developer”,
“fields”: [“name”, “remark”],
“type”: “cross_fields”,
“operator” : “and”
}
}
}

上述语法表示java必须在name跟remark这两个字段中都要匹配 developer也是

most fields策略是尽肯能匹配更多的字段会有排序问题 cross fields策略不能使用minimum_should_match 它们都有缺点一般使用best fields

短语匹配match phrase

GET _search
{
“query”: {
“match_phrase”: {
“remark”: “java assistant” // 在es插入数据时会分词 分词的时候会记录每个单词的位置 比如java的位置是0 assistant位置是1 短语匹配就是这两个单词的位置必须相邻 如果assistant位置是2就差不到了
}
}
}

match phrase中的参数 slop

slop表示这个单词可以移动几次

下标 : 0 1 2 3
doc : hello world java spark
搜索 : hello spark
移动1: hello spark
移动2: hello spark
匹配成功,不需要移动第三次即可匹配。

GET _analyze
{
“text”: “hello world, java spark”,
“analyzer”: “standard”
}

POST /test_a/_doc/3
{
“f” : “hello world, java spark”
}

GET /test_a/_search
{
“query”: {
“match_phrase”: {
“f” : {
“query”: “hello spark”,
“slop” : 2
}
}
}
}

GET /test_a/_search
{
“query”: {
“match_phrase”: {
“f” : {
“query”: “spark hello”,
“slop” : 4
}
}
}
}

前缀搜索 prefix search

GET /test_a/_search
{
“query”: {
“prefix”: {
“f.keyword”: {
“value”: “J”
}
}
}
}

通配符搜索

GET /test_a/_search
{
“query”: {
“wildcard”: {
“f.keyword”: {
“value”: “?eo
}
}
}
}

正则搜索

GET /test_a/_search
{
“query”: {
“regexp” : {
“f.keyword” : “[A-z].+”
}
}
}

fuzzy模糊搜索 就是当搜索条件中有几个字写错了 也能给匹配出来

GET /test_a/_search
{
“query”: {
“fuzzy”: {
“f” : {
“value” : “word”,
“fuzziness”: 2 // 表示只能错两个字
}
}
}
}

类似百度输入框

GET /test_a/_search
{
“query”: {
“match_phrase_prefix”: {
“f”: {
“query”: “java s”,
“slop” : 10,
“max_expansions”: 10 // 表示前缀可以匹配多少个
}
}
}
}

es存储数据流程图

ElasticSearch搜索技术与集群架构原理(算是白话)有问题欢迎评论
检索流程
ElasticSearch搜索技术与集群架构原理(算是白话)有问题欢迎评论
插入流程
ElasticSearch搜索技术与集群架构原理(算是白话)有问题欢迎评论

上一篇:mysql json类型


下一篇:树形结构的数据与一维数组数据的相互转换