一、数据在节点间写入
1、客户端选择一个 coordinating node (协调节点)发送请求过去
2、协调节点对document(文档)进行路由,将请求转发给对应的node(有primary shard)
路由算法:shard = hash(routing) % number_of_primary_shards
3、实际node上的primary shard处理请求,然后将数据同步倒replica node
4、协调节点如果发现primary shard和所有的replica shard都搞定的时候,就返回响应结果给客户端
正在上传…重新上传取消
二、数据写操作底层原理
正在上传…重新上传取消
1、先写入内存 buffer,在 buffer 里的时候数据是搜索不到的;同时将数据写入 translog 日志文件。
2、es默认1s将内存 buffer 数据 refresh 到一个新的 segment file 中,但是此时数据不是直接进入 segment file 磁盘文件,而是先进入 os cache(操作系统缓存) ,这个过程就是 refresh。只要 buffer中的数据被 refresh 操作刷入 os cache中,这个数据就可以被搜索到了
3、新的数据不断进入 buffer 和 translog,不断将 buffer 数据写入一个又一个新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。随着这个过程推进,translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发 commit 操作。
4、commit 操作发生就是将一个 commit point写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file,同时强行将 os cache 中目前所有的数据都 fsync 到磁盘文件中去。最后清空 现有 translog 日志文件,重启一个 translog。 commit 操作叫做 flush。默认 30 分钟自动执行一次 flush,但如果 translog 过大,也会触发 flush。flush 操作就对应着 commit 的全过程,我们可以手动执行 flush 操作,手动将 os cache 中的数据 fsync 强刷到磁盘上去。
总结:数据先写入内存 buffer,然后每隔 1s,将数据 refresh 到 os cache,到了 os cache 数据就能被搜索到( es 从写入到能被搜索到,中间有 1s 的延迟)。每隔 5s,将数据写入 translog 文件(如果机器宕机,内存数据全没,最多会有 5s 的数据丢失),translog 大到一定程度,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。
三、常见问题
- es是准实时的?
默认是每隔 1 秒 refresh 一次的,所以 es 是准实时的,因为写入的数据 1 秒之后才能被看到。可以通过 es 的 restful api 或者 java api,手动执行一次 refresh 操作,就是手动将 buffer 中的数据刷入 os cache中,让数据立马就可以被搜索到。只要数据被输入 os cache 中,buffer 就会被清空了,因为不需要保留 buffer 了,数据在 translog 里面已经持久化到磁盘去一份了。
(2)translog作用?
ES执行 commit 操作之前,数据停留在 buffer 中或者在 os cache 中, buffer和os cache 都是内存,一旦这台机器宕机,内存中的数据会丢失。所以将数据对应的操作写入一个专门的日志文件 translog 中,一旦此时机器宕机,再次重启的时候,es 会自动读取 translog 日志文件中的数据,恢复到内存 buffer 和 os cache 中去。
(3)服务器宕机对数据影响?
translog写入 os cache ,默认每隔 5 秒刷一次到磁盘中去,所以默认情况下,可能有 5 秒的数据会仅仅停留在 buffer 或者 translog 文件的 os cache 中,如果此时机器挂了,会丢失 5 秒钟的数据。