《Redis入门指南》之基本的数据结构

《redis入门指南》这本书入门不错,值得推荐,每一章都有些干活。这里分别加以总结,并增加了自己的一些理解。

常见数据结构

字符串类型

这是最常见的key-value的结构,但是现在的no-sql远不止于此:

我们来看看四个使用字符串类型的场景:

  • INCR num: 进行文章的访问pv统计;
  • INCR num: 生成自增ID,类似于mysql的auto_increment;
  • SET key value:存储序列化的json或其他数据结构;
  • GETBIT key offset: 通过bit位来记录大批量用户的单个状态,如性别,方便快速读取和修改,占用空间小,性能高。必须采用预分配+用户id映射,避免不必要的内存消耗;

散列类型

散列类型略微复杂一些,对应的是mysql中的列数据,但是有对比,才有伤害:

假设双方都要存储一张Person表,具有如下的属性:

  • 性别
  • 身高
  • 拥有车的品牌

这就尴尬了,不是每个人都有车,哪来品牌呢?mysql一定要有冗余的字段,但是redis的散列类型就不需要。
hset richwang sex male height 180 carbrand bmw
hset poolgeorage set male height 170

我们再来看看散列常见的两个场景:

  • HKEYS key | HVALS key | HLEN key : 不在使用结构化的数据来进行key-value存储,而是分字段更灵活的存储,方便单独的修改和更新,每次不需要全量json的更新
  • HEXISTS key | HSETNX: 存储某一类映射关系,确保一一对应,比如person和身份证,一旦添加之后,无法用相同的身份证再次添加。

再提一句,散列是redis中唯一支持数据类型嵌套的类型。

列表类型

列表类型主要是进行数组的描述,一般常见的操作就是向列表两端添加元素,或者获得列表的某一个片段。

从实现上来讲的话:双向链表实现,头尾插入非常方便,头尾获取也非常快,但是对中间元素的读取和写入都比较慢,所以在使用的时候也应该尤其注意这一点。

另外还有一个值得注意的性能指标,LLEN命令会直接读取现成算好的长度,而不是像mysql那样select count(*)进行遍历数据表。

下面来看看列表类型的场景,还是很多的:

  • 新鲜事Feeds,对于一个SNS而言,新鲜事的场景很多,用户每次打开,总是要拉取朋友的新鲜事。对于每个用户而言,使用一个列表存储用户能看到的动态十分方便。每次只要给出当前的index,就可以拉取其新鲜事,而且头尾存储,性能很高。
  • 日志记录:将日志记录到列表中,方便进行头尾查看。
  • ID列表,通过固定顺序将id存储列表类型,使用 LRANGE numbers 0 2 进行分页读取,缺点在于已有顺序不太方便调整。结合活动中心的案例,如果是一枪头发布,使用这个方案没有问题,但是如果活动有上线下线的过程,那么最好还是不要使用这个。
  • 队列循环:RPOPLPUSH source destination,如果source和dest相同的话,那就是一个循环。非常适合进行url的监控,循环的同时还可以不断的加入新的网址。整个系统容易扩展,允许多个客户端同时处理队列;
  • 评论列表:如果评论一经发布不可修改,那么也比较适合序列化之后,存入列表,进行插入和拉取。

集合类型

对于那些元素不可重复的场景,集合类型是必不可少的。很多时候在一些场景下,容易把集合和列表类型混用,所以最好对其两者特性都能够有所了解。集合的主要应用场景一个是不重复,另一个是集合之间的交集、并集、差集。

一个非常常见的场景就是标签的存储。使用两个集合类型:
集合1:标签集合
SADD labels teacher students worker engineer
集合2:标签下属人群集合
SADD teacher tom ted lily

通过这样的设计可以实现如下的几个功能特性:

  • 通过labels集合保存所有的不重复的标签,方便添加、拉取和删除
  • 不同的标签对应了不同的下属人群,那么标签之间非常常见的交集、并集、差集操作,都可以很方便的利用集合的SDIFF DINTER SUNION来实现

针对第二种情况,如果是使用mysql存储的话,就会涉及到一个非常复杂的join的过程:

SELECT p.name FROM person_labels pl, person p, labels l WHERE pl.label_id=l.label_id AND (l.label_name IN (‘teacher’, ‘worker’)) AND p.person_id=pt.person_id GROUP BY p.person_id HAVING COUNT(p.person_id)=3;

所以在这种场景之下,redis的集合类型还是非常的实用的。

有序集合列表

有序集合列表我个人感觉应该是为了互联网的榜单而生,它将每个元素都关联了一个分数。从上文中知道,redis中的列表类型使用了双向链表,获取开头和结尾的元素都是比较容易的,而有序集合则使用了散列表和跳跃表,其中跳跃表就是为了实现查找的log(N)效率而进行的实现。有了优点,不可避免的,它比列表类型更加费内存一些。

我们来看一个文章按照点击量来排序的实例,新建一个有序集合article:pageview,其中存储的是articleId,而其score就是文章的点击量。
每有一篇文章增加了点击,我们就可以使用ZINCRBY article:pageview 1 $articleId,来进行对应的操作。
按照访问量来获取所有的文章列表,就可以直接使用ZRANGE article:pageview 0 -1 withscores 加以实现。

另外一个比较常见的应用就是按照score归档数据,比如score定义为时间戳,那么就可以使用ZREVRANGEBYSCORE articles 六月的timestamp 五月的timestamp limit 0 3 这样就可以获得在六月和五月之间的前三篇文章了。

同时有序集合也是支持一些集合的操作的。举一个例子,上海市教育局想看看黄浦区的教育水平如何,选取了大同中学和大境中学两个学校,分别对应了两个有序列表:datongScore和dajingScore,分别存储其每个学科的平均分。学科的id是完全一样的。那么想看看黄浦区的学科平均分,但是由于两个学校的考题难度不一样,又需要一定的加权处理的时候,这时候就需要执行:
ZINTERSCORE huangpuScore 2 datongScore dajingScore WEIGHTS 1 0.8

再获取一下其中的结果:
ZRANGE huangpuScore 0 -1 WITHSCORES 即可获得想要的结果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容