Redis与KV存储(RocksDB)融合之编码方式

Redis与KV存储(RocksDB)融合之编码方式

简介

Redis 是目前 NoSQL 领域的当红炸子鸡,它象一把瑞士军刀,小巧、锋利、实用,特别适合解决一些使用传统关系数据库难以解决的问题。Redis 作为内存数据库,所有的数据全部都存在内存中,特别适合处理少量的热数据。当有巨量数据超过内存大小需要落盘保存时,就需要使用 Redis + KV存储的方案了。

本文涉及的Ardb就是一个完全兼容Redis协议的NoSQL的存储服务。其存储基于现有成熟的KV存储引擎实现,理论上任何类似B-Tree/LSM Tree实现的KV存储实现均可作为Ardb的底层存储实现,目前Ardb支持LevelDB/RocksDB/LMDB.

本文以Ardb为例,介绍Redis与KV存储之间融合时编解码层的实现。

编码方式

Redis与KV存储的融合方案中, 编解码层是一个很重要的环节。通过编解码层,我们可以屏蔽了各种kv存储实现的不同,可以在任意一个简单的kv存储引擎上,封装实现Redis中string,hash,list,set,sorted set等复杂类型的数据结构。

对于String类型,很显然可以与KV存储中的一个KV对一一对应;

对于其它的容器类型,我们需要

  • 一个KV来存储其整个Key的元信息(比如List的成员个数,过期时间等);
  • 每一个成员需要一个KV来保存成员的名称和值;

对于sorted set,其每个成员有score和rank两个属性,所以需要:

  • 一个KV保存整个Key的元信息
  • 每一个成员需要一个KV保存 score信息
  • 每一个成员需要一个KV保存每个成员对应 rank 信息

Key的编码格式

对于所有的Key, 包含同样的前缀,编码格式定义如下:

[<namespace>] <key> <type> <element...>

namespace用于支持类似redis中的库概念, 可以为任意字符串, 不限制必须为数字;
key则是一个变长二进制字符串
type用于定义一个简单key-value的类型,此类型隐含表明key的数据结构类型;一个字节
meta信息的key中type固定为KEY_META;具体类型将在value中定义(参考下一节)
除以上三部分外,不同类型的key可能有附加字段;如Hash的key可能需要附加field字段

Value的编码格式

内部Value则比较复杂,编码均以type开始, type取值即上节定义的KeyType

<type> <element...>

后续格式根据各种类型定义不同.

各类型数据编码方式

各类型数据的编码方式如下: ns代表namespace

            KeyObject                             ValueObject
String      [<ns>] <key> KEY_META                 KEY_STRING <MetaObject>
Hash        [<ns>] <key> KEY_META                 KEY_HASH <MetaObject>
            [<ns>] <key> KEY_HASH_FIELD <field>   KEY_HASH_FIELD <field-value>
Set         [<ns>] <key> KEY_META                 KEY_SET <MetaObject>
            [<ns>] <key> KEY_SET_MEMBER <member>  KEY_SET_MEMBER
List        [<ns>] <key> KEY_META                 KEY_LIST <MetaObject>
            [<ns>] <key> KEY_LIST_ELEMENT <index> KEY_LIST_ELEMENT <element-value>
Sorted Set  [<ns>] <key> KEY_META                 KEY_ZSET <MetaObject>
            [<ns>] <key> KEY_ZSET_SCORE <member>  KEY_ZSET_SCORE <score>
            [<ns>] <key> KEY_ZSET_SORT <score> <member> KEY_ZSET_SORT

ZSet编码实例

这里以最复杂的Sorted Set来做实例。假设有个Sorted Set为 A: {member=frist, score=1}, {member=second, score=2}。其在Ardb中的存储方式如下:
Key A的存储编码为:

// 伪代码中的|代表域的分割,不代表实际存储为"|"。实际序列化的时候每个域是按照特定位置序列化的.
键为:ns|1|A(1代表是KEY_META元信息类型)
值为:元信息编码(redis数据类型/zset,过期时间,成员个数,最大最小score等)

成员first的score信息存储编码为:

键为:ns|11|A|first (11代表类型为KEY_ZSET_SCORE)
值为:11|1 (11代表类型KEY_ZSET_SCORE,1为该成员first的score)

成员first的rank信息存储编码为:

键为:ns|10|A|1|first (10代表类型为KEY_ZSET_SORT, 1为score)
值为:10 (代表类型KEY_ZSET_SORT,无意义。rocksdb中自动按key大小排序,所以很容易算出rank,不需要存储和更新)

成员second的score信息存储编码略。
当用户使用zcard A命令时,直接访问namespace_1_A即可得到元信息中该有序集合的数目;
当用户使用zscore A first时,直接访问namespace_A_first即可得到first成员的score;
当用户使用zrank A first时,先用zscore得到score,再查找namespace_10_A_1_first的序号;

具体的存储方式代码如下:

阅读全文请点击:http://click.aliyun.com/m/8714/

时间: 2024-10-05 18:47:52

Redis与KV存储(RocksDB)融合之编码方式的相关文章

基于淘宝开源Tair分布式KV存储引擎的整合部署

一.前言 Tair支撑了淘宝几乎所有系统的缓存信息(Tair = Taobao Pair,Pair即Key-Value键值对),内置了三个存储引擎:mdb(默认,类似于Memcache).rdb(类似于Redis).ldb(高性能KV存储),其中前2者定位于cache缓存,ldb则定位于持久化存储.Tair属于分布式系统,由一个中心控制节点(Config Server)和一系列的服务节点(Data Server)组成,Config Server负责管理维护所有的Data Server状态信息.D

谈谈KV存储集群的设计要点

版权声明:本文由廖念波原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/150 来源:腾云阁 https://www.qcloud.com/community Key-value存储系统,是非常普遍的需求,几乎每个在线的互联网后台服务都需要KV存储,我们团队在KV存储方面,经历过几个时期,我自己深感要做好不容易. 这里扯远一点,展开说一下: 第一个时期,很早期的时候,我们的数据存储在mysql表里,按照用户账号简单的分库分

Redis 四:存储类型之有序集合

有序集合似乎更大的操作是由于加了一个叫做“分子”的东西 事实上就好像普通的数据,只是为这个数据加了一个纯数字的标识, 通过操作这些标识来得到我们想要的数据! 分子可以是整形,也可以是双精度浮点型: ==================================================== 1.zadd num 100 a 80 b 70 c 添加一个叫num的有序集合,a元素为100分,b元素为80分.... 2.zscore num a 获取num集合中元素名为a的分子 ====

Redis 三:存储类型之字符串

1.赋值单个: set a 100 [赋值多个:mset a 100 b 200 c 300] 2.取值单个: get a [取值多个:mget a b c] 3.数字递增 incr a 在a的基础上+1,那就是返回101 如果预先的值为0,那么返回1,如果预先的值不是整形,则返回错误“is not an integer...” 3.1 数字递减 decr 用法跟上面一样 decr 4.约定(命名方式) 对象类型:对象ID:对象属性 user:100:friends 存储用户id为100的好友列

Redis 四:存储类型之无序集合

1.sadd num a b c 向num集合中添加abc三个元素 2.srem num b 从num集合中删除b元素 3.smembers num 获取num集合中所有的元素 4.sismember num c 判断c是否存在num集合中 ============================= 5.运算 sadd num a b c sadd num2 a b c d 差集(计算左边比右边多出来的那部分): sdiff num num 2 返回空 sdiff num2 num 返回d 交集

CAS工程用redis集群存储票据ticket Spring整合

maven jar包版本: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <groupId>org.springframework.data</groupId> <artifactId>spr

Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式)

Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式) 原文地址:http://alanland.iteye.com/admin/blogs/1600685(欢迎转载 - 转载请保留该原文链接) 07/19/12 03:08:05 PM 在Jedis开发中,我们很多时候希望直接把一个对象放到Redis中,然后在需要的时候取出来.Redis的key和value都支持二进制安全的字符串,存储Java对象不是问题,下面我们看一下如何来实现. 1要存储的对象 现在写一个

PHP中Redis替代文件存储Session语句

php默认使用文件存储session,如果并发量大,效率非常低.而Redis对高并发的支持非常好,所以,可以使用redis替代文件存储session. 这里,介绍下php的 session_set_save_handler 函数的作用和使用方法.该函数定义用户级session保存函数(如打开.关闭.写入等).原型如下: bool session_set_save_hanler(callback open,callback close,callback read,callback write,ca

Redis 四:存储类型之散列类型

1.散列类型表达方式简介: =========================================== 键 字段 值 =========================================== 前轮 --->富士康 后轮 --->苹果 宝马: 挡风玻璃 --->加多宝 座椅 --->王老吉 方向盘 --->恒大冰泉 =========================================== 散列类型更好的作用于同一个对象,不同属性,对应不同