Elasticsearch为啥这么快

Elasticsearch为啥这么快,第1张

思考几个问题:

这里有篇 文章 讲解的很形象:

这是集群cluster。

这是节点Node:就是个机器。

由一个或者多个节点,多个绿色小方块组合在一起形成一个ElasticSearch的索引。

在一个索引下,分布在多个节点里的绿色小方块称为分片:Shard。

一个分片就是一个Lucene Index。

在Lucene里面有很多小的Segment,即为存储的最小管理单元。

我们分别从Node维度、Shard维度、Segment维度来阐明为啥Elasticsearch这么快。

多节点的集群方案,提高了整个系统的并发处理能力。

路由一个文档到一个分片中:当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?实际上,这个过程是根据下面这个公式决定的:

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。这就解释了为什么我们要在创建索引的时候就确定好主分片的数量,并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

确定了在哪个分片中,继而可以判定其在哪个节点上。

那么主分片数确定的情况下,如果做集群扩容呢?下图是一种主分片的扩容办法,开始设置为5个分片,在单个节点上,后来扩容到5个节点,每个节点有一个分片。也就是说单个分片的容量变大了,但是数量并不增加。

节点分为主节点 Master Node、数据节点 Data Node和客户端节点 Client Node(单纯为了做请求的分发和汇总)。每个节点都可以接受客户端的请求,每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。当接受请求后,节点变为「协调节点」。从这个角度,整个系统可以接受更高的并发请求,当然搜索的就更快了。

以更新文档为例:

Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的 *** 作。因为没有阻塞,所以提升了索引的速度,同时可以通过 _version 字段来保证并发情况下的正确性:

控制在我们索引中的文档只有现在的 _version 为 1 时,本次更新才能成功。

可以设置分片的副本数量来提升高并发场景下的搜索速度,但是同时会降低索引的效率。

在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。

怎样在保留不变性的前提下实现倒排索引的更新?即用上文提到的 _version ,创建更多的索引文档。实际上一个 UPDATE *** 作包含了一次 DELETE *** 作(仅记录标志待Segment Merge 的时候才真正删除)和一次 CREATE *** 作。

为了提升写索引速度,并且同时保证可靠性,Elasticsearch 在分段的基础上,增加了一个 translog ,或者叫事务日志,在每一次对 Elasticsearch 进行 *** 作时均进行了日志记录。

Segment在被refresh之前,数据保存在内存中,是不可被搜索的,这也就是为什么 Lucene 被称为提供近实时而非实时查询的原因。

但是如上这种机制避免了随机写,数据写入都是 Batch 和 Append,能达到很高的吞吐量。同时为了提高写入的效率,利用了文件缓存系统和内存来加速写入时的性能,并使用日志来防止数据的丢失。

LSM-Tree 示意图如下,可见 Lucene 的写入思想和 LSM-Tree 是一致的:

终于说到倒排索引了,都说倒排索引提升了搜索的速度,那么具体采用了哪些架构或者数据结构来达成这一目标?

如上是Lucene中实际的索引结构。用例子来说明上述三个概念:

ID是文档id,那么建立的索引如下:

Name:

Age:

Sex:

可见为每个 field 都建立了一个倒排索引。Posting list就是一个int的数组,存储了所有符合某个term的文档id。实际上,除此之外还包含:文档的数量、词条在每个文档中出现的次数、出现的位置、每个文档的长度、所有文档的平均长度等,在计算相关度时使用。

假设我们有很多个 term,比如:

如果按照这样的顺序排列,找出某个特定的 term 一定很慢,因为 term 没有排序,需要全部过滤一遍才能找出特定的 term。排序之后就变成了:

这样我们可以用二分查找的方式,比全遍历更快地找出目标的 term。这个就是 term dictionary。有了 term dictionary 之后,可以用 logN 次磁盘查找得到目标。

但是磁盘的随机读 *** 作仍然是非常昂贵的(一次 random access 大概需要 10ms 的时间)。所以尽量少的读磁盘,有必要把一些数据缓存到内存里。但是整个 term dictionary 本身又太大了,无法完整地放到内存里。于是就有了 term index。term index 有点像一本字典的大的章节表。比如:

A 开头的 term ……………. Xxx 页

C 开头的 term ……………. Yyy 页

E 开头的 term ……………. Zzz 页

如果所有的 term 都是英文字符的话,可能这个 term index 就真的是 26 个英文字符表构成的了。但是实际的情况是,term 未必都是英文字符,term 可以是任意的 byte 数组。而且 26 个英文字符也未必是每一个字符都有均等的 term,比如 x 字符开头的 term 可能一个都没有,而 s 开头的 term 又特别多。实际的 term index 是一棵 trie 树:

例子是一个包含 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn" 的 trie 树。这棵树不会包含所有的 term,它包含的是 term 的一些前缀。通过 term index 可以快速地定位到 term dictionary 的某个 offset,然后从这个位置再往后顺序查找。

现在我们可以回答“为什么 Elasticsearch/Lucene 检索可以比 mysql 快了。Mysql 只有 term dictionary 这一层,是以 b-tree 排序的方式存储在磁盘上的。检索一个 term 需要若干次的 random access 的磁盘 *** 作。而 Lucene 在 term dictionary 的基础上添加了 term index 来加速检索,term index 以树的形式缓存在内存中。从 term index 查到对应的 term dictionary 的 block 位置之后,再去磁盘上找 term,大大减少了磁盘的 random access 次数。

实际上,Lucene 内部的 Term Index 是用的「变种的」trie树,即 FST 。FST 比 trie树好在哪?trie树只共享了前缀,而 FST 既共享前缀也共享后缀,更加的节省空间。

一个FST是一个6元组 (Q, I, O, S, E, f):

例如有下面一组映射关系:

可以用下图中的FST来表示:

这篇文章讲的很好: 关于Lucene的词典FST深入剖析

想想为啥不用 HashMap,HashMap 也能实现有序Map?耗内存啊!牺牲了一点性能来节约内存,旨在把所有Term Index都放在内存里面,最终的效果是提升了速度。如上可知,FST是压缩字典树后缀的图结构,她拥有Trie高效搜索能力,同时还非常小。这样的话我们的搜索时,能把整个FST加载到内存。

总结一下,FST有更高的数据压缩率和查询效率,因为词典是常驻内存的,而 FST 有很好的压缩率,所以 FST 在 Lucene 的最新版本中有非常多的使用场景,也是默认的词典数据结构。

Lucene 的tip文件即为 Term Index 结构,tim文件即为 Term Dictionary 结构。由图可视,tip中存储的就是多个FST,

FST中存储的是<单词前缀,以该前缀开头的所有Term的压缩块在磁盘中的位置>。即为前文提到的从 term index 查到对应的 term dictionary 的 block 位置之后,再去磁盘上找 term,大大减少了磁盘的 random access 次数。

可以形象地理解为,Term Dictionary 就是新华字典的正文部分包含了所有的词汇,Term Index 就是新华字典前面的索引页,用于表明词汇在哪一页。

但是 FST 即不能知道某个Term在Dictionary(.tim)文件上具体的位置,也不能仅通过FST就能确切的知道Term是否真实存在。它只能告诉你,查询的Term可能在这些Blocks上,到底存不存在FST并不能给出确切的答案,因为FST是通过Dictionary的每个Block的前缀构成,所以通过FST只可以直接找到这个Block在.tim文件上具体的File Pointer,并无法直接找到Terms。

回到上面的例子,给定查询过滤条件 age=24 的过程就是先从 term index 找到 18 在 term dictionary 的大概位置,然后再从 term dictionary 里精确地找到 18 这个 term,然后得到一个 posting list 或者一个指向 posting list 位置的指针。然后再查询 sex=Female 的过程也是类似的。最后得出 age= 24 AND sex=Female 就是把两个 posting list 做一个“与”的合并。

这个理论上的“与”合并的 *** 作可不容易。对于 mysql 来说,如果你给 age 和 gender 两个字段都建立了索引,查询的时候只会选择其中最 selective 的来用,然后另外一个条件是在遍历行的过程中在内存中计算之后过滤掉。那么要如何才能联合使用两个索引呢?有两种办法:

Elasticsearch 支持以上两种的联合索引方式,如果查询的 filter 缓存到了内存中(以 bitset 的形式),那么合并就是两个 bitset 的 AND。如果查询的 filter 没有缓存,那么就用 skip list 的方式去遍历两个 on disk 的 posting list。

用一个例子来说明如何使用 skip list 的思路来做合并(参考 Lucene学习总结之七:Lucene搜索过程解析(5) ):

Advance *** 作是什么?就是 skip list 提供的快速跳跃的特性。

另外一方面,对于一个很长的 posting list,比如:

[1,3,13,101,105,108,255,256,257]

我们可以把这个 list 分成三个 block:

[1,3,13] [101,105,108] [255,256,257]

然后可以构建出 skip list 的第二层:

[1,101,255]

1,101,255 分别指向自己对应的 block。这样就可以很快地跨 block 的移动指向位置了。

Lucene 自然会对这个 block 再次进行压缩。其压缩方式叫做 Frame Of Reference 编码。示例如下:

考虑到频繁出现的 term(所谓 low cardinality 的值),比如 gender 里的男或者女。如果有 1 百万个文档,那么性别为男的 posting list 里就会有 50 万个 int 值。用 Frame of Reference 编码进行压缩可以极大减少磁盘占用。这个优化对于减少索引尺寸有非常重要的意义。当然 mysql b-tree 里也有一个类似的 posting list 的东西,是未经过这样压缩的。

因为这个 Frame of Reference 的编码是有解压缩成本的。利用 skip list,除了跳过了遍历的成本,也跳过了解压缩这些压缩过的 block 的过程,从而节省了 cpu。

这也可以看到,Lucene 为了省内存真是做到了极致。

Bitset 是一种很直观的数据结构,对应 posting list 如:

[1,3,4,7,10]

对应的 bitset 就是:

[1,0,1,1,0,0,1,0,0,1]

每个文档按照文档 id 排序对应其中的一个 bit。Bitset 自身就有压缩的特点,其用一个 byte 就可以代表 8 个文档。所以 100 万个文档只需要 12.5 万个 byte。但是考虑到文档可能有数十亿之多,在内存里保存 bitset 仍然是很奢侈的事情。而且对于个每一个 filter 都要消耗一个 bitset,比如 age=18 缓存起来的话是一个 bitset,18<=age<25 是另外一个 filter 缓存起来也要一个 bitset。

所以秘诀就在于需要有一个数据结构:

可以很压缩地保存上亿个 bit 代表对应的文档是否匹配 filter;

这个压缩的 bitset 仍然可以很快地进行 AND 和 OR 的逻辑 *** 作。

Lucene 使用的这个数据结构叫做 Roaring Bitmap。

其压缩的思路其实很简单。与其保存 100 个 0,占用 100 个 bit。还不如保存 0 一次,然后声明这个 0 重复了 100 遍。

为什么是以65535为界限?程序员的世界里除了1024外,65535也是一个经典值,因为它=2^16-1,正好是用2个字节能表示的最大数,一个short的存储单位,注意到上图里的最后一行“If a block has more than 4096 values, encode as a bit set, and otherwise as a simple array using 2 bytes per value”,如果是大块,用节省点用bitset存,小块就豪爽点,2个字节我也不计较了,用一个short[]存着方便。

在 Lucene 7.0之后,Lucene 针对 bitset的稠稀性,采用不同的存储方式:当 bitset比较稀疏时,直接存储DocID;当 bitset 稠密时,则直接存储 bitset 的Bits数据。根据数据的分布情况不同,采用适当的结构不仅可以提高空间的利用率,还能提高遍历的效率。

Elasticsearch/Lucene 为了提升索引和搜索的效率,从上层到底层,使用了各种巧妙的数据结构和设计,靠优秀的理论加极致的优化,做到查询性能上的极致。

随着小鹏P7上市节奏步步逼近,关于P7和特斯拉Model 3的信息也越来越多。根据目前最新消息,P7的最高续航有可能实现700km+,最低价格会下探到24万,而且轿跑定位绝对拉风。在国内一众电动汽车中,目前是最有可能和Model3正面硬扛的车型。特别是在自动驾驶层面,小鹏汽车一直以自研自居,更是在去年举办了1024科技日。

众所周知,1024是程序员节(因为1024是2的十次方,二进制的基本计量单元之一),作为一家汽车企业,举办这样的活动其实非常违和。你很难想像BBA或者一汽广汽上汽会将之作为一个公司的核心活动。但对于主打“天生智能”、植根于互联网的小鹏汽车而言,这个活动却显得顺理成章。

对于小鹏汽车来说,举办这个节日,不止是“炫耀”自身的科技实力,更是表明自身的品牌调性,尤其是对于旗下小鹏P7与特斯拉Model 3的对比,成为全场活动的核心。

▌武装到牙齿的小鹏P7

“小鹏P7,武装到牙齿,光摄像头比特斯拉多了6个。”这是小鹏汽车10月24日第一场1024智能技术分享日活动后,电动星球蟹老板微博上发布的消息。

这条微博发布后,评论很多,争议很多。人们热衷于争论多了6个摄像头的小鹏P7能不能比特斯拉在自动驾驶上做得更好?回答这一问题的是小鹏汽车自动驾驶副总裁吴新宙,前高通自动驾驶团队负责人。

那么,小鹏P7这套Xpilot 3.0的硬件架构是怎样的?

12个超声波传感器、5个高精度毫米波雷达、13个自动驾驶摄像头、1颗智能座舱摄像头、高精度地图、高精度定位融合、英伟达Xavier自动驾驶芯片

有关这个硬件架构的解读,42号车库在《XPilot 3.0强悍的智能化会成就小鹏P7吗?》一文中做了很好的分析,并将之定义为了全行业最强辅助驾驶硬件架构、除特斯拉外第二件完全自主建立感知能力的车企。

但是,仅止于此?在我们看来,无论是吴新宙将自动驾驶分为四大颗粒——感知、定位、规划、控制;还是从这套硬件架构本身、小鹏自动驾驶团队的组成架构等等来看,以上解读并不能完整说明小鹏P7的特殊性。

特斯拉在自动驾驶上一直坚持纯视觉方案(全车21个传感器,包括12个超声波、8个摄像头、1个前置毫米波雷达,主要以视觉感知为主,参看上图第一张。),而小鹏P7或者说小鹏Xpilot 3.0的硬件架构则是多传感器融合的方案。

除了更多的传感器外(31个,包括摄像头+超声波+毫米波),P7还通过高精度地图+RTK差分+双频高精GPS+超高精度IMU实现了超视距+实时在线的辅助驾驶能力。

是的,超视距+实时在线,这是我们认为小鹏P7在自动驾驶方案上与特斯拉最大的不同。某种程度上,你可以将特斯拉看成桌面端或者单机的,将小鹏P7看成是移动端或者联网的。

映射到自动驾驶能力上,就是特斯拉的车更擅长于处理可视范围内的Input(道路、环境、车辆、行人等等),而小鹏P7在此基础上,还能处理视距范围之外的Input,并将全局定位精度控制在厘米级、相对定位精度<0.3%。后续还能通过V2X等技术方案,实现车辆实时数据的互通和调用,更好地解决超视距的环境感知难题。

你可以将“超视距”的这种能力想像为“预测”或者“想像”。准确的“预测”加上高鲁棒性的可视范围感知能力,让小鹏P7在安全性上有更高的冗余。

当然,说特斯拉更擅长,并不意味着小鹏P7在可视范围内的感知会更差。用小鹏汽车官宣的话来说,小鹏P7打造了迄今为止,量产车最完善的视觉系统——两套环车视觉系统,互为冗余。

▌从L3到L4 ,超越特斯拉?

上面分析完,可能大家会感觉我们想说小鹏已经超越了特斯拉,P7打败了Model 3。但并不是!

从吴新宙当日的演讲和随后接受专访时透露的信息来看,我们认为小鹏汽车依然处于追赶者的位置。

吴新宙说,小鹏汽车是从2015年就开始做自动驾驶研究的,四年多以来做了大量的改装、调试、软硬件匹配等事,甚至培养了一批供应商跟小鹏一起来做这个事,做一系列的系统设计。

2018年G3量产时,小鹏有了第一代自动驾驶、完成了自动泊车;到了2019年,通过多次OTA,G3从XPILOT 1.0变成了XPILOT 2.0(大致是从SAE L1升到L2),在ACC基础上加上了LCC车道保持和ALC自动变道辅助。

而截至目前,小鹏汽车已经具备了端到端的自研能力,涵盖了从感知、定位、规划、控制等所有核心环节。

明年,则是小鹏汽车在自动驾驶上最重要的一年。通过小鹏P7这款车,小鹏汽车的XPILOT将从2.0、2.5达到3.0,实现L3级别的自动驾驶能力,实现高速全自动驾驶以及360度的感知。

此后的2021年,XPILOT将升至3.5 ,具备自主变道能力的高速自动驾驶及停车场自主泊车能力,2023年的XPILOT 4.0将拥有面向城市路况的自动辅助驾驶功能。

吴新宙说,P7交付时虽然搭载了L3级别的自动驾驶硬件,但依然需要几次OTA才能最终实现L3 ,时间点大概是2020年年底前。

我们在专访时问吴新宙,除了NOA 、高速公路全自动变道等等之外,特斯拉V10所呈现出的地图上帝视角、对向来车显示等等,小鹏P7能否做到?吴新宙非常淡定地说,对于小鹏而言,这在技术都没有问题,只有做不做、什么时候做的优先级问题。

而文章标题之所以提到Model 3?,则是因为我们还问了一个关于成本和价格的问题。吴新宙说,从BOM成本来看,P7硬件架构的成本会高于Model 3?。但P7的售价,却不应该由他来公布。

我们此前对P7的价格预估是中配在25-28万之间。考虑到P7目前披露的NEDC 600+续航、百公里加速4s俱乐部、以及更大的尺寸(轴距约3000mm)等等,35.58万起售的(配备基础AP)国产Model 3,的确会感受到压力。

最后补充一点,小鹏汽车在官宣中有这样一句:硬件基础上支持Xpilot 3.0升级到Xpilot 4.0。我们现场问这代表什么?得到的答复是,小鹏汽车从P7这款车开始,在硬件架构上已经做好了向后兼容的准备。说得直白点,就是此后的小鹏车型将支持硬件升级。

▌小鹏的另一个胜负手

如果只是谈小鹏的自动驾驶,行文至此,文章已经可以结束。但小鹏汽车周末的智能技术分享日其实不仅是谈自动驾驶。小鹏汽车董事长兼CEO何小鹏在智能技术分享日开场白时提出的一个问题,就非常具有代表性。

这个问题是:什么是智能汽车?

我仔细想了想,到目前为止真还没有对智能汽车的权威定义。何小鹏在提出问题后给出了自己的答案,认为只具备以下四种能力的汽车才能称为智能汽车。

1、高级别的辅助驾驶能力;

2、具备智能交互能力。有智能座舱、能人格化的自然交流、“我一致坚信,以后汽车的交流形式是语音为主。”

3、有智能进化的能力;能够通过OTA持续升级、能对数据进行运营、有Appstore生态体系,

4、万物互联的能力:包括但不限于5G、C2X(我们认为还要包括IOT)

正是因为有这样的思考,小鹏汽车在架构上其实有两大核心部门。除了吴新宙负责的自动部门,还有副总裁纪宇负责的智能网联部门。

而除了纪宇,小鹏汽车智能网联部门同样和自动驾驶部门一样“大将云集”。

刘凡凡,上海研发负责人,曾在全球最大车载导航供应商泰为工作十多年;负责地图导航、车载系统及应用生态;

刘毅林,上海产品和用户体验的负责人,Frog曾经职位最高的华人设计师,阿里巴巴AliOS斑马车载系统第一代设计师和产品管理人;

赵恒艺,北京负责人,负责人工智能,以及语音、大数据相关的事情,之前在乐视语音当过CEO,曾任思必驰副总裁。

在主题为“拥抱智能、拥抱生态”的演讲中,纪宇将智能汽车分为三代。

第一代解决的是联网的问题;第二代是车机的手机化,代表如特斯拉、斑马,解决的是车机智能化的问题;而小鹏汽车要做的是第三代,要解决的是整个汽车的智能化。

在这个话题上,纪宇说了很多。包括语音交互的自我成长和个性化、包括通过支付宝等手段让手机成为车钥匙、包括他们将与小米在物联网领域展开深度合作、包括什么是全场景智能,怎么让汽车成为贴心私人助理等等。

听完,我们突然意识到,如果说在自动驾驶领域,小鹏汽车还是特斯拉的追赶者。那么在智能网联领域,小鹏汽车已经成为了事实上的引领者。

我们敢于这样说,是因为在G3上我们已经体验到小鹏汽车的这种领先。别人是单个功能能用,而小鹏是多个功能点融在一起的好用。

G3自动泊车,无需寻找车位、无需额外启动,打倒档、点OK,G3就会自动泊车。在当下,这是全行业最好用的自动泊车功能。

自动泊车功能的演进优化,也让我们对小鹏汽车的“运营”有了更多的了解和认同。根据数据,持续对功能点进行优化和调整,实现有价值的OTA,这才是运营的本质。

纪宇说,传统意义上的汽车,把这个汽车买回家以后它是什么样就是什么样,可能五年以后汽车的功能不会增加一点,也不会减少。智能汽车一定是能不断学习的,功能会不断的增加。

而要实现这些能力的话,首先要解决的是下面三个问题,第一个是大数据,第二个是深度学习能力,第三个是OTA整车升级的能力。尤其在OTA上,不能仅仅做成一个时髦的技术,还要把云端和车端的东西结合起来,跟车的大量硬件打通,实现整车的OTA,如果仅仅是APP的OTA是没有价值的。

跟生态的结合,则是小鹏想得非常清楚的另一个要点。譬如,跟支付宝和小米的合作。纪宇说,过往十五六年间,因为支付宝的成功推广,我们今天出门已经不需要带钱包了,只需要带手机和车钥匙就可以了,我们一直在想为什么还带车钥匙?是不是带一个手机就可以?

而在P7这款车上,小鹏终于能安全地做到这一点。不用带钥匙,带个手机就可以,不光可以开门,还可以把车开走。

如果不是小米手机怎么办?打开支付宝,不管什么手机都可以把门打开和开走。跟支付宝的合作,事实上都是利用了支付宝和小米的金融安全能力、手机上密钥验证的能力,保证车端的安全,金融级的数字安全。

结语:智能汽车是下一个赛道

这是何小鹏说过的、我个人最欣赏的一句话。从去年八月何小鹏第一次说出到现在,它也慢慢成为全行业的共识。

何小鹏当天还分享了另一个特别的数据。今年以来,虽然中国纯电动汽车的销售出现了负增长,但是中国智能汽车的增长却一直是在狂飙突进,全年会有百分之三百以上的增长。而在明年,这一增长趋势也不会变化。

第二张图,则是中美国两国智能车的销量合计,单月销量的差距越来越小。

这是何小鹏早前转发的一条朋友圈,也是小鹏汽车眼中的下一个汽车时代。

本文来源于汽车之家车家号作者,不代表汽车之家的观点立场。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11294609.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存