elasticsearch介绍
一、核心功能介绍
索引(index):可以类比为关系型数据库中的“库”
type(type):
早期版本中,一种
type可以类比为一类表,例如user表、order表注意:
es 5.x中一个index可以有多种type
es 6.x 中一个 index 只能有一种 type
es 7.x以后已经移除type这个概念
映射(mapping):定义字段类型、分词方式等信息,类似关系型数据库中的表结构
文档(document):相当于关系型数据库中的一行记录
字段:相当于关系型数据库中的列
集群:由一个或多个节点组成,默认集群名称通常为
elasticsearch节点:集群中的单个运行实例,可以是一台机器,也可以是一个进程
分片和副本:
副本是分片的复制。分片分为主分片和副本分片。
一个 index 的数据会分布在多个主分片中,每个主分片只保存一部分数据,同时每个主分片又可以拥有多个副本分片,用于提升可用性和读取能力。
二、常见数据类型
常见数据类型分为以下几种:
核⼼数据类型
复杂数据类型
专⽤数据类型
三、核心数据类型
字符串
text:⽤于全⽂索引,该类型的字段将通过分词器进⾏分词
keyword:不分词,只能搜索该字段的完整的值
数值型:
long、integer、short、byte、double、float、half_float、scaled_float布尔 - boolean
⼆进制 - binary:该类型的字段把值当做经过 base64 编码的字符串,默认不存储,且不可搜索
范围类型:范围类型表示值是⼀个范围,⽽不是⼀个具体的值
类型分为:integer_range, float_range, long_range, double_range, date_range 如 age 的类型是 integer_range,那么值是 {"gte" : 20, "lte" : 40};搜索 "term" :{"age": 21} 可以搜索该值
⽇期 - date:由于Json没有date类型,所以es通过识别字符串是否符合format定义的格式来判断是否为date类型
format默认为:strict_date_optional_time||epoch_millis
格式 :"2022-01-01" "2022/01/01 12:10:30" 这种字符串格式
从开始纪元(1970年1⽉1⽇0点) 开始的毫秒数
从开始纪元开始的秒数
四、复杂数据类型
- 数组类型 Array
ES中没有专⻔的数组类型, 直接使⽤[]定义即可,数组中所有的值必须是同⼀种数据类型, 不⽀持混合数据类型的数组:
字符串数组 [ "one", "two" ],整数数组 [ 1, 2 ],Object对象数组 [ { "name": "Louis", "age": 18 }, { "name": "Daniel", "age": 17 }]
同⼀个数组只能存同类型的数据,不能混存,譬如 [ 10, "some string" ] 是错误的
- 对象类型 Object:对象类型可能有内部对象
新增带有对象的数据
请求:
POST localhost:9200/es/_doc_6{
"name": "李四",
"date": "1641886870",
"array": [
"one",
"two"
],
"address": {
"region": "China",
"location": {
"province": "GuangDong",
"city": "GuangZhou"
}
}
}查找地区为中国的数据
请求:
POST localhost:9200/es/_search{
"query": {
"match": {
"address.region": "china"
}
}
}五、专⽤数据类型
- IP类型:IP类型的字段⽤于存储IPv4或IPv6的地址, 本质上是⼀个⻓整型字段
查找字段IPV4地址最后一位的0-16的地址信息。
请求:
POST localhost:9200/es/_search{
"query": {
"term": {
"ip_addr": "192.168.0.0/16"
}
}
}六、工作原理
Elasticsearch 天生就是分布式系统,但对开发者屏蔽了大部分分布式细节。通常我们只需要启动多个节点,并为它们指定相同的 cluster.name,再在创建索引时设置主分片数和副本数,剩余的路由、分片分配和副本同步都由 ES 内部完成。
这与传统数据库分库分表或 Solr 依赖 ZooKeeper 的分布式方案不同,Elasticsearch 更强调“内建分布式能力”。
七、节点交互原理
es和其他中间件⼀样,⽐如mysql,redis有master-slave模式。es集群也会选举⼀个节点做 为master节点 master节点它的职责是维护全局集群状态,在节点加⼊或离开集群的时候重新分配分⽚。
所有⽂档级别的写操作不会与master节点通信,master节点并不需要涉及到⽂档级别的变更和搜索等操作,es分布式不太像mysql的master-slave模式,mysql是写在主库, 然后再同步数据到从库。⽽es⽂档写操作是分⽚上⽽不是节点上,先写在主分⽚,主分⽚再同步给副分 ⽚,因为主分⽚可以分布在不同的节点上,所以当集群只有⼀个master节点的情况下, 即使流量的增加它也不会成为瓶颈,就算它挂了,任何节点都有机会成为主节点。 读写可以请求任意节点,节点再通过转发请求到⽬的节点,⽐如⼀个⽂档的新增,⽂档通过 路由算法分配到某个主分⽚, 然后找到对应的节点,将数据写⼊到主分⽚上,然后再同步到 副分⽚上。
八、写入文档
客户端向node-1发送新增⽂档请求。
节点通过⽂档的路由算法确定该⽂档属于主分⽚-P0。因为主分⽚-P0在node-3,所以请求会转发到node-3。
⽂档在node-3的主分⽚-P0上新增,新增成功后,将请求转发到node-1和node-2对应的副分⽚-R0上。⼀旦所有的副分⽚都报告成功,node-3向node-1报告成功,node-1向客户端报告成功。
九、读取文档
客户端向node-1发送读取⽂档请求。
在处理读取请求时,node-1在每次请求的时候都会通过轮询所有的副本分⽚来达到负载均衡。
十、集群文档路由原理
当新增⼀个⽂档的时候,⽂档会被存储到⼀个主分⽚中。es通过一下算法去确定具体的分片的。
shard = hash(routing) % number_of_primary_shardsrouting 是⼀个可变值,默认是⽂档的 _id ,也可以设置成⼀个⾃定义的值。 routing 通过 hash 函数⽣成⼀个数字,然后这个数字再除以 number_of_primary_shards (主分 ⽚的数量)后得到 余数 。 这个分布在 0 到 number_of_primary_shards-1 之间的余数, 就是我们所寻求的⽂档所在分⽚的位置。
查看文档所在的分片信息:
GET /es/_search_shards?routing=1返回数据:
nodes表示节点的信息
shards表示分片信息,会对应上节点的id表明分片在哪个索引上。primary表示是否在当前的分片上十一、es乐观锁
es支持乐观锁进行修改数据,在请求的时候可以增加版本号参数进行控制。如:这里的version是查询出来的version+1,如查询的数据是1,在修改的时候传2才可以
POST /es/_doc/1?version=2&version_type=external
{
"name": "张三",
"team_name": "部门",
"position": "岗位",
"play_year": "工龄",
"jerse_no": "工号"
}十二、倒排索引
例如有以下文档,如何通过james查找这些数据。
| 编号(id) | 内容 |
| -------- | ------------- |
| 1 | James Enis |
| 2 | James Harden |
| 3 | Justin James |
| 4 | LeBron James |
| 5 | James Johnson |
文档排序集合:
| 单词序号 | 单词 | 倒排列表 |
| -------- | ------- | --------- |
| 1 | james | 1,2,3,4,5 |
| 2 | enis | 1 |
| 3 | harden | 2 |
| 4 | justin | 3 |
| 5 | lebron | 4 |
| 6 | johnson | 5 |
把五个文档进行分词,每个分词转成小写字母,并且以每个分词分组,统计它所在的文档位置,当有关键词请求过来的时候,将关键词转成小写,查找出关键词匹配到的文档的位置,然后全部返回。
倒排索引:
| 单词序号 | 单词 | 文档频率 | 倒排列表(DocId;TF;<POS>) |
| -------- | ------- | -------- | ------------------------------------------------------------ |
| 1 | james | 5 | (1;1;<1>),(2;1;<1>),(3;1;<2>),(4;1;<2>),(5;1;<1>), |
| 2 | enis | 1 | (1;1;<1>) |
| 3 | harden | 1 | (2;1;<2>) |
| 4 | justin | 1 | (3;1;<1>) |
| 5 | lebron | 1 | (4;1;<1>) |
| 6 | johnson | 1 | (5;1;<2>) |
参数解释
DocId:单词出现的⽂档id
TF:单词在某个⽂档中出现的次数
POS:单词在⽂档中出现的位置
十三、集群分片管理
分⽚(shard):因为ES是个分布式的搜索引擎, 所以索引通常都会分解成不同部分, ⽽这些分布在不同节点的数据就是分⽚. ES⾃动管理和组织分⽚, 并在必要的时候对分⽚数据进⾏再平衡分配, 所以⽤户基本上不⽤担⼼分⽚的处理细节。
副本(replica):ES默认为⼀个索引创建1个主分⽚, 并分别为其创建⼀个副本分⽚. 也就是说每个索引都由1个主分⽚成本, ⽽每个主分⽚都相应的有⼀个copy.
Elastic search7.x之后,如果不指定索引分⽚,默认会创建1个主分⽚和⼀个副分⽚,⽽7.x版本之前的⽐如6.x版本,默认是5个主分⽚
索引分⽚分配 分⽚分配到哪个节点是由ES⾃动管理的,如果某个节点挂了,那分⽚⼜会重新分配到别的节点上。
创建索引的时候设置分片:
"settings": {
#主分片数量
"number_of_shards": 3,
#副本数量,一个主节点对应1个副本,这里有三个主节点所以副本数量会生成3个
"number_of_replicas": 1
},在单机中,节点没有副分⽚,因为只有⼀个节点没必要⽣成副分⽚,⼀个节点挂点,副分⽚也会挂掉,完全是单故障,没有存在的意义。
在集群中,同个分⽚它的主分⽚不会和它的副分⽚在同⼀个节点上,因为主分⽚和副分⽚在同个节点,节点挂了,副分⽚和主分片⼀样是挂了,不要把所有的鸡蛋都放在同个篮⼦⾥。
可以⼿动移动分⽚,⽐如:从node-1节点移动到node-3节点
POST /_cluster/reroute { "commands": [ { "move": { "index": "es", "shard": 2, "from_node": "node-1", "to_node": "node-3" } } ] }创建索引时指定的主分⽚数以后是⽆法修改的,所以主分⽚数的数量要根据项⽬决定,如果真的要增加主分⽚只能重建索引了。副分⽚数以后是可以修改的。
PUT /es/_settings { "number_of_replicas": 2 }
十四、集群监控管理
- 查看集群的健康状态
http://127.0.0.1:9200/_cat/health?v URL返回了集群的健康信息。
status :集群的状态,red红表示集群不可⽤,有故障。yellow⻩表示集群不可靠但可⽤,⼀般单节点时就是此状态。green正常状态,表示集群⼀切正常。
node.total :节点数,这⾥是3,表示该集群有三个节点。
node.data :数据节点数,存储数据的节点数,这⾥是3。
shards :表示我们把数据分成多少块存储。
pri :主分⽚数,primary shards
active_shards_percent :激活的分⽚百分⽐,这⾥可以理解为加载的数据分⽚数,只有加载所有的分⽚数,集群才算正常启动,在启动的过程中,如果我们不断刷新这个⻚⾯,我们会发现这个百分⽐会不断加⼤。- 查看集群的索引数。
http://127.0.0.1:9200/_cat/indices?v URL返回了集群中的所有索引信息,我们可以看到所有索引的健康情况和具体信息。
uuid : 索引内部分配的名称,索引的唯⼀表示
pri : 集群的主分⽚数量
docs.count : 这⾥统计了⽂档的数量。
docs.deleted : 这⾥统计了被删除⽂档的数量。
store.size : 索引的存储的总容量
pri.store.size : 主分别的容量- 查看磁盘的分配情况
http://127.0.0.1:9200/_cat/allocation?v URL返回了每个节点的磁盘情况。
shards : 该节点的分⽚数量
disk.indices : 该节点中所有索引在该磁盘所点的空间。
disk.used : 该节点已经使⽤的磁盘容量
disk.avail : 该节点可以使⽤的磁盘容量
disk.total : 该节点的磁盘容量- 查看集群的节点信息
http://127.0.0.1:9200/_cat/nodes?v URL返回了集群中各节点的情况。
ip : ip地址
heap.percent : 堆内存使⽤情况
ram.percent : 运⾏内存使⽤情况
cpu : cpu使⽤情况
master : 是否是主节点- 查看集群的其他信息
