Milvus之WAL介绍
来源:SegmentFault
时间:2023-02-16 15:11:22 433浏览 收藏
积累知识,胜过积蓄金银!毕竟在##column_title##开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《Milvus之WAL介绍》,就带大家讲解一下MySQL、SQLite、C++、机器学习、深度学习知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
Milvus 是一款开源的特征向量相似度搜索引擎,在2020-03-11我们发布了版本0.7.0。在该版本中,Milvus 为存储系统添加了一个新组件— WAL(write-ahead logging,预写日志系统)。今天我们就来详细介绍一下相关背景和实现原理,以及如何能更好地使用它。
|背景
我们先回顾一下之前版本数据插入的流程:当用户往 Milvus 系统中插入数据时, Milvus 会先把数据攒在内存里,然后当内存数据达到一定规模(默认128M)或者定时器超时(默认1s)后,内存数据再排队刷入磁盘。当数据真正落盘后它们就能被访问了。这个设计借鉴了操作系统对流数据的处理方式,在写磁盘频率和数据可靠性之间做了一定的平衡。然而随着我们接触到越来越多的用户场景,以上设计渐渐不能满足需求了。首先,用户命令的原子性没得到保证,比如在系统意外退出时,用户某一次插入的数据可能部分落盘、部分丢失;其次,用户无法明确知道数据何时可见,即使在客户端等待1s也未必能保证之前插入数据全部可见;最后,当初设计时没有考虑数据删除,同步执行删除有可能要长时间阻塞用户线程。为了解决上述问题,我们在0.7.0 版本中引入了 WAL 组件。
|WAL 概要
WAL 的中文名是预写日志系统,其核心思想是把用户所有的修改操作(插入、删除)先写入日志中,然后再应用到系统状态里。一旦成功写完日志,即可通知用户操作成功。由于日志是以尾部追加方式写入,耗时较短,所以不会长时间阻塞用户线程。此外为防止意外退出导致数据丢失,系统重启时还会根据日志重做用户操作,以保证数据可靠性。
Milvus 的 WAL 设计也是如此。这里涉及了两个线程:一个是用户线程,另一个是后台线程。用户线程把修改操作写入 WAL 缓存和 WAL 文件后即可认为本次操作成功;然后由后台线程把 WAL 里的操作反映到系统状态里。当数据成功落盘后,系统会定期清理旧的 WAL 文件。整体架构和数据流参考下图。
| 数据一致性
WAL 通过 LSN(Log sequence number,日志序号)来实现数据的一致性。Milvus为用户的每次修改操作分配一个 LSN,这些 LSN 随用户的操作数严格递增。系统通过维护以下这些关键 LSN 点就能保证数据的一致性了:①用户操作的最大LSN;②已经反映到内存但还未落盘的最大LSN;③已经落盘的最大LSN。
用户的修改操作会不断更新①的位置;后台线程把用户操作反映到系统里的过程正是让②不断追上①的过程;同时定时写盘(Auto Flush)机制又让③不断追上②。所以当系统意外退出后,我们只要在下次重启期间比较①③位置就能方便地找到哪些用户操作需要重做。最后根据功能定位,那些③之前的信息已经没有意义了,它们随时可以被删除掉。下图是 WAL 内 LSN 系统的示意图(具体实现时每个集合(collection)会记录下各自集合相关的 LSN,具体逻辑一致就不再展开了)。
对于有实时读写要求的用户,Milvus 提供了同步接口:flush()。当用户调用 flush() 时,该用户线程首先会拿到当前系统的位置①并被阻塞住,直到系统内位置③与其重合才被唤醒并返回。这样待 flush() 返回时,其之前的所有操作都将可见。
flush 可以指定所有集合,也可以指定单个集合。如果用户指定单个集合,为尽可能短的阻塞用户线程,Milvus 内部还会调整执行顺序并优先执行 flush。下面例子是一种可能的调整结果,调整前后对用户效果等价,但用户线程的阻塞时间会明显减少。
|文件及缓存
通过以上介绍,WAL 可以被理解成一个任务队列,用户的修改操作会不断追加在队列尾部,而后台线程又不断从头部消费队列。整个队列需要实时写文件和逐渐清理旧文件。
可以预见,随着系统的运行这个队列有时会变空(后台线程消费完了而用户不再有新的修改操作),有时又会很大(用户一次性插入大量数据,为保证操作原子性必须等整个操作全部写入 WAL 后,后台线程才能开始消费)。而我们需要在不阻塞用户线程的情况下,让 WAL 运行在一个限定大小的内存空间里。
Milvus 在这里使用了双缓冲区。初始时读写指针指向同一片数组;当写指针写到数组尾部时,会判断读指针是否和自己共享同一片缓冲,若是则新数据写往另一片缓冲,否则当前缓冲从头写起;而读指针在追赶写指针时,发现读到缓冲尾部时需判断另一片缓冲的内容是否是当前内容的下一片,若是则从下一片缓冲头部读起,否则需要把下一片内容从磁盘加载到当前缓冲。具体分类示意图见下:
不难证明,该策略在最坏情况下每个 WAL 文件会有一次额外加载的性能损耗。而这也正是我们配置和使用中应该尽量避免的。
|配置和使用
关于 WAL,Milvus 为用户提供了以下几个配置参数:
- enable
是否启用 WAL 组件,默认值 true。启动 WAL 会在一定程度上(取决于系统 IO)影响系统的插入性能,如果用户非常在意系统的插入性能可以选择关闭 WAL。即使关闭 WAL,flush 接口依旧有效。
- recovery_error_ignore
系统重启恢复数据期间是否无视 WAL文件损坏,默认值 true。如果设置成 false,系统恢复数据若发现 WAL 文件损坏,将直接退出。
- buffer_size
WAL 缓存大小,默认值256,单位 MB,合法区间 [64, 4096]按前文介绍,缓存大小会直接影响系统运行期间 WAL 文件是否有一次额外加载的性能损耗。如果用户有批量数据导入,建议把缓存值设为单批次导入数据量的2倍以上。
- wal_path
WAL 路径,默认值 Milvus 数据路径下的wal目录用户可以使用默认路径。不过考虑到 WAL 有频繁的文件读写操作,如果硬件允许,用户可以把它指定在高速磁盘上。
|结语
WAL 是 Milvus 新版存储系统的一部分,通过它可以有效提高用户数据的可靠性。在实现上,我们让它尽可能短地阻塞用户线程以缩短系统响应时间。除此以外,Milvus 的其它功能和优化我们还在持续开发,欢迎各位继续为我们提供宝贵意见和建议。
欢迎加入 Milvus 社区
http://github.com/milvus-io/milvus| 源码
http://milvus.io| 官网
http://milvusio.slack.com| Slack 社区
http://zhihu.com/org/zilliz-11/| 知乎
http://zilliz.blog.csdn.net| CSDN 博客
今天关于《Milvus之WAL介绍》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
214 收藏
-
155 收藏
-
485 收藏
-
436 收藏
-
125 收藏
-
174 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习