概述
Elasticsearch作为一个常用的中间件,为了能够够好的用好它,了解它的整体架构非常有必要.特别是Elasticsearch是一个分布式的中间件,了解了他的架构图,我们才能知道为什么它能够达到高可用,高性能.
架构图
1.数据是以文档为单位,一条文档就是一条数据
2.文档存储在分片当中,分片是分布式存储在任意一台机器(p1,p2,p3是分片)
3.一个索引由多个分片组成,数据分布在多个es节点(索引由p1,p2,p3三个分片组成)
4.每个分片是有0到多个副本的,分布在节点上(p1,p2,p3分别有两个副本R1,R2,R3)
5.主分片提供读写能力(红色p1,p2,p3)
6.主分片副本同步主分片数据,并且提供读服务(R1,R2,R3)
扩容机制
1.索引由多个主分片和多个副分片组成
2.主分片在创建索引后就确定了,不可修改,因为主分片有读写能力,意味着一开始索引的写能力就已经确认了(可以借助重建索引来重新指定主分片数量)
3.副分片可以动态修改,意味着读能力是可以继续扩展的.
4.es和mysql对比, es明显具有分布式扩展能力,所以es读写能力大大超过mysql.
乐观锁控制并发
//请求带上if_primary_term=1&if_seq_no=4控制并发
POST /test-index-20220311/_update/MViAd38BX_oAU-6DNdFf?if_primary_term=1&if_seq_no=4
{
"doc": {
"name":"aaa3"
}
}
//版本已经发生改变,那么会报错,如下
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[MViAd38BX_oAU-6DNdFf]: version conflict, required seqNo [4], primary term [1]. current document has seqNo [5] and primary term [1]",
"index_uuid" : "z8wkuCSBRpK2lVvxSF2AVg",
"shard" : "0",
"index" : "test-index-20220311"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[MViAd38BX_oAU-6DNdFf]: version conflict, required seqNo [4], primary term [1]. current document has seqNo [5] and primary term [1]",
"index_uuid" : "z8wkuCSBRpK2lVvxSF2AVg",
"shard" : "0",
"index" : "test-index-20220311"
},
"status" : 409
}
复制代码
数据路由算法
1.es读写数据实际是写在某个分片的,需要一个hash一致性来控制,这样写入的数据和读取某条数据的分片才能达到一致
2.es数据路由算法其实就是先进行hash计算,然后对主分片数进行取模操作,这样总是能命中某个存在的分片
3.es不能修改主分片的原因就在这里,修改了主分片会存在路由不到数据的问题. 所以可以借助_reindex进行rehash重建立索引.
写数据流程(根据路由值写)
1.当用户发起一个写请求到任意一个node,比如node1,那么这个node1就叫做协调节点
2.协调节点会根据路由数据算法,计算数据分布的分片,假设计算结果是第二个分片,然后协调节点将请求转发到
第二个分片为主分片的所在节点.
3.主分片写完之后,会同步到副本节点,同步完成后返回
4.主分片同步副分片,其实是存在策略的,同步太多会有写入性能问题,同步太少又会导致数据丢失,我们可以通过指定wait_for_active_shards=10&timeout=10s两个参数来控制(涉及写一致性问题)
默认使用的路由值是 document id
写数据流程(主分片写入内部)
1.首先把接收到的请求,也就是原始数据写入到memory buffer
2.同时写入log到translog buffer(写入日志)
3.memory buffer每隔1s钟会进行refresh, 这个过程会建立倒排索引,生成segment文件,等到os缓存写入磁盘
4.translog buffer日志也同时同步数据到磁盘
5.生成segment文件,才加入到倒排索引中,才能被搜索,所以写入的数据如果想快点搜索到,那么可以手动refresh
读数据流程(根据路由值读)
1.读数据请求一般不是用户发起的,一般是协调节点在进行搜索,需要拉取文档数据发起的,一般就是根据路由值(id)拉取数据
2.协调节点首先根据数据路由算法,计算出数据属于哪个分片,然后获取到这个分片所有的主分片和副分片列表
3.协调节点根据轮询负载的策略,转发到某个分片读取数据(可能读取不到,某些分片没有同步完数据,可以通过写策略来避免)
这里读数据,也指的是根据路由值去读数据,和搜索读不是一回事,可以看作搜索读数据的部分
搜索数据流程(搜索读)
1.当用户发起搜索请求,一般是携带一些查询条件的,请求到了协调节点
2.协调节点收到请求后,会将请求转发到索引的每个分片上去(主或者副分片),每个分片取一个代表就行了,这样就是完整的索引数据,因为搜索就是对索引的整个数据就是搜索的,不是针对分片上的数据(分片轮询策略)
3.每个分片根据查询的query,会找到满足条件的数据,并且返回doc id
4.协调节点收到查询结果后,会进行排序,合并分页
5.协调节点最后根据doc ids发起请求,读取对应分片上的数据(上面读数据的意义)(分片轮询策略)