一种基于RDMA的键值存储系统及其工作方法与流程

文档序号:18475265发布日期:2019-08-20 20:56阅读:391来源:国知局
一种基于RDMA的键值存储系统及其工作方法与流程

本发明属于rdma和存储技术领域,具体涉及一种基于rdma的键值存储系统及其工作方法。



背景技术:

随着移动互联网时代的到来,数据量得到了急速增长。像memcached、redis等分布式内存存储系统得到广泛应用。正是因为内存系统取消了磁盘、ssd的限制,数据存储在系统内存中,所以极大地加速了应用的性能。但是,在一些大型的可扩展的应用中,系统的网络通信往往花费几百微秒,这也成为了应用中新的性能瓶颈。为了提高网络性能,一些内存存储系统使用了rdma。rdma可以直接访问远端节点的内存,提供了内核旁路和零拷贝数据传输的优势。与tcp/udp传输相比,rdma可以获得更低的时延、更高的吞吐量。

rdma的ibverbs库提供了双边原语操作send/recv和单边原语操作read/write等特性。send/recv原语提供了用户层的信息交换方式,应用层绕开系统内核直接与网卡适配器进行信息交换。send操作需要远端机器的recv操作相互配合来完成,用户层的应用必须使用网卡提供的api重新改写,才可以进行信息传输。read/write原语允许直接读取或者写入远端机器内存里的数据,而这一过程完全不需要远端机器cpu的参与,远端机器完全无感知。同样用户必须重新改写应用,才可以使用read/write原语。

基于以太网的分布式系统,cpu往往都是很宝贵的资源。通常一台计算机上会运行多个应用程序,这些程序共享操作环境。如果内核和cpu旁路,服务器端只需要使用很少数量的cpu核就可以使网络达到饱和,充分利用网络性能。而rdma的单边操作完成不需要远端机器的cpu参与,有效降低cpu的负载。

由于read/write的远端机器无感知的特性,针对键值存储系统的put操作和get操作的底层实现也就会有变化。现有的基于rdma设计的键值存储针对put操作设计,大多采用轮询线程来监听数据的到来。这虽然有利于性能的提高,但极大地耗费了cpu的资源。而且大多数系统设计的时候都有着数据的拷贝操作,对于数据拷贝需要消耗服务器的cpu的资源。如果value的数据量过大,拷贝就会严重影响系统的性能。

此外,现有的键值存储系统中,总是服务器端处理所有的数据读写请求,而服务器的处理能力总是有上限的。



技术实现要素:

发明目的:针对现有技术的缺陷和不足,本发明提出了新的基于rdma的键值存储系统,减少cpu的数据拷贝操作,降低网络的时延提高服务质量,并提高系统的吞吐量。

本发明的另一目的在于提供上述基于rdma的键值存储系统的工作方法。

技术方案:根据本发明的第一方面,提供一种基于rdma的键值存储系统,所述系统包括:

客户端,向服务器端发起操作请求,对服务器端内存中的数据进行查询或修改;

服务器端,提供存储服务,接收多个客户端的操作请求,根据请求写入数据到内存或者返回查询结果,其中服务器端在启动的时候会向系统申请一块内存,并向rdma网卡进行注册,该块内存包含共享hash表和value存储区两部分,hash表用于记录key与value的映射信息,value存储区用于存储value,客户端与服务器端建立连接的时候会获取该块内存的注册信息,这样客户端就可以通过rdma网卡直接访问该块内存区域。

根据本发明的第二方面,提供上述基于rdma的键值存储系统的工作方法,所述方法包括:

put操作,客户端将key和value存储到服务器端,客户端根据value数据的大小选择rdma不同的传输模式,将key和value存储到服务器端的内存中;

get操作:客户端根据key值获取到相应的value值,客户端使用rdma的read原语从服务器端读取key所对应的value,这个过程完全不需要服务器端参与;

共享hash表:服务器端采用线性探测hash方式记录key与value的映射关系,所有客户端都可以通过rdma操作直接访问该hash表。

进一步地,所述put操作包括:

如果value小于指定阈值s,客户端使用rdma的send原语,将key和value一同发送给服务器端,服务器接收到key和value后,在hash表记录中存储key和value的地址,在value存储区存储value值;

如果value大于或等于指定阈值s,客户端先发送key并请求服务器端分配value存储在服务器端的内存地址,服务器端接收到请求后为value分配存储地址,在hash表记录中存储key和value的地址并将该地址发送给客户端,客户端获得value存储地址后,再通过rdma的write原语直接将value写到服务器端的value存储区。

进一步地,所述get操作包括:

a)客户端通过read原语操作获取相应的key在服务器端hash表上的映射记录,若没有找到key所对应的映射记录,返回空值,否则转步骤b);

b)查询本地缓存是否有对应的key缓存的value数据,若没有,则转步骤c);

c)根据步骤a)获取的value的存储地址,再次使用read原语操作从服务器端读取value值。

进一步地,所述服务器端采用线性探测hash方式记录key与value的映射关系包括:服务器端接收到客户端发来的key以后,通过hash函数计算当前key存储在hash表的位置为桶b=hash(key),如果桶b为空就将key存储在该桶里,否则就从桶b开始线性地往下查找一个空的桶将key存储该桶中。

进一步地,所述服务器端采用线性探测hash方式记录key与value的映射关系还包括:服务器端将连续的b个桶定义为一个块,存储key的时候探测的桶的个数不超过m*b,如果服务器端无法在m*b个桶里为key找到一个空的桶,则将原来的hash表扩展n倍,n>1。

进一步地,所述客户端通过rdma操作直接访问hash表的过程包括:客户端发起get操作,每次按块的大小从hash表中读取记录,查询当前块里是否包含查询的key,如果不包含继续读取下一个连续的块,最多读取m个块。

进一步地,所述hash表的每一条记录都为带有自校验功能的数据结构,自验证数据结构包含:in_use,表示当前的记录是否为空;key,表示实际的键;valuepointer,指向存储value的内存地址;checksum1,表示value的校验和;checksum2,表示整体记录的校验和。

有益效果:和现有技术相比,本发明具有以下优势:

1、高性能:客户端的get操作完全不需要服务器端参与,所有客户端可以并发的请求数据,极大地提高了系统的处理能力。

2、低cpu负载:客户端的put操作会根据value的大小选择不同传输数据模式,如果value过大,会采用rdma的wirte操作直接将value写到服务器端的内存,减少拷贝操作降低cpu负载。同时rdma网络本身就不需要系统内核的参与,系统发送与接收数据不需要用户态与内核态来回切换。

3、高可扩展性:服务器端存储hash表和value的内存都是共享的,客户端对于数据的读取请求不受服务器端性能的影响。

附图说明

图1是本发明的基于rdma的键值存储系统架构图;

图2是本发明的put操作流程设计示意图;

图3是本发明的get操作流程设计示意图;

图4是本发明的自校验数据结构示意图。

具体实施方式

下面结合附图对本发明的技术方案作进一步说明。应当了解,以下提供的实施例仅是为了详尽地且完全地公开本发明,并且向所属技术领域的技术人员充分传达本发明的技术构思,本发明还可以用许多不同的形式来实施,并且不局限于此处描述的实施例。对于表示在附图中的示例性实施方式中的术语并不是对本发明的限定。

图1是本发明的基于rdma的键值存储系统架构图。如图所示,客户端提供4种基本操作:put(key,value),客户端将key和value存储到服务器端;delete(key),删除服务器端的key及其value;get(key),在服务器端查找key对应的value;contains(key),查询服务器端hash表中是否存储key。其中put(key,value)和delete(key)可以看作put类型的操作,都需要对服务器端的内存中的数据进行修改。get(key)和contains(key)可以看作get类型的操作,都是对数据的查询操作,不对数据进行修改。服务器端,提供存储服务,接收多个客户端的操作请求。内存:服务器端在启动的时候,首先会向系统申请一块较大的内存,并向rdma网卡进行注册,该块内存包含共享hash表和value存储区两部分,hash表用于记录key与value的映射等信息,value存储区用于存储value,客户端与服务器端建立连接的时候会获取该块内存的注册信息,这样客户端就可以通过rdma网卡直接访问该块内存区域。键值存储系统中客户端发起的put(key,value)操作中有两种实现模式,一种是客户端直接用rdma的send原语实现,另外一种是使用rdma的send+write混合原语实现。客户端发起的delete(key)操作中,客户端通过send原语将key发送给服务器端,服务器端接收到请求后将hash表中的key和value存储区中的value删除。客户端发起的get(key)操作和contains(key)操作,都是客户端不经过服务端,直接通过read原语操作实现。

hash表记录了key和value的映射关系。hash表的命中率,往往决定了系统的读取性能。当命中率提高,get的读取轮数也就降低了。经过比较,选择了线性探测hash方式。这是因为线性探测结合rdma的read原语的特性有进一步的优化方式。线性探测的hash存储方式,当有hash冲突的时候,会从当前桶线性往下找到一个空的桶。在线性探测hash中,可以将多个连续的桶定义成了块。结合rdma的read原语读取连续内存的特性,可以在一轮中就读取到这个块。如果当前块没有查询到,会继续读取另外一个块。正是这样预取的方式,可以很大程度上提高hash表的命中率。

图2是本发明的put操作流程设计示意图。如图所示,put(key,value)客户端提供key和value,并将key和value存储到服务器端的内存中。客户端先计算value的大小为l,如果l<s,会使用send原语将key和value都发送给服务器端。服务器端收到key和value会将key记录在hash表里,将value存储在value存储区里。本发明中本地缓存是客户端独有的,存储区域一般指的是服务器端存储value的区域,内存指的是hash表和value存储区的整体。如果l>=s,客户端使用send原语只发送key,服务器端收到key以后,会在value存储区为value分配合适的空间,服务器端在hash表中记录key和value的存储地址等相关信息,并将该内存地址发送回客户端,客户端接收到value的存储地址后,使用write原语写入到远端服务器。选择write原语直接避免了服务器端的内存数据拷贝。而value越大,往往拷贝的cpu消耗也就越大。但是为了不影响小的value的服务性能,客户端可以直接将key和value直接通过send原语发送给服务器。s的默认值是1kb。delete(key)与put操作的第一种模式类似,客户端直接使用send原语将key发送给服务器端,服务器端收到key以后,会将hash表中的key和value存储区中的value删除。

图3是本发明的get操作流程设计示意图。get操作设计的特点是完全不涉及到远端服务器的cpu。服务器端为了允许客户端发起rdma的read操作,向rdma网卡注册了hash表内存和value存储内存这两块区域。客户端获取服务器端相关配置信息后,就可以向这两块内存区域进行任意的rdma单边操作。如图所示,get(key)客户端提供key,从服务器端获取相应的value值。第一步客户端通过read原语操作获取相应的key在服务器端hash表上的映射记录,这个记录是按块读取b个连续的hash表记录(b的默认值是8),客户端会看是否命中对应的key,如果没有继续读取下一个块,最多不超过m个块(m的默认值是64),最终成功找到的记录包含了key及其value在服务器端value存储区的地址valuepointer。第二步,第一步如果没有找到,说明服务器中不包含key对应的value,客户端直接返回空值,如果找到则查询本地缓存是否有对应的key缓存的value数据,如果没有就进行第三步。第三步客户端会根据第一步获取的value的存储区地址valuepointer,再次使用read原语操作从服务器端读取value值。添加本地缓存的目的是为了进一步提高get操作的性能。contains(key)只需要get(key)操作的第一步就可以,客户端通过read原语操作获取相应的key在服务器端hash表上的映射记录,如果在hash表中查找到key,则返回true值表示找到,否则返回false值表示没找到。

为了解决客户端读数据与服务器端写数据之间的并发冲突,本发明采用一种自校验数据结构。所有的put操作都要经过服务器端的处理。因此,当服务器端的cpu写本地内存的时候,客户端或许正在读取这段内存。这样也就导致客户端读取到混乱的信息了,这就是读-写竞争问题。读-写竞争总是无法避免的,而现实中也没有很好的硬件机制来解决网卡和cpu的同步问题。软件上的解决都带来了很大的时间消耗。有两种情况会导致客户端读取的信息是混乱的:一是客户端读取hash表内容时候,服务器正在修改该区域的内存。二是客户端读取到的内容指向的value的存储地址是无效的。为了避免这两种情况的发生,hash表的每一条记录都被设计成带有自校验功能的数据结构。任何对hash表记录的修改都会导致校验和的失败。为了避免记录中指针指向内容的失效,又使用了另外一个校验和来覆盖指针指向的实际内容。例如,当服务器取消分配指针指向的内存而重新分配另外一块内存地址时候,客户端仍然持有老的指针地址。客户端可以通过校验和,很容易区分出内容的不一致。

图4是本发明的自校验数据结构示意图。如图所示,展示了hash表每条记录的具体构成,每条记录包含一个覆盖整个记录的校验和。in_use表示当前的记录是否为空,key是实际的键,valuepointer指向value存储区存储value的地址,checksum1是value采用crc循环冗余生成的校验和,checksum2就是整体记录in_use、key、valuepointer、checksum1采用crc循环冗余生成的校验和。valuepointer指针指向的value存储区,前面是value字符串的长度,而后面是实际的value值。客户端发起get(key)操作,当读取hash表记录的时候,每个块包含b条记录,对每条记录分别校验,针对一条记录中数据in_use、key、valuepointer和checksum1重新生成crc校验和checksum_new2,如果checksum_new2等于记录中的checksum2则说明记录数据没有出错,否则说明数据出错,客户端需要重复读取;当读取value值的时候,客户端从服务器端的value存储区读取到value数据,根据读到的value数据重新生成crc校验和checksum_new1,如果checksum_new1等于key所在hash记录里的checksum1则说明value数据没有错误,否则说明数据出错,客户端需要重复读取。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1