【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store

HotRing 热点感知KV索引 有序环哈希

论文阅读笔记

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store

https://www.usenix.org/system...

huazhong

简介

背景、动机

  • 热点问题很普遍。如:阿里生产环境中,50%~90%的访问,只涉及1%的数据。
  • 内存KV结构的热点问题不被重视,大多数KV结构不能感知热点。
  • 目前内存KV结构减少热点访存的方法有局限:CPU cache太小;rehash(为减少冲突)不适合本身巨大的表,且性能提升有限。

主要思想

设计热点感知的内存KV结构——有序环哈希结构。

主要挑战及应对方法:

  • 热点转移:把冲突链改为环。头节点移动到热点项;两种策略检测热点转移。
  • 高并发访问:使用无锁结构,实现插删,并扩展到热点特定操作(热点转移检测、头指针移动、有序环rehash)。

贡献

  • 支持快速访问热点数据。
  • 有轻量的运行时热点转移检测策略。
  • 无锁机制,支持高并发访问,贯穿热点特定操作(热点转移检测、头指针移动、有序化rehash)。
  • 真实环境测试,高度不平衡的负载实验,2.58x。

有序环

把冲突链改为有序环结构。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第1张图片

$order_k = (tag_k, key_k) $。 对冲突环以 tag-key 方式排序。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第2张图片
查找。不命中:

image

不命中,平均只需要查找一半的元素(冲突链则需要遍历整条)。

热点转移识别

两种衡量:accurancy、反应延迟。

把头指针移动到热点项。

随机移动

每隔R个请求,若第R个请求不是访问热点项(指头指针所指元素),则将头指针指向当前访问项。不需历史统计数据,移动到潜在热点项。

实现简单,反应时间较快。

R小,反应延迟可能小,但会造成频繁的指针移动,低效。实验表明,R = 5 较好。

缺点:

  • 识别精度低。
  • 负载倾斜不明显时,该方法低效。
  • 若冲突环有多个热点,无法应对,频繁的移动反而影响其他操作

统计采样

识别精度更高,反应延迟稍长。可以应对环上多个热点的情况。

索引格式

利用头指针、item的剩余16bit空间。

active:控制统计采样。 total count:统计采样时环的总访问次数。

rehash:控制rehash。 occupied:控制并发,保证并发访问的正确性。 counter:某一项的访问次数。

address:下一项的地址。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第3张图片

统计采样:每R个请求,若第R个请求不是访问热点项(指头指针所指元素),则触发采样:active位置1(需CAS原语),之后对该环的访问都会被计数(total counter 和 counter),采样的次数等于该环item的个数。

热点挑整

计算每一项 $t$ 的income:$ W_t = \sum \limits_{i=1}^N \frac{n_i}{N} \cdot [(i-t)mod k ] $. ($n_i$:项$i$ 的计数, $N$:总计数 $k$ : 环长)

$W_t$ 衡量的是:将头指针指向 $t$ 后,该环的平均访存。

选择$W_t$ 最小的项$t$,作为新热点。 使用CAS 原语来移动头指针。最后重置计数器。

可处理多个热点。

RCU

RCU:read-copy-update。小于8B的value,可用CAS原地更新。大于8B的,需用RCU更新。这时需遍历整个环来获取前驱结点,因而,写密集热点会让它的前驱变热。因此,需修改统计采样法。

对RCU更新,增加其前驱的counter,而非其本身counter。这可助头指针指向写密集热点的前驱,加速RCU修改。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第4张图片

热点继承

头节点发生RCU更新或删除。

  • 若环只有一项,用CAS更新头指针即可。
  • 若环有多项:若头节点RCU更新,将头指针指向新版的头(因为它被再次访问的概率高);若头节点删除,则头指针移到下一项,

并发

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第5张图片

  1. 读:不需要额外机制,无锁。
  2. 插入:创建新节点,修改前驱的next指针。使用CAS操作,防止两个线程同时修改同一个next item address,一个成功一个失败,失败的需重新执行操作。
  3. 更新:
  • 小于8B,CAS更新。
  • RCU更新则需要创建新节点,替换旧节点,有并发问题。(图8)

    • 进程1在B后插入C,进程2将RCU更新B。若用CAS,则会成功,因为它们修改的是不同的指针。出错。
    • 进程1RCU更新B,进程2RCU更新D。若用CAS,则两个操作都会成功,而D‘将无法访问,出错。
    • 进程1RCU更新D,进程2删除B。将导致D’无法访问,出错。
  • RCU更新,更新项occupied位置1。如插入&更新,要RCU更新B,需将B的occupied置1,此时C插入会失败,稍后,A的next指针指向B‘,B’的occupied为0。
  1. 删除。被修改项的occupied置1,改完其前驱的next后再置回0。如,删除B,B的occupied置1,此时找D的前驱会不命中,D更新失败,需重来。
  2. 头指针移动。移动头指针时,需检查其他操作,防止头指针指向无效项;删除或更新时,需要检查头指针是否指向它。

    • 将头指针移到一项时,将该项的occupied置1,防止该项更新、删除。
    • 头节点更新,将新头的occupied置1,再移动头节点。
    • 头节点删除,将头、头的后续的occpuied置1,再移动头节点。

无锁 rehash

传统rehash,由负载因子触发。这不适用于热点处理。HotRing 使用访问开销(检索一个item的平均访存次数)来触发rehash。(怎么计算 采样还是?)

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第6张图片

初始化

创建rehash线程,初始化一个两倍大小的哈希表,共用tag的最高位。用来hash的部分从 k 位变为 k+1位,tag则减少一位。设hash value有n bit,旧表的tag范围[0, T),T = 2^(n-k),则两个新头指针分别对应[0, T/2),[T/2, T)。

同时,创建一个rehash node,包含两个子哈希项,其tag分别为0、T/2, rehash 位均为1,里面不存有效KV对。

分割

rehash线程将两个rehash item插入到环中,插入后,新表被激活。如图,分别插入到B前、E前。

这样,此时通过old head访问,可以通过检查rehash位跳过rehash item,后续的通过new head访问新表也能正常。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第7张图片

删除

过渡期:等待所有通过old head访问的操作结束。然后就可以删除旧表和 rehash node,真正拆成两个环。

注意,过渡期只会阻塞rehash 线程,不会阻塞access线程。

(new head1指向old head,new head2 指向tag > T/2的下一项吗?)

实验

baseline:chaining hash(用HotRing的无锁机制), FASTER, Masstree, Memcached。

HotRing-r(用随机采样),HotRing-s(用统计采样)。

  • 单线程、64线程下,比较吞吐量。
  • 不同冲突链长度(key-bucket率从2到16),比较吞吐量。
  • 负载倾斜率(不同zipfian 分布参数,记为$\theta$ ),比较吞吐量。
  • 用YCSB产生写密集负载,进行RCU实验,测吞吐量。
  • 测break-down cost。

其他:(用两种HotRing,chaining hash)

  • 改变负载,即发生热点转移,通过测吞吐量,分析反应延迟。
  • 用read miss负载,测吞吐量,以分析三种机制处理read miss的性能。HotRing更好,因为它们平均只需要查找一半的元素,而冲突链需要遍历整条。
  • 不同R下,测吞吐量,以找最优的R。
  • 尾延迟。统计采样周期最后一个线程需要计算,会有尾延迟。不同$\theta$下,测access 延迟随acess ratio的变化。
  • 检验rehash。250百万key,key-bucket ratio = 8。YCSB产生50%读、50%插入的负载,模拟哈希表增长。这里,I、T、S分布表示rehash的初始化、过渡期、分割。可知,rehash操作,能使得吞吐量恢复到增长前的水平。短期的陡降是因为新哈希表短期的热点感知匮乏。

【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store_第8张图片

后续工作

随机移动针对只能应对冲突环上单个热点的情况,随机采样可处理多个热点。很多情况下,可以通过rehash拆分热点。但是极端情况下,这会失效。作者称将继续探索。

个人体会

链改环,采样,设置几个flag控制并发,本文的设计思路很清晰自然,虽然是常规的想法,但整合成了漂亮的系统设计。

实验做得很充分,通过各种对照,分析各项设计带来的性能提升,值得学习。

一些困惑:

  • 这种结构有没有更好的热点转移识别方法?
  • RCU更新,需要遍历环来获得前驱,理论上来看对于高并发的RCU写密集的负载不友好吧(实验结果倒好),但是设置前向指针又浪费空间得不偿失。
  • Rehash过渡期(即插入rehash node之后,分割前),发生RCU 更新需要阻塞吗?
  • 是否可以把统计采样周期末尾的额外计算交给专门的线程,以减少尾延迟?
  • 这种热点感知方法可以迁移到关系数据库、或者LSM结构上吗?

你可能感兴趣的:(【FAST'20】HotRing: A Hotspot-Aware In-Memory Key-Value Store)