Redis的五种基本数据类型

数据类型简介

redis无论什么数据类型,在数据库中都是以key-value形式保存,并且所有的key(键)都是字符串,所以讨论基础数据结构都是讨论的value值的数据类型
主要包括常见的5种数据类型 如下图:
在这里插入图片描述redis 是 key-value 存储系统
其中key类型一般为字符串,value 类型则为redis对象(redisObject)
数据存储方式如下图:
在这里插入图片描述
操作Redis命令之前需要先连接 Redis客户端
可以使用 redis-cli 命令连接到 Redis 服务器。例如:

redis-cli -h host -p port -a password

其中 host 是 Redis 服务器的主机名,port 是 Redis 服务器的端口号,password 是连接密码(如果有)。

1、string 类型

string 类型存储单个数据,是最简单的数据存储类型,也是最常用的数据存储类型。
存储的内容为 string 字符串类型,如果字符串中的数据是整数形式,也可以进行相应的数字操作。
一个存储空间只能保存一个数据

在这里插入图片描述

1.1、常用的命令

设置键值
要设置一个键值对,请使用SET命令。例如,要将键“name”设置为值“aaa”,可以执行以下操作:

127.0.0.1:6379> SET name  aaa

获取键值
要获取键值,请使用GET命令。例如,要获取键“name”的值,可以执行以下操作:

127.0.0.1:6379> GET name

设置过期时间
要为一个键设置过期时间,请使用EXPIRE命令。例如,要将键“name”的过期时间设置为60秒,可以执行以下操作:

127.0.0.1:6379> EXPIRE name 60

查看过期指定key的过期时间,可以用TTL命令

127.0.0.1:6379> TTL  name

返回的结果便是剩余时间(到期key会自动删除),如果返回-1,则表示无过期时间

判断键是否存在
要检查一个键是否存在,请使用EXISTS命令。例如,要检查键“name”是否存在,可以执行以下操作:

127.0.0.1:6379> EXISTS name

如果键存在,则返回1;如果键不存在,则返回0。

删除键
要删除一个键,请使用DEL命令。例如,要删除键“name”,可以执行以下操作:

127.0.0.1:6379> DEL aaa

自增/自减操作
要对一个键进行自增操作,请使用INCR命令。例如,要将键“cnt”自增1,可以执行以下操作:

127.0.0.1:6379> INCR cnt

类似地,要对一个键进行自减操作,请使用DECR命令。

1.2、注意事项

Redis 的所有操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,所以无需考虑并发带来的数据影响。
数据最大存储量为 512 MB,一般我们多不会超过这个数值。
数值计算的最大范围,对应于 Java 中的 long 型最大值。

1.3、使用场景

  • 缓存功能:String字符串是最常用的数据类型,不仅仅是Redis,各个语言都是最基本类型,因此,利用Redis作为缓存,配合其它数据库作为存储层,利用Redis支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力。
  • 计数器:许多系统都会使用Redis作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。
  • 共享用户Session:用户重新刷新一次界面,可能需要访问一下数据进行重新登录,或者访问页面缓存Cookie,但是可以利用Redis将用户的Session集中管理,在这种模式只需要保证Redis的高可用,每次用户Session的更新和获取都可以快速完成。大大提高效率。
  • 分布式锁
  • 分布式系统全局序列号

2、Hash(哈希)

Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map<String,Object>
Redis 中每个 hash 可以存储 2^32- 1 键值对(40多亿)。

例如
用户ID为查找的key,存储的value为用户对象,包含姓名,年龄,性别等信息,如果用普通的key/value结构来存储
主要有以下3种存储方式:

  • 每次修改用户的某个属性需要,先反序列化改好后再序列化回去。开销较大
    在这里插入图片描述

  • 以用户ID与属性拼接为key,数据为value存储,数据冗余、繁杂。
    在这里插入图片描述

  • 通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。
    在这里插入图片描述

2.1、常用命令

  • 设置 key 指定的哈希集中指定字段的值。
hset key field value

如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将被重写。

  • 返回 key 指定的哈希集中该字段所关联的值
hget key field

当字段不存在或者 key 不存在时返回nil

  • 批量设置hash的值
hmset key field1 value1 field2 value2......

该命令将重写所有在哈希集中存在的字段。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联

  • 返回 key 指定的哈希集中指定字段的值。
hmget key field1  field2......

对于哈希集中不存在的每个字段,返回 nil 值。因为不存在的keys被认为是一个空的哈希集,对一个不存在的 key 执行 HMGET 将返回一个只含有 nil 值的列表

  • 查看哈希表 key 中,给定域 field 是否存在。
hexists key field

返回1 hash里面包含该field。返回0 hash里面不包含该field或者key不存在。

  • 列出该hash集合的所有field
hkeys key

哈希集中的字段列表,当 key 指定的哈希集不存在时返回空列表。

  • 列出该hash集合的所有value
hvals key

哈希集中的字段列表,当 key 指定的哈希集不存在时返回空列表。

  • 为哈希表 key 中的域 field 的值加上增量
hincrby key field increment

如果 key 不存在,会创建一个新的哈希集并与 key 关联。如果字段不存在,则字段的值在该操作执行前被设置为 0,HINCRBY 支持的值的范围限定在 64位 有符号整数

  • 为指定key的hash的field字段值执行float类型的increment加
hincrbyfloat key field increment

如果field不存在,则在执行该操作前设置为0.如果出现下列情况之一,则返回错误:field的值包含的类型错误(不是字符串)。当前field或者increment不能解析为一个float类型。

  • 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在
hsetnx key field value

只在 key 指定的哈希集中不存在指定的字段时,设置字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段已存在,该操作无效果。

  • 返回 key 指定的哈希集包含的字段的数量。
hlen key

哈希集中字段的数量,当 key 指定的哈希集不存在时返回 0

  • 返回hash指定field的value的字符串长度
hstrlen key field

如果hash或者field不存在,返回0.

  • 返回 key 指定的哈希集中所有的字段和值。
hgetall key

返回值中,每个字段名的下一个是它的值,所以返回值的长度是哈希集大小的两倍.当 key 指定的哈希集不存在时返回空列表。

  • 从 key 指定的哈希集中移除指定的一个或多个field。
hdel key field1 field2......

在哈希集中不存在的域将被忽略。如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0。

2.2、使用场景

  • 适用于存储对象,比如把用户的信息存到hash里,以用户id为key,用户的详细信息为value。
  • 电商购物车,以用户ID为key,商品ID为field,商品数量为value。

3、List(列表)

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 2^32- 1 个元素 (4294967295, 每个列表超过40亿个元素)。

在这里插入图片描述

3.1、常用命令

  • push 插入元素
#lpush,在头部插入
#将一个值或者多个值,插入到列表的头部。

127.0.0.1:6379> lpush list one
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3

#使用lpush,这里的l可以看成left,也就是在左边插入,所以目前list是这样的[three, two, one]。
#rpush,在尾部插入
#接下来,使用rpush,在右边也就是在列表尾部插入元素。

127.0.0.1:6379> rpush list right1 right2
(integer) 5

#此时,list是这样的[three, two, one, right1, right2]。用lrange list 0 -1来获取下:

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right1"
5) "right2"
127.0.0.1:6379> 
  • range 通过区间获取元素
#可以想象成python里的range(),通过传入开始和结束的下标,获取元素。

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right1"
5) "right2"
127.0.0.1:6379> lrange list 1 4
1) "two"
2) "one"
3) "right1"
4) "right2"
127.0.0.1:6379> 
  • pop 移除元素
#既然上面可以左右的添加操作,那么移除自然也有左右之分了。
#移除操作,返回的是被移除的元素。

# lpop 左边移除
127.0.0.1:6379> lpop list
"three"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "right1"
4) "right2"
127.0.0.1:6379> 

#rpop 右边移除
127.0.0.1:6379> rpop list
"right2"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "right1"
127.0.0.1:6379> 
  • lindex 通过下标获取元素
    lindex list 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "right1"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> lindex list -1
"right1"
127.0.0.1:6379> 
  • llen 获取list长度
127.0.0.1:6379> llen list
(integer) 3
127.0.0.1:6379> 
  • lrem 移除指定元素
    lrem list 2 one
#现在list里有4个one,我要移除2个。

127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "one"
3) "one"
4) "two"
5) "one"
6) "right1"
127.0.0.1:6379> lrem list 2 one
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
3) "one"
4) "right1"
127.0.0.1:6379> 
  • exists 判断key 是否存在
    exists list
127.0.0.1:6379> exists list
(integer) 1
127.0.0.1:6379> 

#存在返回1,不存在就返回0。
  • lset,设置指定下标的值
    lset list 1 test
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
3) "one"
4) "right1"
127.0.0.1:6379> lset list 1 test
OK
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "test"
3) "one"
4) "right1"
127.0.0.1:6379> 
  • linsert,指定位置之前/之后插入值
#之前:
#linsert list before test before_test
#这是在元素test之前,插入元素before_test。

127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "test"
3) "one"
4) "right1"
127.0.0.1:6379> linsert list before test before_test
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "before_test"
3) "test"
4) "one"
5) "right1"
127.0.0.1:6379> 

#之后:
#linsert list after test after_test
#这是在元素test之后,插入元素after_test。

127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "before_test"
3) "test"
4) "one"
5) "right1"
127.0.0.1:6379> linsert list after test after_test
(integer) 6
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "before_test"
3) "test"
4) "after_test"
5) "one"
6) "right1"
127.0.0.1:6379> 

3.2、使用场景

  • Stack栈:LPUSH+LPOP
  • Queue队列:LPUSH+RPOP
  • Blocking MQ阻塞队列:LPUSH+BRPOP
  • 最新列表,List 类型的 lpush 命令和 lrange 命令能实现最新列表的功能,每次通过 lpush 命令往列表里插入新的元素,然后通过 lrange 命令读取最新的元素列表,如朋友圈的点赞列表、评论列表:

4、Set(集合)

Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 2^32- 1 (4294967295, 每个集合可存储40多亿个成员)。
Redis的set(集合)相当于Java语言里的HashSet,它内部的键值对是无序的、唯一的。它的内部实现了一个所有value为null的特殊字典。
集合中的最后一个元素被移除之后,数据结构被自动删除,内存被回收。
在这里插入图片描述

4.1、常用命令

  • sadd -> 添加集合成员,key值集合名称,member值集合元素,元素不能重复
127.0.0.1:6379> sadd name aaa
(integer) 1
127.0.0.1:6379> sadd name aaa       # 不能重复,重复返回0
(integer) 0
127.0.0.1:6379> sadd name bbb ccc ddd # 支持一次添加多个元素
(integer) 3
  • smembers -> 查看集合中所有的元素,注意是无序的
127.0.0.1:6379> smembers name    # 无序输出集合中所有的元素
1) "bbb"
2) "ccc"
3) "aaa"
4) "ddd"
  • sismember -> 查询集合中是否包含某个元素
127.0.0.1:6379> sismember name aaa  # 包含返回1
(integer) 1
127.0.0.1:6379> sismember name tianqi # 不包含返回0
(integer) 0
  • scard -> 获取集合的长度
127.0.0.1:6379> scard name
(integer) 4
  • spop -> 弹出元素,count指弹出元素的个数
127.0.0.1:6379> spop name    #默认弹出一个
"aaa"
127.0.0.1:6379> spop name 3
1) "bbb"
2) "ccc"
3) "ddd"

4.2、使用场景

  • 标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。
  • 点赞,或点踩,收藏等,可以放到set中实现

5、zset(sorted set:有序集合)

Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。
有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。
在这里插入图片描述

5.1、常用命令

  • zadd -> 向集合中添加元素,集合不存在则新建,key代表zset集合名称,score代表元素的权重,member代表元素
    zadd key [NX|XX] [CH] [INCR] score member [score member …]
127.0.0.1:6379> zadd user:ranking 251 tom
(integer) 1
127.0.0.1:6379> zrange user:ranking 0 -1
1) "tom"
127.0.0.1:6379> zadd user:ranking 1 kris 91 mike 200 frank 220 tim 250 martin
(integer) 5
127.0.0.1:6379> zrange user:ranking 0 -1
1) "kris"
2) "mike"
3) "frank"
4) "tim"
5) "martin"
6) "tom"
  • 计算成员个数(zcard)
127.0.0.1:6379> zcard user:ranking
(integer) 6
  • 计算某个成员分数(zscore)
127.0.0.1:6379> zscore user:ranking mike
"91"
  • 计算成员排名(zrank)
    排序默认是从0开始。
127.0.0.1:6379> zrank user:ranking mike
(integer) 1
127.0.0.1:6379> zrank user:ranking kris
(integer) 0
  • 删除成员(zrem)
127.0.0.1:6379> zrem user:ranking tim
(integer) 1
127.0.0.1:6379> zrange user:ranking 0 -1
1) "kris"
2) "mike"
3) "frank"
4) "martin"
  • 增加成员的分数(zincrby)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "91"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zincrby user:ranking 9 mike
"100"
  • 返回指定排名范围的成员(zrange由高到低)(zrevrange由低到高)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "100"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zrevrange user:ranking 0 -1 withscores
1) "martin"
2) "250"
3) "frank"
4) "200"
5) "mike"
6) "100"
7) "kris"
8) "1"
  • 返回指定分数范围的成员(zrangebyscore由高到低)(zrevrangebyscore由低到高)
127.0.0.1:6379> zrangebyscore user:ranking 100 200 withscores
1) "mike"
2) "100"
3) "frank"
4) "200"
127.0.0.1:6379> zrevrangebyscore user:ranking 300 10 withscores
1) "martin"
2) "250"
3) "frank"
4) "200"
5) "mike"
6) "100"
  • 返回指定分数范围成员个数(zcount)
127.0.0.1:6379> zrange user:ranking 0 -1 withscores
1) "kris"
2) "1"
3) "mike"
4) "100"
5) "frank"
6) "200"
7) "martin"
8) "250"
127.0.0.1:6379> zcount user:ranking 100 200
(integer) 2

5.2、使用场景

  • 排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。
  • 成绩排行:按成绩排序。
  • 权重分配:可以用sorted set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Netocc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值