Redis常见数据类型下

目录

 Hash 哈希

常用指令

HSET

HGET 

HEXISTS

HDEL 

HKEYS  

HVALS 

 HGETALL 

 HMGET 

内部编码

Hash类型和关系型数据库

缓存方式对比 

List 列表 

特点 

常用命令 

LPUSH 

LPUSHX 

 RPUSH 

 RPUSHX 

LRANGE  

LPOP  /  RPOP 

 LINDEX 

LINSERT  

阻塞(BLOCK)版本的命令 

 内部编码

使用场景

 消息队列

微博列表 

Set 集合 

常用命令 

 SADD

SMEMBERS 

SISMEMBER  

SCARD  

SPOP 

SMOVE 

SREM 

集合的交集、并集、差集 

SINTER / SUNION / DIFF  

SINTERSTORE / SUNIONSTORE / DIFFSTORE

 内部编码

使用场景

Zset 有序集合 

常用命令

 ZADD

ZCARD 

ZCOUNT 

ZRANGE 

ZPOPMAX 

ZRANK 

ZREVRANK 

ZSCORE 

ZREM 

ZREMRANGEBYRANK 

ZREMRANGEBYSCORE 

ZINCRBY 

使用场景 

渐进式遍历 

SCAN 


 Hash 哈希

⼏乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数
组、映射。

TIPS:哈希类型中的映射关系通常称为:field-value 用于区别Redis整体的键值对key-val的关系

所以在Redis的value中使用hash类型应该是这么表示key - field - val

常用指令

HSET

设置hash中指定的字段field 的值 value

语法:

HSET key field value [field value ...]

返回值:添加的字段的个数

示例:

HGET 

获取hash中指定字段的值

语法:

HGET key field

返回值:字段对应的值或者nil

示例:

HEXISTS

判断hash中是否有指定的字段

语法:

HEXISTS key field

返回值:1表示存在,0表示不存在

示例:

HDEL 

删除hash中指定的字段

语法:

HDEL key field [field ...]

返回值:本次操作删除的字段个数

示例:

HKEYS  

 获取hash中的所有字段

语法:

HKEYS key

 返回值:字段列表

示例:

HVALS 

获取hash中所有的值

语法:

HVALS key

 返回值:所有的值val

示例:

 HGETALL 

获取哈希汇总的所有字段以及对应的值

语法:

HGETALL key

 返回值:字段和其对应的值

示例:

 HMGET 

一次获取hash中字段的多个值

语法:

HMGET key field [field ...]

 返回值:字段对应的值或者nil

示例:

TIPS:在使⽤HGETALL时,如果哈希元素个数⽐较多,会存在阻塞Redis的可能。如果开发⼈员只需要获取部分field,可以使⽤HMGET

内部编码

哈希的内部编码有两种:

1.ziplist(压缩列表):当hash类型元素小于hash-max-ziplist-entries配置(默认512个)、同时所有的值都小于hash-max-ziplist-value(默认64字节),Redis会使用ziplist作为hash的内部实现,zipliost使用更加紧凑的就够实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀

2.hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时的hashlist的读写小会下降,而hashtable的读写时间复杂度为O(1)

Hash类型和关系型数据库

  • 哈希类型是稀疏的,⽽关系型数据库是完全结构化的,例如哈希类型每个键可以有不同的field,⽽关系型数据库⼀旦添加新的列,所有⾏都要为其设置值,即使为null
  • 关系数据库可以做复杂的关系查询,而Reid社区模拟关系型复杂查询,例如:联表查询、聚合查询等基本不可能,维护成本高

缓存方式对比 

 

现在有三种方法缓存用户信息

1.原生字符串类型 -- 使用字符串类型,每个属性占用一个键

set user:1:name gc
set user:1:age 22
set user:1:sex 男

 优点: 实现简单,针对个别属性变更也很灵活。

缺点:占⽤过多的键,内存占⽤量较⼤,同时⽤⼾信息在?Redis?中⽐较分散,缺少内聚性,所以这种⽅案基本没有实⽤性

2.序列化字符串类型,例如JSON格式

set user:1 经过序列化后的字符串~~

 优点:针对总是以整体为操作的信息比较合适

缺点:序列化和反序列化本身需要一定的开销,如果总是操控个别属性的话不方便

3.哈希类型

hmset user:1 name gc age 22 sex 男

优点:简单直观且灵活

缺点:需要控制hash在ziplist和hashtable两种内部编码的转换,可能会造成内存开销大

List 列表 

列表类型是⽤来存储多个有序的字符串,⼀个列表最多可以存储2^32-1 个元素。在Redis中,可以对列表两端插⼊(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等

入图对列表两端的插入和 弹出操作

特点 

  • 1. 列表中元素是有序的,是可以使用索引下标获取某个元素或者某个范围的元素列表
  • 2. 获取会得到该下标的元素,删除会将列表的长度减小
  • 3. 列表的元素允许重复 

常用命令 

LPUSH 

将⼀个或者多个元素从左侧放⼊(头插)到list中

返回值:插⼊后list的⻓度

示例:

LPUSHX 

在key存在时,将⼀个或者多个元素从左侧放⼊(头插)到list中。不存在则直接返回

语法:

LPUSHX key element [element ...] 

 返回值:插⼊后list的⻓度。

示例:

 RPUSH 

 将⼀个或者多个元素从右侧放⼊(尾插)到list中。

语法:

RPUSH key element [element ...]

 返回值:插⼊后list的⻓度

示例:

 RPUSHX 

在key存在时,将⼀个或者多个元素从右侧放⼊(尾插)到list中

语法:

RPUSHX key element [element ...] 

 返回值:插入之后的list长度

示例:

LRANGE  

获取从start到end区间的所有元素,左闭右闭 

语法:

LRANGE key start stop 

 返回值:指定区间内的元素

如果start为0,stop为-1就是遍历所有

 示例:

LPOP  /  RPOP 

lpop 从list左侧取出元素(即头删)

rpop从list右侧取出元素(即尾删)

语法:

LPOP key
RPOP key

 返回值:取出的元素或者nil

示例:

 LINDEX 

获取从左数第index位置的元素

语法:

LINDEX key index 

 返回值:取出的元素或者nil

示例:

LINSERT  

在特定位置插⼊元素。

语法:

LINSERT key <BEFORE | AFTER> pivot element 

 返回值:插入之后的list长度

 示例:

阻塞(BLOCK)版本的命令 

blpop和brpop是lpop和rpop的阻塞版本,和对应⾮阻塞版本的作⽤基本⼀致

但是阻塞版本会有如下特殊:

  • 在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理解返回nil,但阻塞版本会根据timeout,阻塞⼀段时间,期间Redis可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态
  • 命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元素,命令⽴即返回
  • 如果多个客⼾端同时多⼀个键执⾏pop,则最先执⾏命令的客⼾端会得到弹出的元素

 内部编码

列表类型的内部编码有两种:

1.ziplist(压缩列表):当hash类型元素小于hash-max-ziplist-entries配置(默认512个)、同时所有的值都小于hash-max-ziplist-value(默认64字节),Redis会使用ziplist作为hash的内部实现,zipliost使用更加紧凑的就够实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀

2.linkedlist(链表):大哥你列表无法满足ziplist条件的时候,Redis会使用linkedlist作为列表内部实现

使用场景

 消息队列

Redis可以使⽤lpush+brpop命令组合实现经典的阻塞式⽣产者-消费者模型队列,⽣产者客⼾端使⽤lpush从列表左侧插⼊元素,多个消费者客⼾端使⽤brpop命令阻塞式地从队列中"争抢"队⾸元素。通过多个客⼾端来保证消费的负载均衡和⾼可⽤性 

Redis分频道的阻塞队列模型:

微博列表 

每个⽤⼾都有属于⾃⼰的Timeline(微博列表),现需要分⻚展⽰⽂章列表。此时可以考虑使⽤
列表,因为列表不但是有序的,同时⽀持按照索引范围获取元素。

1.每篇微博使用哈希结构存储,举例微博有中有三个重要属性,title,content,time

hmset mblog:1 title xx time 1476536196 content xxxxx
...
hmset mblog:n title xx time 1476536196 content xxxxx

2.向用户的微博列表添加微博文章,user:uid:mblogs 作为键

其实就是往用户微博列表中,插入微博文章的哈希键

lpush user:1:mblogs mblog:1 mblog:3
...
lpush user:k:mblogs mblog:9

3.获取用户的微博列表,例如获取用户前1~6篇微博文章

keylist = lrange user:1:mblogs 0 9
for key in keylist{
    hgetall key
}

 这种方案实际可能存在两个问题:

1. 1+n问题,如果每次获取的微博个数较多,需要多次hgetall,此时可以考虑使用pipeline流水线模式批量提交命令

2.分裂获取文章时,lrange在列表两端表现好,获取列表中间元素标签差。此时可以对列表文进行拆分提高效率

Set 集合 

1.集合类型也是保存多个字符串类型的元素的,与列表类型不同的是,集合中元素之间是⽆序的

2.集合元素不允许重复,⼀个集合中最多可以存储2^32 -1 个元素。Redis除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集,合理地使⽤好集合类型,能在实际开发中解决很多问题

常用命令 

 SADD

将⼀个或者多个元素添加到set中。注意,重复的元素⽆法添加到set中。

语法:

SADD key member [member ...]

 返回值:本次添加成功的元素个数

示例:

SMEMBERS 

 获取⼀个set中的所有元素,注意,元素间的顺序是⽆序的。

语法:

SMEMBERS key 

返回值:所有元素的列表 

示例:

SISMEMBER  

 判断⼀个元素在不在set中。

语法:

SISMEMBER key member

 返回值:1表示元素在set中,0则表示不在set中 

示例:

SCARD  

获取⼀个set的基数(cardinality),即set中的元素个数

语法:

SCARD key

 返回值:set内的元素个数

示例:

SPOP 

从set中删除并返回⼀个或者多个元素。注意,由于set内的元素是⽆序的,所以取出哪个元素实际是未定义⾏为,即可以看作随机的

语法:

SPOP key [count]

 返回值:取出的元素

示例:

SMOVE 

将⼀个元素从源set取出并放⼊⽬标set中。

语法:

SMOVE source destination member 

 返回值:1表示成功,0表示失败

示例:

SREM 

将指定的元素从set中删除。

语法:

SREM key member [member ...] 

 返回值:本次操作删除的元素个数

示例:

集合的交集、并集、差集 

交集(inter)、并集(union)、差集(diff)如图所示  

SINTER / SUNION / DIFF  

获取sinter交集,sunion并集,diff差集中的元素

语法:

SINTER key [key ...] 
 
SUNION key [key ...] 
 
SDIFF key [key ...]

 返回值:交集、并集、差集的元素

SINTERSTORE / SUNIONSTORE / DIFFSTORE

获取给定set的交集、并集、差集中的元素并保存到⽬标set中。

语法:

SINTERSTORE destination key [key ...]
SUNIONSTORE destination key [key ...]
DIFFSTORE   destination key [key ...]

返回值:交集、并集、差集的元素个数

 内部编码

集合类型的内部编码有两种:

intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于set-max-intset-entries配置
(默认512个)时,Redis会选⽤intset来作为集合的内部实现,从⽽减少内存的使⽤

hashtable(哈希表):当集合类型⽆法满⾜intset的条件时,Redis会使⽤hashtable作为集合的内部实现。

使用场景

集合类型⽐较典型的使⽤场景是标签(tag)。例如A⽤⼾对娱乐、体育板块⽐较感兴趣,B⽤⼾对历史、新闻⽐较感兴趣,这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同⼀个标签
的⼈,以及⽤⼾的共同喜好的标签 。例如⼀个电⼦商务⽹站会对不同标签的⽤⼾做不同的产品推荐

Zset 有序集合 

有序集合相对于字符串、列表、哈希、集合来说会有⼀些陌⽣。它保留了集合不能有重复成员的
特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数

 TIPS:有序集合中的元素是不能重复的,但分数允许重复。类⽐于⼀次考试之后,每个⼈⼀定有⼀个唯⼀的分数,但分数允许相同。

常用命令

 ZADD

添加或者更新指定的元素以及关联的分数到zset中,分数应该符合double类型,+inf/-inf?作为正负极限也是合法的。

ZADD的相关选项:

  • XX:仅仅⽤于更新已经存在的元素,不会添加新元素
  • NX:仅⽤于添加新元素,不会更新已经存在的元素
  • CH:默认情况下,ZADD?返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数。
  • INCR:此时命令类似ZINCRBY的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。

语法:

ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]

返回值:本次添加成功的元素个数。

示例:

ZCARD 

获取⼀个zset的基数(cardinality),即zset中的元素个数。

语法:

ZCARD key

 返回值:zset内的元素个数。 

 示例:

ZCOUNT 

返回分数在min和max之间的元素个数,默认情况下,min和max都是包含的

语法:

ZCOUNT key min max 

 返回值:满⾜条件的元素列表个数 

示例:

ZRANGE 

返回指定区间⾥的元素,分数按照升序。带上WITHSCORES可以把分数也返回

语法:

ZRANGE key start stop [WITHSCORES] 

 此处的[start,stop]为下标构成的区间从0开始,⽀持负数.

返回值:区间内的元素列表

示例:

ZPOPMAX 

删除并返回分数最⾼的count个元素

语法:

ZPOPMAX key [count]

  返回值:分数和元素列表

ZRANK 

返回指定元素的排名,升序。

语法:

ZRANK key member 

 示例: 

ZREVRANK 

返回指定元素的排名,降序

语法:

ZREVRANK key member 

 示例:

ZSCORE 

返回指定元素的分数 

语法:

ZSCORE key member 

 示例:

ZREM 

删除指定的元素

语法:

ZREM key member [member ...]

 返回值: 本次操作删除的元素个数

示例: 

ZREMRANGEBYRANK 

按照排序,升序删除指定范围的元素,左闭右闭。 

语法:

ZREMRANGEBYRANK key start stop 

 返回值:本次操作删除的元素个数。

示例:

ZREMRANGEBYSCORE 

按照分数删除指定范围的元素,左闭右闭。

语法:

ZREMRANGEBYSCORE key min max 

 返回值:本次操作删除的元素个数

示例:

ZINCRBY 

为指定的元素的关联分数添加指定的分数值 

语法:

ZINCRBY key increment member

 返回值:增加后元素的分数

示例:

使用场景 

有序集合⽐较典型的使⽤场景就是排⾏榜系统。例如常⻅的⽹站上的热榜信息,榜单的维度可能是多⽅⾯的:按照时间、按照阅读量、按照点赞量。

比如点赞一篇文章,就可以使用有序集合zadd 和 zincrby功能对该文章的点赞数增加

也可以将用户文章删除zrem,以及展示前100最多赞的文章 zrank等~~

渐进式遍历 

 Redis使⽤scan命令进⾏渐进式遍历键,进⽽解决直接使⽤keys获取键时可能出现的阻塞问题。每次scan命令的时间复杂度是O(1),但是要完整地完成所有键的遍历,需要执⾏多次scan。

  •  ⾸次scan从0开始
  •  当scan返回的下次位置为0时,遍历结束.

SCAN 

以渐进式的方式进行键的遍历

语法:

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type] 

 返回值: 下⼀次scan的游标(cursor)以及本次得到的键。

示例:

除了scan以外,Redis⾯向哈希类型、集合类型、有序集合类型分别提供了hscan、sscan、zscan命令,它们的⽤法和scan基本类似 

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pythoncjavac++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值