有道云排版好一点:https://note.youdao.com/ynoteshare1/index.html?id=a38978147bd85dd15148027aeadd1c92&type=note
倒排索引存储了比包含了一个特定term的文档列表多地多的信息。它可能存储包含每个term的文档数量,一个term出现在指定文档中的频次,每个文档中term的顺序,每个文档的长
度,所有文档的平均长度,等等。这些统计信息让Elasticsearch知道哪些term更重要,哪些
文档更重要,也就是相关性。
1.不可变性
写入磁盘的倒排索引是不可变的,它有如下好处:
1.不需要锁。如果从来不需要更新一个索引,就不必担心多个程序同时尝试修改。
2.一旦索引被读入文件系统的缓存(译者:在内存),它就一直在那儿,因为不会改变。只要文件系统缓存有足够的空间,大部分的读会直接访问内存而不是磁盘。这有助于性能提升。
3.在索引的声明周期内,所有的其他缓存都可用。它们不需要在每次数据变化了都重建,因为数据不会变。
4.写入单个大的倒排索引,可以压缩数据,较少磁盘IO和需要缓存索引的内存大小。
此处的不可变可以理解为已写入的索引不会局部变化,只会不断累加或者重写。有点类似redis持久化里面的aof,不断累加日志,然后到一定量之后经行“重写”。
2.动态索引
既然要不可变,那么更新的话只能选择多个索引。不是重写整个倒排索引,而是增加额外的索引反映最近的变化。每个倒排索引都可以按顺序查询,从最老的开始,最后把结果聚合。有点像累加,但是每次累加都是独立的小索引。
Elasticsearch底层依赖的Lucene,引入了 per-segment search 的概念。一个段(segment)是有
完整功能的倒排索引,但是现在Lucene中的索引指的是段的集合,再加上提交点。
索引vs分片
为了避免混淆,需要说明,Lucene索引是Elasticsearch中的分片,Elasticsearch中的索引是分片的集合。当Elasticsearch搜索索引时,它发送查询请求给该索引下的所有分
片,然后过滤这些结果,聚合成全局的结果。
更新过程
1. 新的文档首先写入内存区的索引缓存。
2. 不时,这些buffer被提交:
2.1)一个新的段——额外的倒排索引——写入磁盘。
2.2)新的提交点写入磁盘,包括新段的名称。
2.3)磁盘是fsync’ed(文件同步)——所有写操作等待文件系统缓存同步到磁盘,确保它们
可以被物理写入。
3. 新段被打开,它包含的文档可以被检索
4. 内存的缓存被清除,等待接受新的文档。
3.缓存进磁盘
在缓存区数据,不可能实时往磁盘写入同步,这样太耗费磁盘性能了。但是同步太慢的话,又会有写入的数据无法快速查到的问题。ES提供了每秒自动同步一次的服务,并且提供了refeash API用于手动同步。
POST /_refresh <1>
POST /blogs/_refresh <2>
PUT /my_logs//设置自动同步时间
{
"settings": {
"refresh_interval": "30s" <1>
}
}
4.持久化
这一点和mysql的redolog,防止内存中的提交因为关机而丢失,专门针对这部分未提交的内存中的数据做持久化。在ES中称为事务日志translog
1. 当一个文档被索引,它被加入到内存缓存,同时加到事务日志。
2. refresh使得分片的进入如下图描述的状态。每秒分片都进行refeash:
内存缓冲区的文档写入到段中,但没有fsync。
段被打开,使得新的文档可以搜索。
缓存被清除
3. 随着更多的文档加入到缓存区,写入日志,这个过程会继续
4. 不时地,比如日志很大了,新的日志会创建,会进行一次全提交:
内存缓存区的所有文档会写入到新段中。
清除缓存
一个提交点写入硬盘
文件系统缓存通过fsync操作flush到硬盘
事务日志被清除
事务日志记录了没有flush到硬盘的所有操作。当故障重启后,ES会用最近一次提交点从硬盘恢复所有已知的段,并且从日志里恢复所有的操作。事务日志还用来提供实时的CRUD操作。当你尝试用ID进行CRUD时,它在检索相关段内的文档前会首先检查日志最新的改动。这意味着ES可以实时地获取文档的最新版本。
5.合并段
此处类似redis aof的重写达到的效果。
ES通过后台合并段解决这个问题。小段被合并成大段,再合并成更大的段。这是旧的文档从文件系统删除的时候。旧的段不会再复制到更大的新段中。修改和删除在这里免除了重复,得到了真正的实现。
1. 索引过程中,refresh会创建新的段,并打开它。
2. 合并过程会在后台选择一些小的段合并成大的段,这个过程不会中断索引和搜索。
3. 下图描述了合并后的操作:
新的段flush到了硬盘。
新的提交点写入新的段,排除旧的段。
新的段打开供搜索。
旧的段被删除。