Redis - 五种数据类型以及消息发布订阅

Redis - 五种数据类型以及消息订阅

 想要使用Redis,那对它的数据类型必须了如指掌,它支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。这里我们就来看看这些数据类型是怎样的并且是如何使用的。这里列举的命令指示部分常用命令,完整的大家参考官方文档以及其他资料,这里推荐一个网站Redis 命令参考

1.String(字符串)

String是最常用的一种数据类型,普通的key/value存储都可以归为此类。最大能存储 512MB。并且String是二进制安全的。可包含任何数据。比如jpg图片或者序列化的对象。

1.1 set/get

 set:设置key对应的值为String类型的value
 get:获取key对应的值

127.0.0.1:6379> set name Tracy
OK
127.0.0.1:6379> get name
"Tracy"

1.2 mget

 批量获取多个key的值,如果不存在则返回nil

127.0.0.1:6379> mget name age
1) "Tracy"
2) "20"
127.0.0.1:6379> mget name sex
1) "Tracy"
2) (nil)

1.3 incr && incrby

 incr:对key对应的值进行加加操作(+1),并返回新的值;
 incrby:加指定值

127.0.0.1:6379> set score 10
OK
127.0.0.1:6379> incr score
(integer) 11
127.0.0.1:6379> incrby score 10
(integer) 21
127.0.0.1:6379> incr name
(error) ERR value is not an integer or out of range

1.4 decr && decrby

 decr:对key对应的值进行减减操作(-1),并返回新的值;
 decrby:减指定值

127.0.0.1:6379> decr score
(integer) 20
127.0.0.1:6379> decrby score 5
(integer) 15

1.5 setnx

 设置key对应的值为String类型的value,如果key已经存在则返回0

127.0.0.1:6379> setnx name Kobe
(integer) 0
127.0.0.1:6379> setnx name1 Kobe
(integer) 1

1.6 setex

 设置key对应的值为String类型的value,并设定有效期

127.0.0.1:6379> setex name 60 Tracy
OK
127.0.0.1:6379> ttl name
(integer) 57
127.0.0.1:6379> get name
"Tracy"

1.6 getrange

 获取key对应value的子字符串

127.0.0.1:6379> getrange name 0 -1
"TracyMcgrady"
127.0.0.1:6379> getrange name 0 4
"Tracy"

1.7 mset

 批量设置多个key的值,如果成功表示所有值都被设置,否则返回0表示没有任何值被设置

127.0.0.1:6379> mset name Kobe age 20
OK
127.0.0.1:6379> get name
"Kobe"
127.0.0.1:6379> get age
"20"

1.8 getset

 设置key的值,并返回key旧的值

127.0.0.1:6379> getset name Tracy
"Kobe"
127.0.0.1:6379> get name
"Tracy"

1.9 append

 给指定key的value追加字符串,并返回新字符串的长度

127.0.0.1:6379> append name McGrady
(integer) 12
127.0.0.1:6379> get name
"TracyMcGrady"

1.10 应用场景

 除此之外还有支持一些其他的命令,大家可以查看官网文档。String是最常用的一种数据类型,普通的key/value存储都可以归为此类,value不仅可以存储String类型,也可以存储数字,比如有时我们需要实现某些计数功能,incr命令可以很简单就实现,通过原子递增保持计数。

2.Hash(哈希)

Hash是一个String类型的field和value(键值对)之间的映射表,Redis的Hash数据类型的key(hash表名称)对应的value实际的内部存储结构为一个HashMap,特别适合用于存储对象.相对于把一个对象的每个属性存储为String类型,将整个对象存储在Hash类型中会占用更少内存。所存储的成员较少时数据存储为ZipMap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

2.1 hset

 设置key对应的HashMap中的field的value

127.0.0.1:6379> hset user name Tracy
(integer) 1
127.0.0.1:6379> hset user age 20
(integer) 1

2.2 hget

 获取key对应的HashMap中的field的value

127.0.0.1:6379> hget user name
"Tracy"

2.3 hgetall

 获取key对应的HashMap中的所有field的value

127.0.0.1:6379> hgetall user
1) "name"
2) "Tracy"
3) "age"
4) "20"

2.4 hgetall

 返回key对应的HashMap中的field的数量

127.0.0.1:6379> hlen user
(integer) 2

2.5 应用场景

 当我们需要存储一些结构化的数据时,Hash的作用就体现出来了,我们这里用一个用户的信息来举个例子,假设我们需要去存储一个用户的信息,那么我们有几种做法。
 第一种就是将整个对象序列化之后存储,当我们在正式业务中对象结构复杂并且设计修改时,需要将Value取出反序列化然后修改之后再序列化放回Redis,从各方面增加了开销,并且涉及并发时更加容易造成不必要的麻烦。
在这里插入图片描述
 第二种就是我们通过用户标识以及属性去拼接,一个对象存储N个属性就会产生多少个Key-Value键值对,虽然省去了序列化开销而且避免了并发问题出现,但是用户标识重复存储,当对象属性多或者数据量大时就会造成很多不必要的内存浪费。
在这里插入图片描述
 这里我们的Hash就登场了,在Hash数据结构中,Key依然是我们的用户标识,但是Value对应的是一个Map而不单纯是一个值。
在这里插入图片描述
 通过Hash这种数据结构,我们若需要修改某一个用户的某一个属性,那就十分轻松了,也避免了上面出现的问题。我们知道了Hash结构对应Value内部实际就是一个HashMap,实际Redis做了两种不同实现,当Hash的成员属性较少时为了节省内存会采用类似一维数组的方式来紧凑存储,并未采用真正的HashMap结构,对应Value的redisObject此时encoding为ZipMap,而当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

3.List(列表)

List是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或尾部。

3.1 lpush

 在key对应的list的头部添加一个元素

127.0.0.1:6379> lpush names Tracy Kobe Kevin
(integer) 3

3.2 lrange

 获取key对应的list的指定下标范围的元素,-1表示获取所有元素

127.0.0.1:6379> lrange names 0 -1
1) "Kevin"
2) "Kobe"
3) "Tracy"
127.0.0.1:6379> lrange names 1 1
1) "Kobe"

3.3 lpop

 从key对应的list的头部删除一个元素,并返回该元素

127.0.0.1:6379> lpop names
"Kevin"

3.4 rpop

 从key对应的list的尾部删除一个元素,并返回该元素

127.0.0.1:6379> rpop names
"Tracy"

3.5 rpush

 在key对应的list的尾部添加一个元素

127.0.0.1:6379> lrange names 0 -1
1) "Kobe"
127.0.0.1:6379> rpush names Paul
(integer) 2
127.0.0.1:6379> lrange names 0 -1
1) "Kobe"
2) "Paul"

3.6 应用场景

List应用场景非常多,也是Redis最重要的数据结构之一,比如关注列表,粉丝列表等都可以用Redis的list结构来实现。List就是链表,相信我们基本都接触过,使用List我们可以轻松地实现最新消息排行等功能。List的另一个常用场景就是消息队列,可以利用List的push操作将任务存在List中,然后再用pop操作将任务取出执行。List的实现为一个双向链表,即支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也是使用List结构。

4.Set(集合)

Set是String类型的无序集合。集合成员是唯一的,集合中不能出现重复的数据。它是通过哈希表实现的,所以查找、添加、删除的复杂度都是 O(1)。

4.1 sadd

 在key对应的set中添加一个元素

127.0.0.1:6379> sadd nameset Kobe
(integer) 1
127.0.0.1:6379> sadd nameset Tracy
(integer) 1

4.2 smembers

 获取key对应的set的所有元素

127.0.0.1:6379> smembers nameset
1) "Kobe"
2) "Tracy"

4.3 suion

 获取给定key对应的set并集

127.0.0.1:6379> sadd nameset2 Paul
(integer) 1
127.0.0.1:6379> sunion nameset nameset2
1) "Kobe"
2) "Paul"
3) "Tracy"

4.4 sinter

 获取给定key对应的set交集

127.0.0.1:6379> sadd nameset3 Kobe
(integer) 1
127.0.0.1:6379> sinter nameset nameset3
1) "Kobe"

4.5 spop

 随机返回并删除key对应的set中的一个元素

127.0.0.1:6379> spop nameset
"Tracy"

4.6 scard

 返回集合中元素的数量(Key不存在返回0)

127.0.0.1:6379> scard names
(integer) 3
127.0.0.1:6379> scard users
(integer) 0

4.7 应用场景

SetList类似是一个列表的功能,特殊之处在于Set可以自动排重。当我们需要存储一个不重复的列表数据时,Set是一个很好的选择,并且Set还提供了验证某个成员是否在Set集合内的接口,这个也是List所不能提供的。
Set集合概念就是一些不重复值的组合。利用该数据结构,可以存储一些集合性的数据,比如各社交应用中,可以将一个用户关注的所有人都存放在一个集合中,或者将其所有粉丝存放在一个集合中。利用集合提供的求交集、并集、差集等操作,可以非常方便地实现如共同关注、可能感兴趣等功能。Set内部实际上是一个Value全部为null的HashMap,实际就是通过计算hash值的方式来快速排重的。

5.SortedSet(有序集合)

有序集合(SortedSet)集合(Set)一样也是String类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。通过分数来为集合中的成员进行从小到大的排序。Set是通过HashMap存储,key对应set的元素,value是空对象。在HashMap存储为基准上,还加了一层跳跃表:相当于双向链表,在其基础上添加前往比当前元素大的跳转链接,用这种设计也可以更有效率地进行排序和跳转,关于跳表会写一篇博客介绍。

5.1 zadd

 在key对应的zset中添加一个元素

127.0.0.1:6379> zadd names 90.0 Kobe
(integer) 1
127.0.0.1:6379> zadd names 88.0 Tracy
(integer) 1
127.0.0.1:6379> zadd names 100 Gosling
(integer) 1

5.2 zrange/zrevrange

 zrange:获取key对应的zset中指定范围的元素,-1表示获取所有元素(从小到大)
 zrevrange:获取key对应的zset中指定范围的元素,-1表示获取所有元素(从大到小)

127.0.0.1:6379> zrange names 0 -1
1) "Tracy"
2) "Kobe"
3) "Gosling"
127.0.0.1:6379> zrevrange names 0 -1
1) "Gosling"
2) "Kobe"
3) "Tracy"

5.3 zrangebyscore

 zrange:返回有序集key中,指定分数范围的元素列表

127.0.0.1:6379> zrangebyscore names 80 90
1) "Tracy"
2) "Kobe"

5.4 zrank/zrevrank

 zrank:获取key对应的zset中指定成员(member)的排名。其中member按score值递增(从小到大),排名从0开始
 zrevrank:获取key对应的zset中指定成员(member)的排名。其中member按score值递增(从大到小),排名从0开始

127.0.0.1:6379> zrank names Tracy
(integer) 0
127.0.0.1:6379> zrevrank names Tracy
(integer) 2

5.5 zrem

 zrange:删除key对应的zset中的一个元素

127.0.0.1:6379> zrem names Gosling
(integer) 1
127.0.0.1:6379> zrange names 0 -1
1) "Tracy"
2) "Kobe"

5.6 应用场景

Sorted Set的使用场景与set类似,区别是set不是有序的,而Sorted Set可以根据用户提供一个优先级(score)来为成员排序,并且是插入有序的,即自动排序。当我们需要一个有序并且不重复的集合列表时间,那么选择Sorted Set这种数据结构就十分有效。Sorted Set应用场景也十分广泛,例如全班同学成绩排名,value存储同学的学号,score设置为其考试分数,这样数据插入集合时就已经进行了天然的排序,排行榜类似当日活跃度和用户积分也是这个设计理念。另外还可以用来做带权重的队列,例如普通消息的score为1,重要消息的score为2,工作线程便可以根据score来选择优先执行重要任务。我们还可以score设置为过期时间的时间戳,这样就可以简单地通过过期时间排序,定时清除过期数据了。

6.Pub/Sub(消息发布订阅)

 发布订阅类似于消息管道,用来进行系统之间消息解耦,我们可以设定对某个key值(channel频道)进行消息发布及消息订阅,当一个channel上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这就类似于rabbitmq、activemq、rocketmq、kafka等。

6.1 subscribe

 订阅指定频道的信息

127.0.0.1:6379> subscribe channel_task
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel_task"
3) (integer) 1

6.2 unsubscribe

 取消订阅指定的频道。若不指定则取消订阅所有的频道。

127.0.0.1:6379> unsubscribe channel_task
1) "unsubscribe"
2) "channel_task"
3) (integer) 0

6.3 publish

 将信息message发送到指定的频道channel。返回收到消息的客户端数量。

127.0.0.1:6379> publish channel_task add_user_score
(integer) 1   (此时有一个订阅该频道的客户端收到信息)

6.4 应用场景

  消息发布订阅的模式可以有很多应用场景,例如订单交易成功后会员系统加积分、货物系统出货等操作都可以用该思路去完成,还有平时普通的即时聊天功能也可以通过该功能实现。但是Redis的发布订阅和其他MQ比起来功能更加薄弱,但是也更加轻量。同时由于Redis消息持久化可能会导致数据可靠性比较差,并且没有相比其他MQ提供的丰富后台功能,所以在平时使用消息队列时更多的会选择其他产品。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值