微软KV Store Faster如何巧妙实现1.6亿ops

作者:叶提
Faster实现主要分为三部分:

Epoch Protection框架,实现并发系统下全局修改,延迟同步到所有线程,简化并发设计。faster线程在大多时候不需要同步,完全独立执行。

支持高并发的无锁hash 索引,是实现高吞吐的关键。

Hybrid Log,使用逻辑地址将内存和二级存储统一起来,数据超出内存大小后可flush到硬盘,使其能够支持超出内存大小的数据量。

Faster的限制包括:只支持点查,不支持range query;基本只适合update-intensive的场景;不写wal(影响update性能),恢复后部分数据丢失。

Instrduction

faster支持三种接口,read和两类update: blind update和read-modify-writes(RMWs)。RMWs指在原来的value上原子更新,支持记录的部分更新(比如只更新value的一个字段)。faster是一个point-operation系统,在内存中可实现亿级别的吞吐,尤其在支持超过内存限制的数据量下依然能保持如此高的性能。可见在设计和实现上的确做了比较大的努力和创新的。

首先为支持可扩展的线程模型,faster扩展了标准的epoch-based同步机制,通过trigger action促进全局changes延迟同步到所有线程,这个epoch框架帮助faster简化了并发设计。

然后介绍了无锁、高并发和cache友好的hash索引的设计,与纯内存allocator结合使用时,就是一个内存的kv系统,性能和扩展性高于其它热门的纯内存结构。

最后介绍了HybridLog。log-structuring技术可以支持超出内存限制的大数据量的存储,通过写wal支持failure recovery,基于read-copy-update的策略,记录的更新都是追加写的方式写入log中。但是这样的方式限制了吞吐和扩展能力,in-place更新是性能的关键。因此,faster提出了HybridLog:内存与append-only log的方式结合,热数据支持in-place更新,冷数据read-copy-update,先copy到热数据区域再in-place更新。

faster遵循大多数case可以fast的原则,在以下三个方面做了精细的设计:

1.实现无锁高并发的哈希索引对于记录提供快速的point访问。
2.选择合适的时机做耗时的操作,像hash索引扩容、checkpoint和淘汰等。
3.大多数时候可以做in-place更新。

faster在内存负载下的性能是远超出于其它纯内存系统的,而且是在支持数据量超出内存限制和支持热点数据集变化的情况下。

Epoch Protection Framework

Epoch不是新概念,已被Silo、Masstree和Bw-Tree用于资源回收。faster将其扩展,成为更通用的框架,主要用于memory-safe garbage collection、hash索引表扩容、log-structured allocator的circular buffer的维护和page flushing、page边界维护和checkpoint。

Epoch Basics

系统维护一个sharded原子计数变量E,叫做当前的epoch,每个线程都可以增加它的值。每个线程T都有一个本地的E,用Et表示。线程周期地刷新本地的epoch值,每个线程的epoch值都保存在sharded epoch table中。如果所有线程的本地epoch都比epoch c大,则认为c是安全的。faster额外维护了一个全局的Es,用于记录最大的安全的epoch。对于任意线程T,都满足Es

Trigger Actions

使用trigger action使这个框架具备当一个epoch变为安全时执行任意全局action的能力。当前的epoch从c增加为c+1时,线程额外关联一个action,该action在epoch c变为safe时触发。

Using

对于线程T支持4种操作:

Acquire: 为T保留一个entry,将Et设置为E

Refresh: 更新Et到E

BumpEpoch(action): 更新c到c+1,

Release: 将T的entry从epoch table中移除

使用trigger action的epoch在并行系统中可以简化延迟同步。一个典型的例子:当共享变量status变为active时,需要调用函数active-now。线程更新自己的status到active,并将active-now作为trigger action,并不是所有线程可以立马看到status改变,但是可以保证当线程refresh它的epoch时可以看到。因此只有当所有线程都看到status变为active才会调用active-now。

THE FASTER HASH INDEX

faster高性能hash index的特点有concurrent、latch-free、scalable和resizable。与普通的hash table实现不一样,不保存key值,保存记录set的物理或者逻辑地址,纯内存下是物理地址,混合存储下是逻辑地址。

索引组织

22.png

该设计假设64位系统cache line大小为64bytes。索引有2^k个hash bucket,每个bucket的size为cache line的大小:64bytes。一个bucket包含8个entry和一个指向下一个bucket的指针。8字节entry的设计可以使用64位原子的操作。

64位的机器上,物理地址通常小于64位,intel机器使用48位的指针。因此它这里只用48位来存储地址,剩余15位叫做tag,用于hash,一位叫做tentative bit,用于insert过程中的两阶段算法。

索引操作

hash index建立在一个保证的基础之上:每个(offset, tag)对应唯一一个entry。address指向记录的set,这点跟普通hash table很不一样,hash index中不保存key,而是指向记录的set,将冲突放到value中解决。

支持以下操作:

finding and deleting an entry: 根据key值直接定位到bucket中的entry,先根据offet定位到对应bucket,再遍历找到匹配tag的entry。删除entry使用CAS原子操作用0替代掉匹配的entry。0表示是空的entry,可以使用。

23.png

inserting: tag不存在时,insert到一个新的entry。图3(a)展示了通常的操作方式,遍历bucket中的entries找到空的entry,使用CAS将新的tag insert,但是存在两个线程并发将相同的tag写入的问题。如图3(a)所示,T1从左到右遍历entry找到第5个entry并写入g5,与此同时,T2将g3删除,然后从左到右遍历entry找到第三个entry并写入g5。

这个问题的本质原因是线程独立地选择entry并且直接修改它。可以使用lock bucket的方式来解决,但是太重了。faster使用无锁的两阶段的方式来解决,借助于tentative位,线程找到空的enty写入新的记录并设置tentative位,一个被设置了tentative位的entry对于读写是不可见的,然后再重新扫描bucket检查是否存在相同的tag,如果存在则返回重试,否则重置tentative位完成insert操作。图3(b)展示了这个操作。

In-memory, Log-Structured and HybridLog

论文先讲了纯memory实现和纯log-structered的实现,最后将两者结合起来形成最终的HybridLog。

记录的格式为图2所示由8个字节的header、key和value组成,key和value可以是定长也可以是变长的,header分为16位的meta和48位的地址,用少量的位保存一些log-structured allocator所需要的信息,地址用于维护记录链表。

In-memory

纯memory的实现中,记录只保存在memory中,使用底层分配器像jemalloc分配内存,hash index中保存物理地址,支持read、update and insert和delete操作:

reads:根据key定位到hash index的entry,遍历记录list找到key值对应的记录。

updates and inserts:支持blind update和RMW update,使用in-place更新的方式。在epoch protection下,线程可以安全的in-place更新记录。如果entry不存在,按照上述hash index的两阶段方式写入,如果list中找不到此记录,使用CAS操作原子地将新记录写入到list的尾部。

deletes:使用CAS操作将记录从list中移除,当entry删除时,将entry设为0,标识entry是空闲可用的。删除记录后,内存不能立马释放,因为可能有并发的update存在,faster使用epoch protection解决,每个线程维护一个thread-local的空闲,当epoch变为safe后可以将其释放。

Log-Structured

24.png

纯log-structered的实现中,使用逻辑地址将内存和磁盘统一起来,用追加log的方式将记录写入。可以支持大数据量存储,论文第7章测试了性能不超过2000w的ops,也不可随着线程数scale。实现上使用两个offset分别维护内存的最小逻辑地址和下一个空闲地址的offset,称为head offset和 tail offset。内存分配总是从tail offset处分配,head offset与tail offset之间的空间是内存的容量,这里叫做Circular Buffer,是定长pages组成的array,与物理page对应。

为实现无锁的方式将记录flush到磁盘上,引入了两个状态数组,flush-status记录当前flush磁盘的page,closed-status决定是否page可以被淘汰。要淘汰的page必须要保证已经完全flush到磁盘了。当tail offset增大时,使用epoch机制的trigger action触发异步io请求将page flush到磁盘,epoch安全后调用,确保所有线程在这个page上的写都完成了,设置flush-status。

随着tail offset的增长,头部page需要从内存中淘汰,需要先确保page没有线程在访问,传统数据库一般使用latch pin住这个page,faster为了实现高性能,还是借助于epoch管理淘汰。

Blind update就是简单的将新的记录append到log的尾部。delete记录通过header中标志位识别,资源回收时会识别。Read和RMW操作与内存中相似,只是update是追加写一条新记录,逻辑地址跟纯内存中的物理地址处理也不同,如果地址大于head offset,则数据在内存中,否则提交异步的读请求到磁盘。

HybridLog

log-structured可以处理超出内存大小的数据量,但是append-only的特征会带来一些代价:每次update都需要原子更新tail offset,拷贝数据,原子更新hash index中的逻辑地址。而且update-intensive的负载下,很快会到io瓶颈。在这种负载下,in-place更新有以下优点:

1.频繁访问的记录可放在更高层级的cache中

2.不同hash桶的key值访问路径不会有冲突
3.large value的部分更新可以避免复制整个记录
4.大多数更新不需要修改hash index

25.png

HybridLog将Log分为了三个部分:stable 磁盘部分、read-only和mutable部分。统一为一套逻辑地址,read-only和mutable都在内存中,其中只有mutable部分可以原地更新,保存hot data,read-only部分的数据更新操作需要先将其copy一份到mutable中,再在mutable中原地更新。

随着tail offset的增长,mutable头部的数据转换为read-only,read-only头部的数据刷到磁盘中。可以看出比较适合更新集中的应用场景。相比log-structured,增加了read-only offset,原理和head、tail offset类似,read-only offset将可以in-place更新的mutable部分和immutable部分分开。

HybridLog内存部分可以看作是一个缓存,性能基本取决于它的效率。数据库缓存和操作系统下的内存管理通常有fifo、clock、lru和lru的变种等,这些算法(除fifo外)都需要细粒度的统计信息才能很好的工作,faster没有这些overhead,比较类似Second-Chance的FIFO。

faster数据分布取决于访问模式,一段时间后热点数据逐渐集中在内存中。mutable和read-only region的内存划分是尤其重要的。mutable部分较大可以使内存性能更好,in-place更新更多,但是可能会使得mutable的部分数据也面临淘汰的问题。较大的immutable region会导致过多昂贵的append-only update,copy到mutable使得log较快增长。论文提到实验得出,9:1的比例对于mutable和immutable的划分可以有比较好的性能。

Recovery

faster将update性能放在首位,写wal会影响update性能,所以不写wal,进程failure后内存中的数据就丢了。

不过它可以恢复到consistent状态,比如任意两个更新请求r1和r2,是被一个线程顺序提交的,恢复后可能的状态:1. none 2. only r1 3. r1 and r2。也就是不会出现只有r2而没有r1的情况。

测试

论文对比了高性能的内存结构Masstree和Inter TBB hash map,以及两个热门的kv store RocksDb和Redis。

单线程下,uniform分布和zipf分布数据。faster表现最好TBB其次rocksdb表现最差。

256线程下,uniform分布达到1.1亿,TBB也接近这个数值,zipf下faster可以将热点数据集中在mutable区域,性能达到1.6亿,与其它系统拉出了明显差距。

扩展能力测试,faster在单cpu和多cpu下的scale能力都很好,masstree也不错但是性能差很多。TBB单cpu的scale能力很好,但是多cpu下比较差。详细的测试内容,大家可以自行查看论文。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/516178.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当飞猪遇上 Serverless | 云原生 Talk

来源 | 阿里巴巴中间件责编 | 晋兆雨头图 | CSDN付费下载于视觉中国前言2019 年 3 月,我们跟随着集团的步伐,将 Serverless FaaS 引入到飞猪,并取得了一定的阶段性成果:这一年,我们参与共建了 Node FaaS 研发平台和稳定…

vue ui 面板创建项目安装 axios 时,浏览器卡死的解决办法

目录 踩坑记1. 问题场景2. 解决办法踩坑记 Vue UI 可视化面板创建新项目,当安装完插件,再安装 axios 依赖时,点击 “ 安装 axios ” 按钮居然毫无响应,此时浏览器卡死、cmd 终端无法关闭,更杯具的是,CPU 占用率 100%,也无法关机或重启电脑 😂 。 1. 问题场景 2. 解决…

EdgeRoutine技术专家教你把JS代码跑到CDN边缘

4月27日CDN云课堂中,阿里云智能技术专家洪晓龙在线分享《阿里云CDN轻量编程环境》,对EdgeRoutine的背景、功能、案例实践介绍并在线进行上手操作演示,希望更多用户能够使用CDN轻量编程环境服务自主编程、快速落地实际线上业务。本文为直播分享…

使用手机企业微信创建自己的企业(公司)

文章目录1. 登录企业微信2. 管理企业3. 全新创建企业4. 补充信息5. 效果图1. 登录企业微信 登录手机企业微信,选择设置 2. 管理企业 3. 全新创建企业 4. 补充信息 补充信息全新创建 所在企业:自己给公司起一个名称 行业类型:随机一个或者…

淘宝万亿级海量交易订单存储在哪?

01淘宝交易订单系统介绍 天猫和淘宝每天发生的实物和虚拟商品的交易达到亿级别。考虑到一次成功交易的整个链路,会涉及到会员信息验证,商品库信息查询,订单创建,库存扣减,优惠扣减,订单支付,物…

vue 单文件组件中,输入template 按 tab 键不能自动补全标签的解决办法

1. 操作步骤 选择: 文件 ⇒ \Rightarrow ⇒ 首选项 ⇒ \Rightarrow

企业微信_新建自建H5小程序应用及主页与菜单设置

文章目录一、新建自建H5小程序应用1. 登录企微管控台2. 登录登录手机企微3. 应用管理4. 创建应用5. 效果图二、主页与菜单设置2.1. 应用主页2.2. 菜单设置2.3. 主页与菜单设置的区别一、新建自建H5小程序应用 1. 登录企微管控台 登录企业微信管理后台 2. 登录登录手机企微 …

阿里云助力1药网开辟疫情防控“第二战场”

这一切都要从那天清晨说起 ”人民日报的带货能力太强大了,昨晚一大波流量进来抢药,我们的服务器快撑不住了,谁能帮忙看看这个线上问题?”在大年初七的清晨,1药网的IT总监在阿里云至尊服务群上紧急地寻求着帮助。此时的…

阿里云资深技术专家易立:我对云原生软件架构的观察与思考

来源 | 阿里巴巴中间件作者 | 易立,阿里云资深技术专家,容器技术负责人头图 | CSDN付费下载于视觉中国前言云原生计算包含三个维度的内容,云原生基础设施,软件架构和交付与运维体系,本文将聚焦于软件架构层面。

【MySQL】 如何在“海啸”下保命

作者:田杰 在数据库的日常使用中,来自应用的高并发场景并不罕见,其标志性的表现为 高新连接创建速率(CPS,比如 PHP 短连接)、发送大量请求到 DB 数据库层。 如同 海啸,大量的新建连接和请求猛烈…

企业微信H5_自建应用连接H5

文章目录1. 进入自建应用2. 自定义菜单3. 添加主菜单4. 补充信息5. 点击发布6. 登录手机企微7. 点击菜单8. 第2种效果1. 进入自建应用 找到自建的应用 2. 自定义菜单 点击-自定义菜单-已启用 3. 添加主菜单 点击-添加主菜单 4. 补充信息 补充信息-点击保存 主菜单&a…

【MySQL】时区设置引发的卡顿

作者:田杰 查询执行时间长引发应用感知 “卡顿” 的场景在数据库的日常支持和使用中并不少见,但由于时区设置引发的 SQL 执行“卡顿”仍然是一个有趣的现象,之前没有具体关注过。 这次客户的细致与坚持让我们找到了问题的源头。 1. 名词解释…

老码农90%的程序猿都是瞎努力,这份路线教你成为高手!

数据正在变得越来越常见,小到我们每个人的社交网络、消费信息、运动轨迹……,大到企业的销售、运营数据,产品的生产数据,交通网络数据……如何从海量数据中获得别人看不见的知识,如何利用数据来武装营销工作、优化产品…

企业微信_H5应用如何本地及真机调试_host配置及代理相关

文章目录一、准备工作1. 下载SwitchHosts2. 创建vue项目3. 启动项目3. 请求验证4. 域名访问5. Invalid Host header二、电脑调试2.1. 设置应用主页2.2. PC企微登录2.3. PC企微应用2.4. 更新验证2.5. 跳转页面三、手机调试3.1. 代理软件3.2. 安装,启动3.3. 连接无线网…

揭秘MySQL生态重要功能,X-Engine引擎核心能力——OnlineDDL

概述 X-Engine是阿里自研的数据库存储引擎,以插件的方式接入到MySQL生态,支持行锁,事务,MVCC等OLTP场景的核心功能。 X-Engine的核心优势是低成本,高性价比,尤其适用于历史库场景,目前阿里巴巴…

企业微信_获取access_token

文章目录一、快速入门1. 开发文档2. 管控台3. 接口文档4. 参数获取5. api调试二、java实战2.1. 入口2.2. 核心方法2.3. 核心配置2.3. RestUtils 工具类2.5. token缓存策略三、源码分享3.1. 后端源码3.2. 前端源码一、快速入门 1. 开发文档 企业内部开发文档: http…

荷兰政府用大数据预测天气预防自然灾害,他们是怎么做的?

作者 | 乔治娜乌斯蒂克翻译 | Katie责编 | 晋兆雨头图 | CSDN付费下载于视觉中国你是否对天气预报电视报道的背后的运作感到好奇?是谁在管理政府卫星?也许你会思考关于传感器的一个问题——数据会流向何处? 在荷兰,这些数据是由KN…

Excel VBA Sql 操作Access数据库

目录 1. 文件创建2. 数据库连接2.1 前期和后期绑定2.2 通过判断 Excel 的不同版本,给出不同的连接字符串2.3 Excel 自连接3. 应用:增、删、改3.1 增加数据的语法3.2 删除数据的语法3.3 修改数据的语法4. 结语1. 文件创建 首先,我们需要在预先设置的路径下新建Excel工作簿。…

企业微信小程序_小程序开发工具及真机调试_host配置及代理

文章目录一、开发前准备1. 开发文档2. 工具安装3. 安装插件4. 调整编译模式5. 选择企业6. PC 调试前端7. PC 调试后端二、甄姬调试前端2.1. 预览小程序2.2. 手机企微扫码2.3. 手机企微调试2.4. 多场景调试2.5. 手机企微调试前后端一、开发前准备 1. 开发文档 小程序开发文档&…

别再盲目学Python了!

如果你想问最近这些年什么编程语言最值得学习,我会毫不犹豫的告诉你是Python。无论是刚入门的程序员,还是年薪BATJ的技术大牛,都无可否认现在Python对于一个程序员职业发展的重要性。所以不仅是开发小白,甚至很多开发老手&#xf…