摘要
许多社交媒体和物联网服务都有非常大的工作集,由数十亿个微小(100 B)对象组成。大型的、基于闪存的缓存对于以可接受的货币成本为这些工作集提供服务非常重要。然而,在flash上缓存微小的对象是有挑战性的,原因有两个:(i) ssd只能在比单个对象大得多的多kb页面中读写数据,这强调了flash可以写入的次数有限;(ii)在不失去闪存的成本优势的情况下,每个缓存对象可以在DRAM中保存很少的比特。不幸的是,现有的闪存缓存设计未能解决这些挑战:写优化设计需要太多的DRAM,而DRAM优化设计需要太多的闪存写。
我们介绍Kangaroo,一个新的闪存缓存设计,优化了DRAM使用和闪存写入,以最大化缓存性能,同时最小化成本。Kangaroo结合了一个大的,集合关联的缓存和一个小的,日志结构的缓存。集合关联的缓存只需要最少的DRAM,而日志结构的缓存则将Kangaroo的闪存写操作最小化。使用Facebook和Twitter的跟踪数据进行的实验表明,Kangaroo的DRAM使用接近于最佳的事先DRAM优化设计,闪存写入接近于最佳的事先写优化设计,且漏写率比两者都好。Kangaroo的设计是帕累托最优的范围内允许写率,DRAM大小和闪存大小,减少了29%的失误比目前的先进水平。Kangaroo的设计是帕累托最优的范围内允许写率,DRAM大小和闪存大小,减少了29%的失误比目前的先进水平。 这些结果在Facebook的一个生产闪存的测试部署中得到了证实。
1、介绍
许多web服务需要快速、廉价地访问数十亿个微小对象,每个对象只有几百字节或更少。例如社交网络,如Facebook或LinkedIn;微博服务,如Twitter;电子商务;以及物联网中的新兴传感应用。考虑到这些应用程序的社会重要性,对于高性能和低成本(即资金和操作费用)的缓存微型对象有很强的需求。
在现有的内存和存储技术中,闪存是目前性价比最高的。DRAM和非易失性存储器(nvm)具有出色的性能,但两者的价格都比闪存高一个数量级。因此,使用大量的闪存和最小的DRAM的成本争论。
Flash的主要挑战是它的写入耐力有限;也就是说,flash在磨损之前只能被写入一定次数。磨损对于小对象来说尤其是个问题,因为flash只能在多kb的粒度下进行读写。例如,写一个100b的对象可能需要写一个4kb的flash页面,将写入的字节增加40倍,并迅速耗尽flash设备。因此,最大限度地减少写入闪存的多余字节也是成本问题。
这个问题。以前的闪存缓存设计要么使用了太多的DRAM,要么写了太多的闪存。日志结构的缓存顺序地写对象到闪存,并保持一个索引(通常在DRAM中),跟踪对象在闪存中的位置[20,35,47,63,64,67]。通过顺序地写入对象,并批处理许多插入到每个闪存写入中,日志结构的缓存大大减少了写入闪存的多余字节。然而,跟踪数十亿个微小的对象需要一个大的索引,甚至一个高度优化的索引也需要大量的DRAM[35]。集合关联缓存通过哈希对象键到不同的集合进行操作,很像CPU缓存[16,25,55]。这些设计不需要DRAM索引,因为一个对象的可能位置是由它的键暗示的。然而,集合关联缓存会将许多多余的字节写入闪存。将单个小对象写入缓存需要重写整个对象集,这大大增加了写入闪存设备的字节数。
我们的解决方案:袋鼠。我们将介绍袋鼠,一种新的闪存缓存设计,可用于数十亿个小对象。关键的观点是,现有的缓存设计都解决了问题的一半,它们可以结合在一起,克服彼此的缺点,同时放大它们的优点。
袋鼠采用了层次化的设计来达到日志结构和集合关联缓存的最佳效果(图1a)。为了避免大的DRAM索引,袋鼠将大量的缓存容量组织成一个集合关联的缓存,称为KSet。为了减少写闪存,袋鼠在KSet前面放了一个小的(例如5%的闪存)日志结构的缓存,称为KLog。KLog缓冲了许多对象,在KSet中寻找映射到同一集合的对象(例如,哈希冲突),这样每次写入KSet的闪存都可以插入多个对象。我们的见解是,即使是一个小的日志也会产生许多哈希冲突,所以只需要少量的额外DRAM(用于KLog的索引)就可以显著减少闪存写入(在KSet中)。
在“袋鼠”的设计中,各层相互补充,以最大限度地提高命中率,同时降低闪存和DRAM的系统成本。袋鼠算法引入了三种技术,有效地实现了其分层设计,提高了其有效性。首先,袋鼠的分区索引可以在使用最少的DRAM的情况下,高效地找到KLog中映射到KSet中同一集合的所有对象。其次,由于袋鼠是一个缓存,而不是键值存储,它可以自由删除对象,而不是将它们招收进KSet。袋鼠的阈值允许策略利用了这种自由,只在有足够的哈希冲突时才允许对象从KLog到KSet,也就是说,只有在闪存写操作被充分摊平的情况下。第三,袋鼠的RRIParoo逐出策略通过支持KSet中的智能逐出来提高命中率,尽管KSet缺乏跟踪逐出元数据的传统DRAM索引。
总结的结果。我们实现袋鼠作为一个模块在CacheLib[16](可在cachelib.org)。我们通过在真实系统和模拟灵敏度研究中重现生产轨迹来评估袋鼠。先前的设计受到DRAM使用量或闪存写入速率的限制,而袋鼠则针对这两个限制条件进行了优化。例如,在典型的DRAM和闪存写预算下,《袋鼠》在Facebook的生产跟踪中降低了29%的遗漏率(图1b),将遗漏率从0.29降低到0.20。此外,在仿真中,我们表明袋鼠可以很好地扩展闪存容量,在不同的DRAM和闪存写预算下也能很好地执行,并能很好地处理不同的访问模式。我们将详细分析袋鼠的技术,看看每个技术的贡献有多大。最后,我们通过在Facebook的一个测试部署,展示了袋鼠在现实世界中的优势。
贡献。本文的主要贡献如下:问题:我们表明,对于微小的对象,先前的缓存设计要么需要太多的DRAM(日志结构的缓存),要么需要太多的闪存写(集合关联的缓存)。关键思想:我们展示了如何结合日志结构和集关联设计以低成本在flash上缓存微小对象,并给出了这个设计的理论依据。袋鼠式设计,实现:袋鼠引入了三种技术来实现和改进基本设计:它的分区索引、阈值准入和RRIParoo驱逐。这些技术提高了命中率,同时保持DRAM使用、闪存写入和低运行开销。结果:我们显示,不像以前的高速缓存,袋鼠的设计可以处理不同的DRAM和闪存写预算。因此,袋鼠是帕累托最优的范围内的约束和不同的工作负载。
2、背景和相关工作
本节讨论依赖数十亿个微小对象的重要应用程序,为什么需要flash来缓存它们,flash带来的挑战,以及现有的flash-cache设计的缺点。
2.1微型对象是重要且数量众多的
在许多大型系统中,小对象非常普遍:
在Facebook,小对象普遍存在于社交图中。例如,社会图的平均边缘大小小于100 B。通过边缘、节点和其他对象,平均对象大小小于700 B[16,25]。这导致了针对小对象[16]的专用闪存缓存系统的开发。
在Twitter上,tweet被限制在280b,并且tweet的平均长度小于33个[57]字符。由于大量且不断增长的tweet, Twitter寻求一种经济有效的缓存解决方案[76]。
在微软Azure,一个日益增长的用例是处理来自传感器数据的更新,比如来自Azure流分析中的物联网设备。在处理一个更新(例如,触发一个实时操作)之前,服务器必须获取平均大小为300b的元数据(传感器的测量单位、地理位置、所有者等)。为了提高效率和可用性,服务器缓存最流行的元数据[38]。另一个用例出现在搜索广告中,Azure缓存预测和其他结果[48,49]。
每个系统都访问数十亿个对象,每个对象都大大低于块存储设备的最小写粒度4 KB。 例如,Facebook每天记录15亿用户的[9],单是好友连接,每个用户就有数百到数千条边[25,68]。 Twitter每天有超过5亿条新推文,每天有超过1.9亿的用户。 虽然物联网更新频率和广告印象并不公开,但据估计,在2020年[33],连接设备的数量在上超过了500亿,而且据估计,早在2007年,平均每人每天就会看到5000个广告[65]。
2.2在flash中缓存微小的对象是困难的
虽然上述应用程序中的各个对象都很小,但各个服务器上的应用程序工作集的数据总量仍然高达tb。为了降低后端数据管理系统的吞吐量需求,应用程序依赖于大规模、经济高效的缓存,因为一个缓存服务器可以取代数十个后端服务器[16]。不幸的是,正如下面所述,当前的缓存系统对于小对象的效率很低。因此,需要为大量的小对象优化缓存系统。
为什么不使用内存呢?DRAM是昂贵的,无论是在采集和每位的功率成本方面。这使得传统的DRAM缓存难以扩展,特别是当数据大小呈指数级增长时。由于运营方面的考虑,DRAM容量也经常受到限制。数据中心运营商通常提供数量有限的服务器配置,以降低管理复杂性。在一些实际的部署中,为了缓存而调整服务器配置是不可能的[66]。此外,DRAM通常需求量很大,因此所有的应用程序都被鼓励尽量减少DRAM的使用。例如,最近几年Facebook的趋势是减少内存,增加每台服务器的闪存[16,66]。
为什么不使用闪存呢?目前,在内存和存储技术中,Flash提供了性能和成本的最佳组合,因此是大多数大规模缓存的选择技术[16,22,23,35,64]。它比DRAM持久、便宜、节能,而且比机械磁盘快得多。虽然基于闪存的缓存确实使用DRAM来处理元数据和“热”对象,但缓存的大部分容量都是闪存,以降低端到端的系统成本。
flash缓存的挑战。Flash出现了许多DRAM缓存中不存在的问题。一个很大的问题是flash的写持久性是有限的,这意味着在flash设备磨损并必须更换之前,写入的次数是有限制的[24,42,46]。如果不小心,缓存会很快磨损闪存设备,因为它们快速地接收和删除对象[16,35]。因此,许多现有的闪存缓存会过度供应容量,为了减缓耗尽速度而遭受更多的遗漏[16,23]。新的闪存技术,如多层QLC(4位/ cell)和PLC(5位/ cell)[28],提高了容量,降低了成本,但显著降低了写耐力。