Redis学习笔记(二)-四种复合数据类型
继续上次的进行,第一篇重要学习了Redis的一些基本概念和基本操作语句,对Redis有了一个大概的认识,并且会简单使用,第一篇中忘记说明Redis的安装方法,这个很简单,上官网下载安装包解压即可。
这一次主要展开学习一下Redis的四种高级数据类型:(除字符串外)
1. 散列类型
2. 列表类型
3. 集合类型
4. 有序集合类型
我的这些学习笔记都是自己花心思整理出来的干货,希望能对也在学习的你起到帮助的作用,也可以方便自己以后查看和复习。
散列类型
散列类型的含义就是一个key对应着一个value,而value内部是一系列的key-value合集(也就是一个散列表)。类似于下面这个示例:
散列可以理解为两层JSON的嵌套,这种数据类型在现实中可以存储和表达很多类型的数据,是key-value数据库数据格式的一种基础升级,可以用散列存储一些较为复杂的数据,就比如上面的这个汽车的例子,这样存储以来,就可以通过car:2这个键直接获取到一系列描述这个键的键值对。
比如用散列来存储一篇博客:
这就是存储一个更为复杂的数据的例子,可以看出来,在现实网络环境中,绝大多数的数据对象都可以抽象成一个散列来存储。这也就是为什么散列在Redis里有着很基础也很重要的作用。
下面简单介绍下散列的一些基本命令,可以覆盖到绝大多数应用场景
散列的命令:
插入散列数据
HSET car price 500
HSET car name BMW查询散列
HGET car name同时插入多个散列
HMSET key field1 value1 field2 value2获取散列的key所对应的所有键值对
HGETALL key判断散列中是否存在一个字段
HEXISTS key field当字段不存在时,插入字段,存在时不做操作。该命令也是原子操作。
HSETNX key field value只获取散列中的字段
HKEYS key只获取散列中的值
HVALS key获取key中的字段数量
HLEN key
总结:
可以通过以上的命令和介绍看出来,散列是一个升级版的key-value,是一个我们理解的嵌套的JSON数据,它在现实场景中可以更灵活的表达更多的数据类型和抽象对象。在维护上来看,它也是要比字符串更方便维护,所以任何复杂对象都可以用散列来表达和封装,而简单的单属性的内容就可以直接用字符串来存储。
列表类型
列表类型可以存储一个有序的字符串列表(list),列表类型内部使用的是双向链表,这样访问头和尾的数据的速度就会非常快。
命令:
向列表两端增加元素
LPUSH key value
RPUSH key value还可以同时增加多个元素:
LPUSH numbers 1
LPUSH numbers 2 3
[3,2,1]RPUSH numbers 0 -1
[3,2,1,0,-1]从列表两端弹出元素
LPOP key
RPOP key弹出操作分两步:第一步将左边或者右边元素从列表中移除,第二步返回被移除的元素。
获取列表中的元素个数
LLEN key
这个命令类似于传统SQL语句中的 select conut(*) from table, 但是LLEN的复杂度是1,Redis直接会读取现成的值。而不像部分关系型数据库需要再次遍历该表的所有记录进行统计。获取指定范围的元素
LRANGE key 0 2
获取从左边开始的编号从0 到 2 的元素。如果索引超出指定范围,而LRANGE不会写LPOP那样删除该片段。
支持负索引,-1 代表右边第一个 -2代表右边第二个,以此类推。删除指定的key
LREM key count value
删除key对应列表中从左边开始前count个值为value的内容。 count等于0 删除所有元素, count < 0 则取其绝对值获取指定下标元素
LINDEX number 0 从左边的下标0开始算,获取指定下标的元素。如果索引为-1 则代表最右边元素。更改列表中指定的值
LSET number 1 7 把number序列中的下标为1的元素设置为7删除指定范围内的值
LTRIM number 1 2 删除列表中除了下标 1 2 范围内的所有元素。LTRIM和LPUSH经常一起使用。比如记录日志时,我们只希望保留最近100条记录。则可以这样:
LPUSH log $newlog
LTRIM 0 99
每次增加日志后都trim一下,保证列表中只有100条记录。在指定元素的左边或右边插入元素
LINSERT key before|after value1 value2
向key列表中插入一个元素,从左边开始查找到元素value1,在value1的左边(before)或者右边(after)插入value2从一个列表中弹出元素插入到另一个列表
RPOPLPUSH source destination
从source列表中的右边弹出一个元素插入到destination列表中的左边,并最终返回这个值。整个过程是原子的。当source和destination相同时,RPOPLPUSH会不断的把队尾元素转移到队首。
总结:
列表就相当于链表一样,可以存储很多有序的数据,并且可以快速的找到你所需要的数据,列表类型在现实应用中也是有着很广泛的应用。
集合类型
集合中的每个元素都是不同的,且没有顺序。一个集合类型键可以存储最多 2^32 -1 个字符串。集合类型常用的操作有插入,删除,判断元素是否存在。由于集合在Redis内部实现是由hash table实现的,所以这些操作的复杂度都是O(1)的。最方便的是多个集合类型键之间还可以进行交集,并集和差集的运算。
命令:
增加元素
SADD key number [number …]
如果集合中存在这个元素,则忽略其,加入剩余不存在的元素。删除元素
SREM key number [number …]
删除元素时,如果要删除的元素不存在集合中,则忽略。删除其他的元素。获取集合中所有元素
SMENBERS key判断元素是否在集合中
SISMEMBER key number
这个命令的复杂度是O(1),存在则返回1,不存在则返回0集合差集运算
SDIFF key [key …]{1,2,3} - {2,3,4} = {1}
{2,3,4} - {1,2,3} = {4}
{1} - {2,3} = {1}
多个集合连续运算是先计算前两个,用结果再后第三个计算,以此类推。集合交集运算
SINTER key [key …]{1,2,3} ∩ {2,3,4} = {2,3}
并集运算
SUNION key [key …]
{1,2,3}∪{2,3,4} = {1,2,3,4}获取集合中元素个数
SCARD key进行集合运算并将结果存储
SDIFFSTORE destination key [key …]
SINTERSTORE destination key [key …]
SUNIONSTORE destination key [key …]随机获取集合中的元素
SRANDMEMBER key [count]SRANDMEMBER abcdefg 2
可能返回任意两个字母从集合中弹出一个key
SPOP key
pop出来后就相当于删除了。
总结:
集合就相当于编程语言中的Set,是一系列元素的集合,但是无序的,而且不能有重复的数据。同样的,在现实环境下有着很广泛的应用。
有序集合
最后,来说一下有序集合。
列表是通过链表来实现的,它获取靠近两端的数据非常快,但是获取中间的的数据会比较慢。所以它更适合实现如“新鲜事”,“日志”等很少访问中间元素的应用。
有序集合是通过散列表和跳跃表实现的,所以即使读取位于中间的数据也很快。列表不能简单的调整某个元素的位置,但有序集合可以(通过更改这个元素的分数)有序集合比列表更耗内存。
命令:
增加元素
ZADD key score number
eg: ZADD scoreboard 89 Tom 67 Peter 100 David如果重复插入相同的内容,则覆盖
ZADD scoreboard 76 Peter插入的分数还支持浮点数。以及正无穷(+inf)和负无穷(-inf)
获取元素分数
ZSCORE scoreboard Tom获取排名在某个范围内的列表
ZRANGE scoreboard 0 2
ZRANGE scoreboard 1 -1 (-1代表最后一个元素)需要返回元素和分数:
ZRANGE scoreboard 0 -1 WITHSCORES获取指定分数范围内的元素
ZRANGEBYSCORE scoreboard 80 100包含80,不包含100
ZRANGEBYSCORE scoreboard 80 (100限制查询出来的条数
ZRANGEBYSCORE scoreboard 80 (100 limit 3查询分数低于100的前三个
ZREVRANGEBYSCORE scoreboard 100 0 limit 0 3
100 0 代表查询范围从100开始到0,0 3 代表对查询出来的结果取三个元素,从编号为0的开始取增加某个元素的分数
ZINCRBY scoreboard 4 Jerry
返回更改后的分数减少指定元素的分数
ZINCRBY scoreboard -4 Jerry获得集合中元素数量
ZCARD key删除一个或多个元素
ZREM key number [number …]按照排名范围删除元素
ZADD test 1 a 2 b 3 c 4 d 5 e 6 fZREMRANGEBYRANK 0 2 – 删除掉了a b c
获得指定元素排名
ZRANK scoreboard Peter – 分数最小排名为0
ZREVRANK scoreboard Peter – 分数最大排名为0有序集合的交集
ZINTERSTORE destination numkeys key [key …] [WEIGHT weight [weight]] [AGGREGET SUM|MIN|MAX]numkeys 指后面有几个key来做交集操作
1) AGGREGET 是SUM时(默认SUM), 每个交集计算的是相同元素的分数和,然后存放到destination键中。ZADD sortedSet1 1 a 2 b
ZADD sortedSet2 2 a 4 bZINTERSTORE sortedSetsResult 2 sortedSets1 sortedSets2
(Integer) 2ZRANGE sortedSetsResult 0 -1 WITHSCORES
a
3
b
62) 当AGGREGATE是MIN时,destination元素中的分数是每个参与计算的集合中该元素分数最小值
ZINTERSTORE sortedSetsResult 2 sortedSets1 sortedSets2 AGGREGATE MIN
a
1
b
23) 当AGGREGATE是MAX时,destination元素中的分数是每个参与计算的集合中该元素分数最大值
ZINTERSTORE sortedSetsResult 2 sortedSets1 sortedSets2 AGGREGATE MAX
a
2
b
44) ZINTERSTORE还能通过WEIGHTS参数设置每个集合的权重,来按权重计算每个相交集合中的键所占得比例
ZINTERSTORE sortedSetsResult 2 sortedSets1 sortedSets2 WEIGHT 1 0.1
a
1.2
b
2.4并集的操作ZUNIONSTORE与ZINTERSTORE的用法一样。
总结:
有序集合可以存储很多需要排序的内容,网络中有大量的场景是需要将数据进行排序的,所以有序集合的应用非常广泛。例如按照文章访问量排序,按照口碑排序购买商品等等。有序集合的交并差也是很方便使用的。这样在一些购买推荐,别人在查看的内容等等推送信息上,都可以用到有序集合来实现。
这一篇主要学习了除了字符串以外的四种常见的复合数据类型,并且详细介绍了每种数据类型的含义使用场景以及相关命令。下一篇来学习一下Redis的事务。
(未完待续)