Redis专题(二) ——Redis数据类型(2)

Redis专题(二)——Redis数据类型(2)

(原创内容,转载请注明来源,谢谢)

四、列表类型(List)

列表类型可以存储一个有序的字符串列表,其存储方式是双向链表的数据结构,即可以从两头增加、删除内容。因此,redis列表的操作方式和数据结构的链表非常像,大部分情况下是用push、pop进行操作。

列表的优势很明显,两头的数据增加、删除很快,但是缺点也比较明显,就是当需要获取中间的第i个元素的时候,则需要从头(或尾)逐个进行遍历。但是,遍历的过程中如果还有并发的增加元素,则可以直接从另一头增加,不需要将列表锁起来,这也是其优势。

列表类型的元素在如新鲜事(即通常只会查看前n条记录,且n较小)等场景速度非常快。因为即使原始数据非常多,但是列表可以从另一头取数据,且当有新内容时也是直接加入到尾部,因此非常的便利且高效。

1、设置、获取数据

1)设置:LPUSH keyvalue1 value2…、RPUSH key value value2…分别是从表的左、右两头塞入新的数据。

2)弹出:LPOP key、RPOP key分别是从左右两头弹出第一个数据。

3)获取元素个数:LLENkey,不存在返回0,redis的获取类似数据库的count,但是非常高效,时间复杂度是O(1),即读取现成值,不用遍历。

4)获取列表片段:LRANGEkey start stop,从key左边第start个获取到第stop个元素,获取的过程不会删除元素,和pop命令不一样。另外,key或stop的值为负数,则表示从右边计算。如-1,-10表示从右边第一个到第十个。

5)删除列表指定值:LREMkey count value,将key的值为value的元素删除count个,count为正数从左数,负数从右数,0则删除全部。

2、实例

1)新鲜事存取

设定key为usernews:userid,每当有新鲜事时,则用lpushusernews:userid value的方式将值从左边插入,拉取最近10条新鲜事则采用lrange usernews:userid 1 10的方式。

2)文章id存取

当要获取最新10个文章时,如果用前面说的自增count的方式获取最大的10个id,存在的问题是如果中间有删除的文章,则id不是连续的,此时的获取如果还要加上判断,效率很低。

而将id存在列表内,当删除文章时使用lrem相应的把列表的值删除,获取最新10个文章则使用lrange的方式,更为高效。

3、其他命令

1)数组方式使用列表:LINDEXkey index 获取列表key的第index个元素,LSET key index value相应的赋值,index是负数时从右边开始计算。

2)批量删除:LTRIMkey start end,将索引小于start和大于end的值全部删除,仅保留start至end的元素。删除之后列表的索引会变化,此时在最左边的元素下标将变成0,以此类推。

3)向列表中间插入元素:LINSERTkey BEFORE|AFTER index value,会在key的下标为index的元素的前面|后面插入值。

4)原子性的将列表从一个元素移到另一个元素:RPOPLPUSH key1 key2,把key1的最右边的元素移除,插入到key2的最左边。当redis用作消息队列系统时,如果需要经过多个队列,则此操作很重要,可以将监控到的队列进行转移,完成一个转移到下一个队列。

五、集合类型(Set)

集合是一组没有顺序的元素,其中每个值都不相同,一个集合最多可以存储232-1个字符串。集合和列表很相似,但是区别在于集合是无序的、每个元素值唯一的,列表是有序的、元素值不唯一的。

1、设置与获取

1)增加/删除元素:SADD keymember1 member2…,SREM key member1 member2…,返回的是成功的个数,sadd的member如果有重复的则重复的那一个不会插入,srem如果删除不存在的member也不会去删除。

2)获取全部:SMEMBERSkey、判断是否存在:SISMEMBER key member

3)集合间运算:SDIFFkey1 key2…,SINTER key1 key2…,SUNION key1 key2…分别表示若干个集合的差集、交集和并集。返回集合运算的结果。

命令SDIFFSTOREresultkey key1 key2…可以将若干键的差集计算后存在resultkey里面,同理还有SINTERSTORE、SUNIONSTORE。

2、实例

1)要存储不能重名的字段,如用户名,当需要批量导入的时候,就可以使用此操作,因为重名的情况下sadd key会返回0,表示插入失败,则不允许进行导入。

2)博客系统给文章加标签,每个文章可以有多个标签,但是标签之间不能重复,则可以使用集合的方式。

3、其他命令

1)获取元素个数:SCARDkey

2)获取集合随机一个元素:SRANDMEMBERkey count,count默认是1,随机获取key集合中的count个元素,count为正数时获取的值互不相同,count为负数时获取的值可以相同。

由于redis存储key是采用hash的方式,因此这个随机的随机性不是那么好,当若干key的hash结果一样时,会存在同一个bucket里面,导致随机到的可能性降低。

3)弹出元素:SPOPkey,由于集合无序,因此会随机弹出一个元素。

六、有序集合类型(Sorted Set)

此数据类型,在集合的基础上,为集合的每个元素关联一个分数,使得集合的结果可以进行排序。有序集合的每个元素仍要求不一样,但分数可以一样。

1、有序集合和列表的异同

1)相同之处

二者都有序,且都可以获取某一范围内的元素。

2)不同之处

a.列表是双向链表,因此获取两边很快而获取中间很慢,很少用列表获取中间值;有序集合用的是散列表(hash)和跳跃表(skip list)实现,获取中间元素的速度比列表快,速度为O(logn)。

b.列表不能简单的调整元素的位置,有序集合可以通过调整分数直接调整元素的位置。

c.有序集合比较耗内存。

2、基本操作

1)增加元素:ZADDkey score1 member1 score2 member2…,当对同一个member进行add时,会覆盖上一次的score。score支持浮点数,且+inf和-inf表示正负无穷大。

2)获取元素分数:ZGETkey member

3)获取排序位置为某个范围的元素:ZRANGE key start stop [withscores],获取key的分数从start至stop的全部元素,从小到大排序,获取的结果是若干个member的有序集合;当加上withscores时,获取的是member1 score1 member2 score2这样的集合。

其时间复杂度是O(log n+m),n是有序集合元素个数,m是返回的元素个数。

当两个score一样,redis将member按照0<9<A<Z<a<z的方式进行排序,中文和其他符号按照编码方式进行排序。

ZREVRANGE将结果按照score从大到小排列。

4)获取score为某个范围的元素:ZRANGEBYSCOREkey min max [withscores] [LIMIT offset count],此获取的是包含min和max的,如果希望不包含某边,例如不含最小值,则在min前面加上英文括号(,另外,+-inf也可以用上,表示只比较大于或者小于。

5)增加某个元素的分数:ZINCRBYkey increment member,如果member不存在,会赋值为0后再进行增加的操作。

3、实例

1)此功能可以实现按点击量对文章进行排序、实现对学生成绩排序等。

2)对时间排序也可以使用有序集合,只要将时间都转成unix时间戳,然后用时间戳当作score即可。

4、其他操作

1)元素数量:ZCARDkey、指定分数范围内元素数量:ZCOUNT key min max,其中min和max的特性与ZRANGEBYSCORE相同。

2)删除元素:ZREMkey member1 member2… 、按排名范围删除:ZREMRANGEBYRANK key start stop、按分数范围删除:ZREMRANGEBYSCOREkey min max

3)获取元素排名:从小到大——ZRANKkey member,从大到小——ZREVRANK key member

4)有序集合交集:ZINTERSTOREresultkey numkeys key1 key2… [WEIGHTS weight1 weight2…] [AGGREGATE SUM|MIN|MAX]

此方法将多个key的交集存在resultkey中,返回resultkey元素个数。

返回集中,相同元素由于被合并,其分数要变化,变化的分数由AGGREGATE确定,默认是sum,即键分数是每个参与计算的键的分数和,min和max则是最小、最大值。

当设置了weight,则每个分数会被乘以相应的weight后进行比较。

5)ZUNIONSTORE,类似ZINTERSTORE,是求两个有序集合的并集。

——written by linhxx 2017.08.04

相关链接:

Redis专题(二)——Redis数据类型(1)

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-08-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java Web

Java学习笔记(2)——数据类型

终于要写点干货了,其实思考了很久下面一篇文章要写什么,主要的纠结点在于,既想要分享那些精美的知识,又怕这些知识不太好嚼。后来想想还是对初学者不太好友算了..一...

2483
来自专栏用户2442861的专栏

C内存管理一 概述

我们写了这么多年的程序员,可能理论方面还比不上大学生。有人 "嘘"我了,如果有能回答以下几个问题的同学请举手: 1.面试经常遇到:同学请说说堆栈的区别? 2....

481
来自专栏玄魂工作室

Python黑帽编程2.4 流程控制

Python黑帽编程2.4 流程控制 本节要介绍的是Python编程中和流程控制有关的关键字和相关内容。 2.4.1 IF …..ELSE 先上一段代码: ...

2634
来自专栏ShaoYL

OC语言Block 续

1189
来自专栏用户2442861的专栏

Python yield 使用浅析

您可能听说过,带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ?

541
来自专栏kalifaの日々

美团北京视频面试题目

1.用过makefile吗 2.python的多线程是真正的多线程吗? 3.写一个冒牌排序,再写一个递归的冒泡排序 4.写一个单链表反转,十几行代码以内 ...

682
来自专栏企鹅号快讯

JAVA核心技术学习笔记

掌握Java核心技术是学习和掌握好Java技术的关键,下边分17个点对这些Java核心技术进行讲解。 >>>1.Java中没有多继承,而是用接口来代替多继承 >...

1765
来自专栏更流畅、简洁的软件开发方式

静态变量 静态对象 静态函数和非静态函数的区别。(我的理解,大家看看对不对)

先明确一下 语言:asp.net C# 1、静态变量: static string str1 = "1234"; 2、静态对象 static SqlConn...

1765
来自专栏Java Web

Java 面试知识点解析(一)——基础知识篇

2035
来自专栏我有一个梦想

3D游戏开发之UE4中的集合:TSet容器

好久没有更新了,最近一直在老家过年,网络不通的,今天才有时间更新一集。 一、TSet<T>是什么 UE4中,除了TArray动态数组外,还提供了各种各样的模板容...

18510

扫描关注云+社区