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

  • Post author:
  • Post category:其他




字符串

字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串如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 的读写效率会下降。


使用场景

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



版权声明:本文为weixin_41499498原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。