API的理解和使用-数据类型和基本操作

本文深入介绍了Redis中的五种主要数据结构:字符串、哈希、列表、集合和有序集合。详细阐述了每种数据结构的内部编码方式、常用命令及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字符串

字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串如Json、Xml) ,数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。

命令

(1) 设置值

set key value

set命令有几个选项:
ex seconds: 为键设置秒级过期时间
px milliseconds: 为键设置毫秒级过期时间
nx: 键必须不存在,才可以设置成功,用于添加
xx: 与nx 相反,键必须存在,才可以设置成功,用于更新

set hello world ex 10 nx

setex key seconds value  #设置过期时间
setnx key value #键不存在设置key
set key value xx #对存在的键进行更新

(2) 批量设置值

mset key1 value key2 value2 ...

(3) 批量获取值

mget key1 key2 key3 ...

批量get 可以提高开发效率,假如没有mget,要执行n 次get 命令需要的耗时如下:
n次 get 时间= n次网络时间+n次命令时间

使用mget 后执行n次命令耗时如下:
n次 get 时间= 1次网络时间+n次命令时间

在这里插入图片描述

(4) 计数

incr key

incr 命令用于对值做自增操作,返回结果分为三种情况:
1)值不是整数,返回错误
2)值是整数,返回自增后的结果
3)键不存在,按照值为0自增,返回结果为1

decr key(自减)
incrby key increment (自增指定数字)
decrby key decrement (自减指定数字)
incrbyfloat key increment (自增浮点数)

(5) 追加值
append key value

127.0.0.1:6379> set sichuan chengdu
OK
127.0.0.1:6379> append sichuan shi
(integer) 10
127.0.0.1:6379> get sichuan
"chengdushi"

(6) 字符串长度
strlen key
每个中文占3个字节

127.0.0.1:6379> set hello "世界"
OK
127.0.0.1:6379> strlen hello
(integer) 6

getset 和set 一样可以设置值,但是返回的是原值

127.0.0.1:6379> getset hello world
(nil)
127.0.0.1:6379> getset hello redis
"world"

(7) 设置指定位置的字符
将下面pest 变成best

127.0.0.1:6379> set redis pest
OK
127.0.0.1:6379> SETRANGE redis 0 b
(integer) 4
127.0.0.1:6379> get redis
"best"

(8) 获取部分字符串

getrange key start end

start end 为偏移量从0开始

内部编码

字符串类型的内部编码有三种:

  • int: 8个字节的长整型
  • embstr: 小于等于39个字节的字符串
  • raw: 大于39个字节的字符串
    redis 会根据当前值得类型和长度决定使用哪种内部编码实现。
哈希

哈希类型是指键值对本身又是一个键值对结构,Redis键值对和哈希类型二者的关系如图:
在这里插入图片描述

命令

(1) 设置值
hset key field value

添加一个user

hset user:1 name tom

(2) 获取值
hget key field

hget user:1 name

127.0.0.1:6379> HSET user:1 name tom
(integer) 1
127.0.0.1:6379> hget user:1 name
"tom"

(3) 删除field
hdel 会删除一个或多个field, 结果返回为成功删除的个数

hdel user:1 name

(4) 计算field 的个数
相当于统计对象的属性个数,如user 的age、name…

hlen key

(5) 批量设置或获取field-value
hmset key field value
hmget key field [field]

127.0.0.1:6379> hmset user:1 name tom age 18
OK
127.0.0.1:6379> hmget user:1 name age
1) "tom"
2) "18"

(6) 判断field 是否存在
hexists key field
存在返回1,不存在返回0

(7) 获取所有field
hkeys key

127.0.0.1:6379> hkeys user:1
1) "name"
2) "age"

(8) 获取所有value
hvals key

127.0.0.1:6379> hvals user:1
1) "tom"
2) "18"

(9) 获取所有field和value
hgetall key

127.0.0.1:6379> hgetall user:1
1) "name"
2) "tom"
3) "age"
4) "18"

如果哈希元素比较多,使用hgetall可能会阻塞redis,可以使用hscan,该命令会渐进式遍历哈希类型。

(10) hincrby hincrbyfloat

hincrby key field
hincrbyfloat key field

这两个命令和incrby incrbyfloat 一样只不过作用域是field

(11) 计算value 的字符串长度 (需要redis 3.2以上)
hstrlen key field

内部编码

哈希类型的两种内部编码

  • ziplist(压缩列表)
    当创建哈希类型时,如果哈希的field 个数小于512个,同时value小于64字节时
  • hashtable(哈希表)
    采用ziplist无法满足时,如果field-value不满足ziplist内部编码条件,则采用hashtable内部编码保存时间复杂度为O(1)
列表

列表(list) 类型是用来存储多个有序的字符串,列表中的每个字符串称为元素,一个列表最大存储2^32-1个元素。在redis中可以从列表两端插入和弹出元素。既可以充当队列又可以当栈。

在这里插入图片描述

命令

(1) 添加操作
从右边插入元素。从右至左
rpush key value…value


相当于listkey = [a,b,c]

127.0.0.1:6379> rpush listkey a b c
(integer) 3

(2) 获取所有元素
lrange key 0 -1

127.0.0.1:6379> lrange listkey 0 -1
1) "a"
2) "b"
3) "c"

(3) 从左边插入
lpush key value
和从右边插入结果一样,只不过从左侧插入

127.0.0.1:6379> lpush listkey2 a b c
(integer) 3
127.0.0.1:6379> lrange listkey 0 -1
1) "a"
2) "b"
3) "c"

(4) 插入元素
在某个元素前插入
linsert key before 元素 new元素
如在c++ 前面插入java,返回结果为元素长度

127.0.0.1:6379> lrange dev 0 -1
1) "php"
2) "java"
3) "c"
127.0.0.1:6379> linsert dev before java c++ 
(integer) 4
127.0.0.1:6379> lrange dev 0 -1
1) "php"
2) "c++"
3) "java"
4) "c"

在某个元素后插入
linsert key after 元素 new元素

(5) 查找

  • 获取指定范围内的元素列表
    lrange key start end
    索引从左至右为0到N-1,但是从右至左为-1到-N
    上面已经使用过了,不再举例

  • 获取指定索引的元素
    lindex key index

      127.0.0.1:6379> lindex dev 0
      "php"
    
  • 获取列表长度
    llen key
    比如有4个元素

      127.0.0.1:6379> llen dev
      (integer) 4
    

(6) 删除

  • 从列表左侧弹出元素
    lpop key

“php” 最先弹出

127.0.0.1:6379> lrange dev 0 -1
1) "php"
2) "c++"
3) "java"
4) "c"
127.0.0.1:6379> lpop dev
"php"
127.0.0.1:6379> lrange dev 0 -1
1) "c++"
2) "java"
3) "c"
  • 从列表右侧删除
    rpop key

  • 删除指定元素
    lrem key count value
    根据count 的不同分为三种类型:
    count > 0 ,从左至右,删除最多count 个等于value的元素
    count < 0 ,从左至右,删除最多|count| 个等于value的元素
    count = 0 ,删除所有
    比如删除所有"c"

      127.0.0.1:6379> lrange dev 0 -1
      1) "c"
      2) "c++"
      3) "java"
      4) "c"
      127.0.0.1:6379> lrem dev 0 "c"
      (integer) 2
    
  • 按照索引范围修剪列表
    ltrim key start end
    比如只保留第1个和第2个元素

      ltrim dev 0 1
    

(7) 修改
修改指定下标的元素:
lset key index newvalue
比如将第1个元素改为"python"

127.0.0.1:6379> lrange dev 0 -1
1) "c++"
2) "java"
127.0.0.1:6379> lset dev 1 python
OK
127.0.0.1:6379> lrange dev 0 -1
1) "c++"
2) "python"

(8) 阻塞操作
阻塞式弹出如下:
blpop key [key…] value timeout
brpop key [key…] value timeout

  • 列表为空:如果timeout=3,那么客户端要等到3秒后返回,如果timeout=0,那么客户端一直阻塞下去,直到有新元素进来pop后返回给客户端以及阻塞时间。

      127.0.0.1:6379> brpop list 3
      (nil)
      (3.07s)
    

    先执行brpop dev 0 再添加元素后的结果如下
    
    127.0.0.1:6379> lpush dev php
    (integer) 1
    127.0.0.1:6379> brpop dev 0
    1) "dev"
    2) "php"
    (30.45s)
  • 如果列表不为空,客户端立即返回并弹出一个元素

      127.0.0.1:6379> brpop dev 0
      1) "dev"
      2) "python"
      127.0.0.1:6379> lrange dev 0 -1
      1) "c++"
    

注意在使用brpop 时,有两点需要注意:
第一,如果是多个键,那么brpop 会从左至右遍历,一旦有一个键能弹出元素,客户端立即返回。
第二,如果多个客户端对同一个键执行brpop,那么最先执行的brpop 命令的客户端可以获取到弹出的值。

内部编码

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

  • ziplist:当列表的值元素个数小于list-max-ziplist-entries(默认是512个),且每个元素的值小于64自己时,redis采用ziplist的形式存储列表,减少了内存的使用。
  • linkedlist:当列表其值不满足ziplist的条件的时候,redis会采用链表的形式存储值。
    但在redis3.2版本之后,当元素大于512个或元素大小超过64个字节,内部编码已从linkedlist变为quicklist。quicklist采用了ziplist的优点和linkedlist的优点,也就是每个节点都是一个ziplist节点之间用双向的指针联系起来,这样即使得内存使用的减少满足了快速的插入和删除,也减少了空间的冗余。
使用场景

lpush+lpop=Stack(栈)

lpush+rpop=Queue(队列)

lpsh+ltrim=Capped Collection(有限集合)

lpush+brpop=Message Queue(消息队列)

集合

集合(set) 类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复的元素,并且集合中的元素是无序,不能通过索引下标获取元素。

命令

(1) 集合内操作
添加元素
sadd key element

127.0.0.1:6379> sadd project c c++ java
(integer) 3

删除元素
srem key element

返回成功删除的个数

127.0.0.1:6379> srem project c++
(integer) 1

计算元素个数
scard key
scard 时间复杂度为O(1),它不会遍历所有元素,二是直接用redis 内部变量

127.0.0.1:6379> scard project
(integer) 2

判断元素是否在集合中
sismember key element
存在返回1。反之为0

127.0.0.1:6379> sismember project java
(integer) 1

随机从集合中返回指定元素个数
srandmember key count

127.0.0.1:6379> srandmember project 2
1) "c"
2) "java"

从集合中随机弹出元素
spop key

127.0.0.1:6379> spop project 
"c"
 c 已经从集合中删除

获取所有元素
smembers key

127.0.0.1:6379> smembers project
1) "java"

(2) 集合间操作

求多个集合的交集

sinter key key

127.0.0.1:6379> sadd project c++ php
(integer) 2
127.0.0.1:6379> sadd project2 c++ java python net
(integer) 4
127.0.0.1:6379> sinter project project2
1) "c++"
2) "java"

求多个集合的并集
sunion key key

127.0.0.1:6379> sunion project project2
1) "python"
2) "c++"
3) "php"
4) "java"
5) "net"

求多个集合的差集
sdiff key key

127.0.0.1:6379> sdiff project project2
1) "php"
127.0.0.1:6379> sdiff project2 project
1) "python"
2) "net"

将交集、并集、差集的结果保存
sinterstore destination key key
sunionstore destination key key
sdiffstore destination key key

127.0.0.1:6379> smembers project2
1) "c"
2) "php"
3) "net"
127.0.0.1:6379> smembers project
1) "python"
2) "c++"
3) "java"
4) "net"
127.0.0.1:6379> sinterstore store project project2
(integer) 1
127.0.0.1:6379> smembers store
1) "net"

store 本身也是一个集合

内部编码

集合(set)类型的两种内部编码

  • intset(整数集合)
  • 当创建集合类型时,如果集合的元素个数小于512个,且元素都为整数是内部编码为intset
  • hashtable(哈希表)
    采用intset为内部编码保存,如果元素和元素值不满足intset内部编码条件,则采用hashtable内部编码保存
使用场景

集合类型比较典型的使用场景是标签(tag),例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣就是标签。

有序集合

有序集合保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。和列表下标不一样的是,它是给每个元素设置一个分数(score) 作为排序的依据。

命令

(1) 集合内
添加成员
zadd key score member [score member…]

127.0.0.1:6379> zadd user 150 tom
(integer) 1

Redis3.2 为zadd 命令添加了nx,xx,ch,incr 四个选项:
nx: member 必须不存在,才可以设置成功,用于添加
xx: member 必须存在,才可以设置成功,用于更新
ch: 返回此次操作后,有序集合元素和分数发生变化的个数
incr: 对score 做增加,相当于后面介绍的zincrby
有序集合相比集合增加了排序字段,但是也产生了代价,zadd 的时间复杂度为O(log(n)),sadd 的时间复杂度为O(1)

计算成员个数
zcard key

计算某个成员的分数
zsocre key member

127.0.0.1:6379> zscore user tom
"150"

计算成员排名
zrank key member
zrevrank key member

zrank 是从分数从低到高返回排名,zrevrank 反之。排名从0开始

127.0.0.1:6379> zrank user tom
(integer) 1
127.0.0.1:6379> zrank user jack
(integer) 0

删除成员
zrem key member

127.0.0.1:6379> zrem user tom
(integer) 1

增加成员的分数
zincrby key increment member
jack 增加10分

127.0.0.1:6379> zincrby user 10 jack
"130"

返回指定排名范围内的成员
zrange key start end [withscores]

127.0.0.1:6379> zrange user 0 2 withscores
1) "rank"
2) "80"
3) "tom"
4) "100"
5) "jack"
6) "130"

zrange 是从低到高返回,zrevrange 反之,如果加上withscores 参数则连分数一起返回。

返回指定分数范围内的成员
zrangevyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offset count]

127.0.0.1:6379> zrangebyscore user 100 150
1) "tom"
2) "jack"

min 和max 还支持开区间()和闭区间[], -inf 和+inf 分别代表无限小和无限大。

返回指定分数范围内的个数
zcount key min max

127.0.0.1:6379> zcount user 120 200
(integer) 1

删除指定排名内的升序元素
zremrangebyrank key start end

删除指定分数范围内的成员
zremrangebyscore key min max

(2) 集合间操作
交集
zinterstore destination numkeys key … [weights weight…] [aggregate sum|min|max]
这个命令参数较多,下面分别进行说明

destination: 交集计算结果保存到这个键
numkeys:需要做交集计算键的个数
key[key…]: 需要做交集计算的键
weights weight[weight…] :每个键的权重,在做交集计算时,每个键中的的每个member 会将自己分数乘以这个权重,每个键的权重默认是1。
aggregate sum|min|max: 计算成员交集后,分值可以按照sum、min、max 做汇总,默认值是sum

sum:取交集后值相加
max:取交集后保留值最大的

127.0.0.1:6379> zinterstore store2 2 user user2 weights 1 0.5 aggregate max
(integer) 2
127.0.0.1:6379> zrange store2 0 -1 withscores
1) "tom"
2) "100"
3) "jack"
4) "130"

并集
zunionstore destination numkeys key … [weights weight…][aggregate sum|min|max]

内部编码

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

  • ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value 配置(64字节)时,redis 会使用ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使用。
  • skiplist(跳跃表):当ziplist 条件不满足时,有序集合会使用skiplist 作为内部实现,因为此时ziplist 的读写效率会下降。
使用场景

有序集合比较典型的使用场景就是排行榜系统。例如视频网站的播放量排行,榜单的维度可能是时间、播放量、点赞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值