Redis 的 key 和数据类型

Redis 是一个高性能的键值对(key-value) 内存数据库。它支持存储的 value 类型十分丰富。性能极高,读写速度每秒 10w 次以上。

Redis 的操作是原子性的。要么成功执行,要么失败完全不执行。单个操作是原子性的,多个操作也支持事务,即原子性,通过 multi 和 exec 指令实现。

Redis 支持两种持久化机制:RDB(全量数据快照) 和 AOF(追加写命令到日志文件)。

关于 key

所有数据结构(数据类型)的 key 都是合法的字符串,区别主要在于 value 存储的数据结构不同。如 string 类型的 value 是 string,hash 类型的 value 是 hash 表(多个属性、属性值对组成)。

key 的命名

小技巧: 关于 key 的使用有一个小技巧,对 key 进行格式化设计。

key 的基本命名规范

系统名称(或服务名称)、数据库表名、字段名、唯一标识符(如具体的 id 值),中间用一个英文冒号 : 分割

sys_name:table_name:col_name:{unique_id}

# 常见的设置登录 token
# key:  sso:user:uid:101  
# value:xgGy0Th9CoIb88NR8oVWhlihoM

set sso:user:uid:101 xgGy0Th9CoIb88NR8oVWhlihoM

与 key 相关的命令

基本命令

# 统计当前 db 中 key 的个数
dbsize

# 切换 db,通常共有 16 个 db(索引是 0~15)
# 0 号数据库,是 redis 客户端的默认 db
select 0

127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> select 0
OK
127.0.0.1:6379>
# 清空当前 db 中的所有 key
# 不要在生产环境执行!!!
flushdb 

查找符合指定模式的 key

基本语法:keys <pattern>

keys 命令用于查找(或过滤)所有符合指定模式(pattern)的键。返回匹配的键组成的数组。

Redis 支持的匹配模式如下:

  • ?:匹配单个任意字符。例如,h?llo 可以匹配 hello、hhllo、hxllo 等。
  • *:匹配零个或者多个任意字符。例如,h*llo 可以匹配 hllo、hello、heeello 等。
  • []:匹配中括号范围内的任意一个字符。例如,h[a-z]llo可以匹配hello、hgllo、hzllo。
  • 可以使用反斜线来转义特殊字符。
# 查看所有的键
# 由于 Redis 中有大量的 key,切勿在生产环境执行
keys * 
# 查看以 ss 开头、以 101 结尾的键
127.0.0.1:6379> keys ss*101
1) "sso:user:101"

检查指定的 key 是否存在

exists 命令用于检查指定的键是否存在。存在返回 1,否则返回 0。

127.0.0.1:6379> exists sso:user:101
(integer) 1

查看 key 对应的 value 值的类型

type 命令用于返回键所存储的 value 值的类型,如果键不存在就返回 none。

127.0.0.1:6379> type sso:user:101
string
127.0.0.1:6379> type abcdef
none

以秒为单位设置 key 的过期时间

expire 命令用于设置键的过期时间(以秒为单位)。成功返回 1,如果键不存在或者不能为键设置过期时间时,则返回 0。

# 3600 秒后过期
127.0.0.1:6379> expire sso:user:101 3600
(integer) 1
127.0.0.1:6379> expire abc 60
(integer) 0
127.0.0.1:6379> get abc
(nil)

注意:如果使用 set 修改了 key 对应的 value 值,key 的过期时间会被重置为默认值 -1(永不过期)。

以秒为单位设置 key 的过期时间戳

expireat 命令用于以 Unix 时间戳(Unix timestamp)格式设置键的过期时间。成功返回 1。

expireat sso:user:101 1677058313 

以毫秒为单位设置 key 的过期时间

pexpire 命令用于设置键的过期时间(以毫秒为单位)。成功返回 1。

# 60 秒后过期
127.0.0.1:6379> pexpire sso:user:101 60000
(integer) 1

以毫秒为单位设置 key 的过期时间戳

pexpireat 命令用于设置键的过期时间戳(以毫秒为单位)。成功后返回 1。

127.0.0.1:6379> pexpireat sso:user:101 1677058313000
(integer) 1

修改 key 的名称

rename 命令用于修改键的名称。不会影响 key 的过期时间。

127.0.0.1:6379> rename sso:user:101 sso:user:102
OK

renamenx 命令用于修改键的名称,新的键名不能已存在(可避免旧键名将已存在的新键名覆盖)。 成功返回 1,失败返回 0。

127.0.0.1:6379> mset mk a mk2 b
OK
127.0.0.1:6379> renamenx mk mk2
(integer) 0
127.0.0.1:6379> renamenx mk2 mk3
(integer) 1

删除 key 的过期时间限制

persist 命令用于删除给定键的过期时间,使得键永不过期。成功后返回 1,否则返回 0。

127.0.0.1:6379> persist sso:user:101
(integer) 1

查看 key 的过期时间

ttl 命令用于查看键的过期时间。返回秒数,-1 表示永不过期,-2 表示键不存在。

127.0.0.1:6379> set mk foo
OK
127.0.0.1:6379> ttl mk
(integer) -1
127.0.0.1:6379> pexpire mk 60000
(integer) 1
127.0.0.1:6379> ttl mk
(integer) 57
127.0.0.1:6379> set mk bar
OK
127.0.0.1:6379> ttl mk
(integer) -1

删除 key

del 命令用于删除已存在的键(一个或多个):不存在的键会被忽略,返回被删除键的数量。

127.0.0.1:6379> mset mk a mk2 b
OK
127.0.0.1:6379> del mk uuu mk2 vvv
(integer) 2

迭代遍历 key

scan 命令用于迭代遍历所有的 key。

语法:scan cursor [MATCH pattern] [COUNT count]

  • cursor 游标,每次迭代需根据返回的 cursor 值,调整 cursor,当整个遍历结束时,返回 0。
  • pattern 按指定的模式匹配 key。
  • count 每次遍历获取的数量。
127.0.0.1:6379> dbsize
(integer) 27

127.0.0.1:6379> scan 0 match * count 20
1) "3"
2)  1) "c3"
    2) "z3"
    3) "sa"
    4) "user"
    5) "c2"
    6) "str"
    7) "name"
    8) "test"
    9) "st2"
   10) "stack"
   11) "name3"
   12) "counter"
   13) "zr2"
   14) "name2"
   15) "bighash"
   16) "st3"
   17) "name1"
   18) "sites"
   19) "z2"
   20) "z1"
127.0.0.1:6379> scan 3 match * count 20
1) "0"
2) 1) "d"
   2) "st"
   3) "zr3"
   4) "ms"
   5) "que2"
   6) "bi"
   7) "zr"

当 redis 中的 key 非常多时,不宜使用 keys *,因为它会导致服务器短暂卡顿(阻塞)。这时,就适合采用 scan 分批获取数据。

注意:如果遍历过程中,key 发生了变化(新增、删除),会影响遍历的结果。scan 本质上属于分页获取数据,并不能保证准确地遍历出所有的 key。

value 的数据类型

Redis 是一个 key => value 键值对形式的数据库。

对于 key 对应的 value 值,Redis 支持多种数据类型(数据结构)。

基础数据类型:

  • string(字符串)
  • list(链表)
  • hash(哈希)
  • set(无序集合)
  • zset(有序集合)

复杂数据类型

  • bitmap(位数组)
  • hyperloglog(基数统计)
  • geo(地理位置,3.2 版本新增)
  • bloomfilter(布隆过滤器)
  • stream(流,5.0 版本新增)

string

string 即字符串,它是最简单最常用的数据类型。 它能够存储任何类型的字符串,包括数值、字符串、json字符串、二进制、base64 编码的图片。

在 Redis 中,字符串的最大容量为 512MB。

应用场景

  • 计数器,如统计浏览次数、incr 限流等
  • 鉴权 token
  • 热点数据缓存
  • 分布式互斥锁
  • 全局自增 ID

常用命令

set 用于设置 key 的 value。

语法:set key value [EX seconds] [PX milliseconds] [NX|XX]

  • EX seconds 表示以秒为单位设置有效期。
  • PX milliseconds 表示以毫秒为单位设置有效期。
  • NX 表示只有当 key 不存在时,才进行设置。
  • XX 表示只有当 key 已存在时,才进行设置。
  • 如果没有 NX 和 XX 选项,key 存在就更新,不存在就新增。
# 如果 key 已经存在,则覆盖原先的 value。否则,就新增。
set name jack

# 同时设置有效期(秒数),仅当 key 已存在时才操作。
set name lily ex 9999 xx

# 同时设置有效期(秒数),如果 key 已经存在,则覆盖原先的 value。否则,就新增。
setex name 9999 rose

# 同时设置有效期(秒数),仅当 key 不存在时才操作;否则,返回 nil
set name2 rose2 ex 9999 nx

# 仅当 key 不存在时才操作;否则,返回 0
setnx name3 rose3

setex 和 setnx 命令其实是在 set 命令的基础上衍生出来的。用法示例如上。

get 用于获取 key 对应的 value。如果 key 不存在,就返回 nil。

语法:get key

127.0.0.1:6379> get name
"rose"    

setrange 用于替换 value 中的子字符串,从 offset 偏移量处开始替换(offset 的最小值为 0)。返回新字符串的长度。

语法:setrange key offset value

set email lijie@163.com         // OK
setrange email 6 gmail.com      // (integer) 15
get email                       // "lijie@gmail.com"

getrange 用于获取 key 对应的 value 的子串。

语法:getrange key start end

  • start 表示起始位置。0 表示第一个位置。
  • end 表示结束位置。对于最后一个位置,有两种写法(-1 和 strlen - 1)。
  • 获取字符串的子串时,包含 start 和 end 处的字符。
127.0.0.1:6379> getrange name 0 -1
"rose"
127.0.0.1:6379> getrange name 0 3
"rose"

getset 用于设置 key 的 value,同时返回旧的 value。

语法:getset key value

127.0.0.1:6379> getset name newrose
"rose"

mset 用于设置一个或多个 key-value 对。

语法:mset key value [key value ...]

127.0.0.1:6379> mset name1 jack1 name2 jack2
OK

mget 用于获取一个或多个 key 的 value。

语法:mget key [key ...]

127.0.0.1:6379> mget name1 name2
1) "jack1"
2) "jack2"        

msetnx 用于对一个或多个不存在的 key,设置 value。如果有已存在的 key,就都失败。

语法:msetnx key value [key value ...]

127.0.0.1:6379> msetnx name101 jack101 name rose
(integer) 0
127.0.0.1:6379> get name101
(nil)

strlen 用于获取 key 对应的 value 的长度。

语法:strlen key

127.0.0.1:6379> strlen name
(integer) 7              

incr 用于将 key 对应的 value 加 1,返回新的 value。如果 key 之前不存在,先将 key 的 value 初始化为 0,再进行 incr 加 1 操作(只能对数值进行操作)。

语法:incr key

127.0.0.1:6379> incr counter
(integer) 1
127.0.0.1:6379> incr counter
(integer) 2

incrby 用于将 key 对应的 value,加上指定的增量(increment)。这个增量可为负数。

语法:incrby key increment

127.0.0.1:6379> incrby c2 8
(integer) 8
127.0.0.1:6379> incrby c2 -3
(integer) 5              

incrbyfloat 用于将 key 对应的 value,加上指定的浮点数增量。

语法:incrbyfloat key increment

127.0.0.1:6379> incrbyfloat c2 1.2
"6.20000000000000018"

decr 用于将 key 对应的 value 减 1,返回新的 value。 和 incr 类似,还有 decrby 命令。

语法:decr key

127.0.0.1:6379> decr c3
(integer) -1
127.0.0.1:6379> decr c3
(integer) -2
127.0.0.1:6379> decrby c3 5
(integer) -7             

append 用于在 key 对应的 value 的末尾追加字符串。返回新字符串的长度。可对不存在的 key 操作。

语法:append key value

127.0.0.1:6379> append str aaa
(integer) 3
127.0.0.1:6379> append str bbb
(integer) 6
127.0.0.1:6379> get str
"aaabbb"

hash

hash 是一个 string 类型的属性(字段)和属性值的映射表。也称哈希表。

hash 最多能存储 2^32 - 1 个 field-value 对。

hash 特别适合用于存储对象。

相较于将整个对象信息存储为单个 string 类型,将对象存储在 hash 类型中占用的内存更少,便于存取、新增和删除对象的部分属性(字段)。

应用场景

  • 存储用户信息
  • 小型的实时数据库
  • 购物车
  • 计数器(统计网站每天和每月的访问量,商品的好评和差评数)

常用命令

hset 用于设置 hash 表的一个属性和属性值。

语法:hset key field value

127.0.0.1:6379> hset user name jack
(integer) 1
127.0.0.1:6379> hset user name rose
(integer) 0
127.0.0.1:6379> hset user age 18
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "rose"
3) "age"
4) "18"   

hget 用于获取 hash 表一个指定属性的值。

语法:hget key field

127.0.0.1:6379> hget user name
"rose"

hgetall 用于获取 hash 表所有的属性、属性值。

语法:hgetall key

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

hsetnx 用于给哈希表某个不存在的属性设置属性值。如果属性已存在,就返回 0。

语法:hsetnx key field value

127.0.0.1:6379> hsetnx user name rose
(integer) 0

hmset 用于设置哈希表的一个或多个属性、属性值。

语法:hmset key field value [field value ...]

127.0.0.1:6379> hmset user gender female height 170
OK
127.0.0.1:6379> hgetall user
1) "name"
2) "rose"
3) "age"
4) "18"
5) "gender"
6) "female"
7) "height"
8) "170"

hkeys 用于获取哈希表的所有属性名称。

语法:hkeys key

127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "gender"
4) "height"

hdel 用于删除哈希表一个或多个属性。

语法:hdel key field [field ...]

127.0.0.1:6379> hdel user gender height
(integer) 2
127.0.0.1:6379> hkeys user
1) "name"
2) "age"

hexists 用于判断哈希表中是否存在某个属性。

语法:hexists key field

127.0.0.1:6379> hexists user name
(integer) 1
127.0.0.1:6379> hexists user gender
(integer) 0
127.0.0.1:6379>

hlen 用于获取哈希表中属性的数量。

语法:hlen key

127.0.0.1:6379> hlen user
(integer) 2

hvals 用于获取哈希表的所有属性值。

语法:hvals key

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

hincrby 用于给哈希表的指定属性的属性值,加上增量(整数,可以为负数)。

语法:hincrby key field increment

127.0.0.1:6379> hincrby user age 10
(integer) 28

hincrbyfloat 用于给哈希表的指定属性的属性值,加上浮点数增量。

语法:hincrbyfloat key field increment

127.0.0.1:6379> hincrbyfloat user age 3.5
"31.5"
127.0.0.1:6379> hincrbyfloat user age -13.5
"18"

hscan 用于迭代遍历哈希表的属性和属性值。

语法:hscan key cursor [MATCH pattern] [COUNT count]

  • cursor 游标,每次迭代需根据返回的 cursor 值,调整 cursor,当整个遍历结束时,返回 0。
  • pattern 按指定的模式匹配属性名称。
  • count 获取的属性-属性值对的数量。
127.0.0.1:6379> hscan user 0 MATCH *
1) "0"
2) 1) "name"
   2) "rose"
   3) "age"
   4) "18"

当哈希表的属性非常多时,hgetall 会导致服务器短暂卡死,这时就该使用 hscan。

list

list 是一个链表结构,支持从两端插入和弹出。它既可以作为栈(后进先出),也可以作为队列(先进先出)

列表中的元素是有序的,最多支持 2^32 - 1 个元素。

应用场景

  • 电商秒杀活动。
  • 抢红包活动。
  • 简单的消息队列。(可支持阻塞消费,但不支持 ack 机制)
  • 并发量较大的页面数据(首页)分页功能

常用命令

lpush 用于从列表的头部插入一个或多个元素。返回列表的长度。

语法:lpush key value [value ...]

127.0.0.1:6379> lpush que a
(integer) 1
127.0.0.1:6379> lpush que b c d
(integer) 4
127.0.0.1:6379> lrange que 0 -1
1) "d"
2) "c"
3) "b"
4) "a"

lpushx 用于从已存在的列表头部插入一个元素。列表不存在时,就返回 0。

语法:lpushx key value

127.0.0.1:6379> lpushx que e
(integer) 5
127.0.0.1:6379> lpushx noque test
(integer) 0

rpop 用于从列表的尾部弹出一个元素(会被删除),返回被弹出的元素。

语法:rpop key

127.0.0.1:6379> rpop que
"a"

brpop 用于从一个或多个列表的尾部弹出一个元素,如果列表中没有元素就会阻塞等待,直到列表中能有一个元素弹出或等待超时为止。

语法:brpop key [key ...] timeout

127.0.0.1:6379> brpop que 10
1) "que"
2) "b"
127.0.0.1:6379> brpop que 10
1) "que"
2) "c"
127.0.0.1:6379> brpop que 10
1) "que"
2) "d"
127.0.0.1:6379> brpop que 10
1) "que"
2) "e"
127.0.0.1:6379> brpop que 10
(nil)
(10.07s)

lpop 用于从列表的头部弹出一个元素。

语法:lpop key

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

blpop 用于从一个或多个列表的头部弹出一个元素,如果列表中没有元素就会阻塞等待,直到列表中能有一个元素弹出或等待超时为止。

语法:blpop key [key ...] timeout

127.0.0.1:6379> blpop stack 10
1) "stack"
2) "b"

rpoplpush 用于从源列表的尾部弹出一个元素,并将该元素插入到目的列表的头部。

语法:rpoplpush source destination

127.0.0.1:6379> lpush que1 a b c
(integer) 3
127.0.0.1:6379> rpoplpush que1 que2
"a"
127.0.0.1:6379> lrange que1 0 -1
1) "c"
2) "b"
127.0.0.1:6379> lrange que2 0 -1
1) "a"

brpoplpush 用于从源列表的尾部弹出一个元素,并将该元素插入到目的列表的头部。如果源列表中没有元素就会阻塞等待,直到能有一个元素弹出或等待超时为止。

语法:brpoplpush source destination timeout

127.0.0.1:6379> brpoplpush que1 que2 10
"b"
127.0.0.1:6379> brpoplpush que1 que2 10
"c"
127.0.0.1:6379> brpoplpush que1 que2 10
(nil)
(10.09s)
127.0.0.1:6379> lrange que2 0 -1
1) "c"
2) "b"
3) "a"

lindex 用于获取列表中指定索引处的一个元素。

注意:索引是从 0 开始的,0 代表列表的头部,-1 代表列表的尾部。

语法:lindex key index

127.0.0.1:6379> lindex que2 0
"c"
127.0.0.1:6379> lindex que2 1
"b"
127.0.0.1:6379> lindex que2 2
"a"
127.0.0.1:6379> lindex que2 3
(nil)
127.0.0.1:6379> lindex que2 -1
"a"

linsert 用于在列表的指定元素之前或之后插入一个元素。

语法:linsert key before|after pivot value

127.0.0.1:6379> linsert que2 before b x
(integer) 4
127.0.0.1:6379> lrange que2 0 -1
1) "c"
2) "x"
3) "b"
4) "a"

llen 用于获取列表的长度。即列表中元素的个数。

语法:llen key

127.0.0.1:6379> llen que2
(integer) 4

lrange 用于获取列表中指定索引区间的元素。

语法:lrange key start end

127.0.0.1:6379> lrange que2 0 -1
1) "c"
2) "x"
3) "b"
4) "a"

lrem 用于从列表中删除与指定参数相同的元素。返回删除的数量。

语法:lrem key count value

  • 当 count > 0 时,从表头开始向表尾搜索匹配,删除的数量上限为 count。
  • 当 count < 0 时,从表尾开始向表头搜索匹配,删除的数量上限为 count 的绝对值。
  • 当 count = 0 时,删除所有匹配的元素。
127.0.0.1:6379> lrem que2 3 x
(integer) 1
127.0.0.1:6379> lrange que2 0 -1
1) "c"
2) "b"
3) "a"

lset 通过索引修改列表中的一个元素。

语法:lset key index value

127.0.0.1:6379> lset que2 0 z
OK
127.0.0.1:6379> lset que2 9 y
(error) ERR index out of range
127.0.0.1:6379> lrange que2 0 -1
1) "z"
2) "b"
3) "a"

ltrim 用于截取保留列表中指定索引区间的元素。

语法:ltrim key start end

127.0.0.1:6379> ltrim que2 0 1
OK
127.0.0.1:6379> lrange que2 0 -1
1) "z"
2) "b"

rpush 用于从列表的尾部插入一个或多个元素。返回列表的长度。

语法:rpush key value [value ...]

127.0.0.1:6379> rpush que2 j k
(integer) 4
127.0.0.1:6379> lrange que2 0 -1
1) "z"
2) "b"
3) "j"
4) "k"

rpushx 用于从已存在的列表尾部插入一个元素。列表不存在时,就返回 0。

语法:rpushx key value

127.0.0.1:6379> rpushx que2 m
(integer) 5
127.0.0.1:6379> lrange que2 0 -1
1) "z"
2) "b"
3) "j"
4) "k"
5) "m"

set

set 是集合,它是包含字符串元素(成员)的无序集合

集合中的元素是唯一的,即没有重复数据。

集合最多可容纳 2^32 - 1 个元素。

对集合可以取并集、交集、差集。

应用场景

  • 好友推荐、共同好友、tag标签。
  • 天猫商品的多维度筛选(求交集)。
  • 点赞、投票、喜欢等功能(每个用户只能操作一次)。
  • 抽签、抽奖功能。

常用命令

sadd 用于向集合中添加一个或多个元素(会自动去重)。返回添加成功的个数。

语法:sadd key member [member ...]

127.0.0.1:6379> sadd st a
(integer) 1
127.0.0.1:6379> sadd st b c b b
(integer) 2

smembers 用于查看集合中的所有元素。

语法:smembers key

127.0.0.1:6379> smembers st
1) "c"
2) "b"
3) "a"

scard 用于获取集合中元素的数量。

127.0.0.1:6379> scard st
(integer) 3

sdiff 用于返回多个集合的差集,返回仅在第一个集合中才有的元素。

语法:sdiff key [key ...]

127.0.0.1:6379> sadd st2 a f
(integer) 2
127.0.0.1:6379> sdiff st st2
1) "c"
2) "b"

sdiffstore 用于将多个集合的差集存储到目的集合。若目的集合已存在,会被覆盖。

语法:sdiffstore destination key [key ...]

127.0.0.1:6379> sdiffstore st3 st st2
(integer) 2
127.0.0.1:6379> smembers st3
1) "c"
2) "b"

sinter 用于返回多个集合的交集。

语法:sinter key [key ...]

127.0.0.1:6379> sinter st st2
1) "a"

sinterstore 用于将多个集合的交集存储到目的集合。若目的集合已存在,会被覆盖。

语法:sinterstore destination key [key ...]

127.0.0.1:6379> sinterstore st3 st st2
(integer) 1
127.0.0.1:6379> smembers st3
1) "a"

sunion 用于返回多个集合的并集。

语法:sunion key [key ...]

127.0.0.1:6379> sunion st st2
1) "c"
2) "a"
3) "b"
4) "f"

sunionstore 用于将多个集合的并集存储到目的集合。若目的集合已存在,会被覆盖。

语法:sunionstore destination key [key ...]

127.0.0.1:6379> sunionstore st3 st st2
(integer) 4

sismember 用于判断指定的一个元素是否在集合中。如果是,返回 1;否则,返回 0。

语法:sismember key member

127.0.0.1:6379> sismember st a
(integer) 1
127.0.0.1:6379> sismember st x
(integer) 0
# 随机弹出集合中的一个元素(会被删除)。弹出成功,输出被弹出的元素。
spop 集合名         

smove 用于将指定的一个元素从源集合移动到目的集合。

语法:smove source destination member

127.0.0.1:6379> smembers st
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> smove st st2 a
(integer) 1
127.0.0.1:6379> smembers st
1) "c"
2) "b"
127.0.0.1:6379> smembers st2
1) "a"
2) "f"

spop 用于从集合中随机弹出一个或多个元素。返回被弹出的元素(弹出的元素会被删除)。类似于不重复抽奖。

语法:spop key [count]

127.0.0.1:6379> spop st
"c"
127.0.0.1:6379> spop st
"b"
127.0.0.1:6379> spop st
(nil)

srandmember 用于从集合中随机获取一个或多个元素。集合不受影响。类似于可重复抽奖。

语法:srandmember key [count]

127.0.0.1:6379> sadd st a b c
(integer) 3
127.0.0.1:6379> srandmember st
"c"
127.0.0.1:6379> srandmember st
"a"
127.0.0.1:6379> srandmember st
"a"
127.0.0.1:6379> srandmember st 2
1) "a"
2) "b"

srem 用于从集合中删除指定的一个或多个元素。

语法:srem key member [member ...]

127.0.0.1:6379> srem st a
(integer) 1
127.0.0.1:6379> srem st b c
(integer) 2
127.0.0.1:6379> smembers st
(empty list or set)

sscan 用于迭代遍历集合中的元素。

语法:sscan key cursor [MATCH pattern] [COUNT count]

127.0.0.1:6379> sscan st 0 match *
1) "0"
2) 1) "c"
   2) "b"
   3) "a"
127.0.0.1:6379> sscan st 0 match * count 1
1) "2"
2) 1) "c"

zset

zset 是 set 类型的升级,它在 set 的基础上增加了一个分数属性 score(double 类型),故称为有序集合(sorted set)。

在 zset 中,元素(member 成员)默认是按 score 升序排列的。可以把它看做是只有两个字段的 MySQL 数据表,一个字段表示 score,另一个字段表示 member。

有序集合中的元素也是唯一的,但元素的 score 可以重复

zset 类型在 web 应用中非常有用。最多可存储 2^32 - 1 个元素。

应用场景

  • 百度热搜、微博的热门话题。
  • 主播的日榜、周榜、魅力值排行榜。
  • 商品评价中的 tag 和评价次数。
  • 针对垃圾评论的反 spam 规则(10秒钟之内不能多次评论)。
  • 滑动窗口限流(时间戳作为 score)

常用命令

zadd 用于向有序集合中添加一个或多个元素及其 score。返回新增的元素个数。

语法:zadd key [NX|XX] [CH] [INCR] score member [score member ...]

  • NX 表示只有当元素不存在时,才进行操作。
  • XX 表示只有当元素已存在时,才进行操作,不会添加新的元素。
  • CH 表示返回新增或修改的元素个数。
  • INCR 表示给指定的一个元素增加分数增量,用来修改分数,如果元素不存在,就新增。返回这个元素的 score。
127.0.0.1:6379> zadd zr 100 a 101 c 100 v
(integer) 3
127.0.0.1:6379> zrange zr 0 -1
1) "a"
2) "v"
3) "c"
127.0.0.1:6379> zadd zr incr 100 a 102 b
(error) ERR INCR option supports a single increment-element pair
127.0.0.1:6379> zadd zr incr 100 a
"200"
127.0.0.1:6379> zadd zr incr 100 b
"100"
127.0.0.1:6379> zrange zr 0 -1 withscores
1) "b"
2) "100"
3) "v"
4) "100"
5) "c"
6) "101"
7) "a"
8) "200"

zcard 用于获取有序集合中元素的数量。

127.0.0.1:6379> zcard zr
(integer) 4

zcount 用于获取有序集合中指定 score 区间的元素数量。

语法:zcount key min max

127.0.0.1:6379> zcount zr 100 101
(integer) 3

zincrby 用于给有序集合中的一个元素加上 score 增量。返回新的分数。

语法:zincrby key increment member

127.0.0.1:6379> zincrby zr -50 a
"150"

zinterstore 用于将一个或多个有序集合的交集,存于目的集合。求交集的有序集合的数量必须和 numkeys 一致。

语法:zinterstore destination numkeys key [key ...] [WEIGHTS weight [weight ...] [AGGREGATE SUM|MIN|MAX]

  • WEIGHTS 权重,参与计算的集合各自对应一个权重。先将元素的 score 乘以权重,再进行计算。
  • AGGREGATE 指定交集元素的 score 的聚合方式。默认是 SUM 求和。
127.0.0.1:6379> zadd zr2 10 c
(integer) 1
127.0.0.1:6379> zinterstore zr3 2 zr zr2 weights 3 7
(integer) 1
127.0.0.1:6379> zrange zr3 0 -1 withscores
1) "c"
2) "373"

zlexcount 用于获取有序集合中指定字典区间的元素数量。

语法:zlexcount key min max

  • 减号和加号代表特殊含义。- 表示负无穷大,+ 表示正无穷大。
  • ( 表示开区间,[ 表示闭区间。
127.0.0.1:6379> zlexcount zr - +
(integer) 4
127.0.0.1:6379> zlexcount zr [a [y
(integer) 4

zrange 用于获取有序集合中指定索引区间内的元素。

语法:zrange key start end [withscores]

  • 索引 0 代表有序集合的头部,-1 代表有序集合的尾部,-2 代表倒数第二的索引位置。依次类推。
  • withsocres 表示将 score 和元素一起返回。
127.0.0.1:6379> zrange zr 0 -1 withscores
1) "b"
2) "100"
3) "v"
4) "100"
5) "c"
6) "101"
7) "a"
8) "150"

zrangebyscore 用于获取有序集合中指定分数区间内的元素。

语法:zrangebyscore key min max [WITHSCORES] [LIMIT offset count]

127.0.0.1:6379> zrangebyscore zr -inf +inf
1) "b"
2) "v"
3) "c"
4) "a"
127.0.0.1:6379> zrangebyscore zr 0 100 withscores
1) "b"
2) "100"
3) "v"
4) "100"
127.0.0.1:6379> zrangebyscore zr 0 100 withscores limit 0 1
1) "b"
2) "100"

zrangebylex 用于获取有序集合中指定字典区间内的元素。

语法:zrangebylex key min max [LIMIT offset count]

127.0.0.1:6379> zrangebylex zr - +
1) "b"
2) "v"
3) "c"
4) "a"

zrank 用于获取有序集合中指定元素的索引。

语法:zrank key member

127.0.0.1:6379> zrank zr b
(integer) 0
127.0.0.1:6379> zrank zr v
(integer) 1

zrem 用于删除有序集合中指定的一个或多个元素。返回删除的数量。

语法:zrem key member [member ...]

127.0.0.1:6379> zrem zr v a
(integer) 2

zremrangebylex 用于删除有序集合中指定字典区间内的元素。

语法:zremrangebylex key min max

127.0.0.1:6379> zrange zr 0 -1 withscores
1) "b"
2) "100"
3) "c"
4) "101"
127.0.0.1:6379> zremrangebylex zr [b [c
(integer) 2
127.0.0.1:6379> zcard zr
(integer) 0

zremrangebyrank 用于删除有序集合中指定索引区间内的元素。

语法:zremrangebyrank key start end

127.0.0.1:6379> zremrangebyrank zr 0 -1
(integer) 0

zremrangebyscore 用于删除有序集合中指定分数区间内的元素。

语法:zremrangebyscore key min max

127.0.0.1:6379> zremrangebyscore zr -inf +inf
(integer) 0

zrevrange 用于获取有序集合中指定索引区间内的元素,先按分数降序排序。

语法:zrevrange key start stop [WITHSCORES]

127.0.0.1:6379> zadd zr 3 a 4 b 5 c
(integer) 3
127.0.0.1:6379> zrevrange zr 0 -1 withscores
1) "c"
2) "5"
3) "b"
4) "4"
5) "a"
6) "3"

zrevrangebyscore 用于获取有序集合中指定分数区间内的元素,先按分数降序排序(分数相同则按字典降序排)。

语法:zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]

127.0.0.1:6379> zrevrangebyscore zr 5 4 withscores
1) "c"
2) "5"
3) "b"
4) "4"

zrevrank 用于获取有序集合中指定元素的索引,先按分数降序排序。

语法:zrevrank key member

127.0.0.1:6379> zrevrank zr c
(integer) 0

zscore 用于获取有序集合中指定元素的分数。

语法:zscore key member

127.0.0.1:6379> zscore zr c
"5"

zunionstore 用于将一个或多个有序集合的并集,存于目的集合。求并集的有序集合的数量必须和 numkeys 一致。若目的集合已存在,就覆盖。

语法:zunionstore destination numkeys key [key ...] [WEIGHTS weight [weight ...] [AGGREGATE SUM|MIN|MAX]

127.0.0.1:6379> zrange zr2 0 -1 withscores
1) "c"
2) "10"
127.0.0.1:6379> zrange zr3 0 -1 withscores
1) "c"
2) "373"
127.0.0.1:6379> zunionstore zr3 2 zr zr2
(integer) 3
127.0.0.1:6379> zrange zr3 0 -1 withscores
1) "a"
2) "3"
3) "b"
4) "4"
5) "c"
6) "15"

zscan 用于迭代遍历有序集合中的元素及其分数。

语法:zscan key cursor [MATCH pattern] [COUNT count]

127.0.0.1:6379> zscan zr3 0 match *
1) "0"
2) 1) "a"
   2) "3"
   3) "b"
   4) "4"
   5) "c"
   6) "15"

bitmap

bitmap 位图,也称位数组,是由多个二进制位组成的数组。每个二进制位的默认值为 0。数组的索引是从 0 开始的。

bitmap 支持的最大位数是 2^32 位,它可以极大的节约存储空间。1 byte = 8 bit。

bitmap 的底层数据结构用的是 String 类型的 SDS 数据结构来保存位数组,Redis 把数组的 8 个 bit 位利用起来,每个 bit 位表示一个元素的二值状态(0 或 1)。

bitmap 本质上是一个二进制位数组,每个位置的值只能是 0 或 1,起始位置的索引(偏移量)是 0,每个位置的初始值为 0。常用于二值统计。

应用场景

  • 用户签到。
  • 记录用户当前的在线状态。
  • 统计活跃用户。

常用命令

setbit 设置位数组指定位置(索引)的值。返回原来的值。

语法:setbit key offset value

offset 指的是偏移量,也就是位数组的索引(起始位置为 0)。

# 设置位数组 mb 的 mb[0] 和 mb[2] 的值为 1
127.0.0.1:6379> setbit mb 0 1
(integer) 0
127.0.0.1:6379> setbit mb 2 1
(integer) 0

getbit 获取位数组指定位置的值。

语法:getbit key offset

# 获取位数组 mb 的 mb[2] 和 mb[3] 的值
127.0.0.1:6379> getbit mb 2
(integer) 1
127.0.0.1:6379> getbit mb 3
(integer) 0

bitcount 统计位数组中值为 1 的二进制位的数量。

语法:bitcount key [start] [end]

127.0.0.1:6379> bitcount mb
(integer) 2

bitop 对一个或多个位数组执行位运算,并将位运算的结果保存到第一个位数组。

语法:bitop bit_operator dest_key key1 key2

bitop 命令支持 and、or、not、xor 四种位运算。

  • and:按位与(&),两个都为 1,结果才为 1,否则为 0。
  • or:按位或(|),任何一个为 1,结果就为 1。
  • not:按位取反,0 变 1,1 变 0。
  • xor:按位异或,值不同为 1,否则为 0。
127.0.0.1:6379> setbit mb 0 1
(integer) 0
127.0.0.1:6379> setbit mb 1 1
(integer) 0
127.0.0.1:6379> setbit mb2 0 1
(integer) 0
127.0.0.1:6379> setbit mb2 2 1
(integer) 0
# 对 mb 和 mb2 按位与运算,并将结果保存到 new_mb
127.0.0.1:6379> bitop and new_mb mb mb2

bitpos 查找位数组中指定范围内出现的第一个 0 或 1,返回第一个值为 bit_value 的索引。

语法:bitops key bit_value [start] [end]

127.0.0.1:6379> bitpos mb 1
(integer) 0
127.0.0.1:6379> bitpos mb 0
(integer) 2

hyperloglog

Redis 中 hyperloglog 是用来进行基数统计的算法。

其优点是在输入元素的数量(或者体积)非常大时,计算基数所需的空间总是固定且很小。

每个 hyperloglog 只需要 12 KB 内存,就可以计算 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

基数就是集合中不重复元素的个数。比如,数据集合{1,3,5,7,5,3},这个数据集的基数集就是{1,3,5,7},基数是 4。

hyperloglog 只会根据输入元素来计算基数,而不会储存元素本身,所以 hyperloglog 不能像集合那样,返回输入的各个元素。

占用空间极小,支持输入海量的元素,特别适合海量数据的基数统计。

核心是基数估算算法,最终估算的基数数值存在一定误差。

误差说明:基数估计的结果是一个带有 0.81% 标准错误(standard error)的近似值,在可接受的范围。

应用场景

  • 统计每日访问 IP 数
  • 统计页面实时 UV 数
  • 统计在线用户数
  • 统计日活、月活

常用命令

pfadd 命令用于将一个或多个元素添加到 hyperloglog 数据结构中。

语法:pfadd key element [element ...]

127.0.0.1:6379> pfadd myh a b c a
(integer) 1

pfcount 命令用于返回指定 hyperloglog 的基数估值,如果是多个 hyperloglog,则返回基数估值之和。

语法:pfcount key [key ...]

127.0.0.1:6379> pfcount myh
(integer) 3

pfmerge 命令用于将多个 hyperloglog 合并为一个 hyperloglog

语法:pfmerge dest_key source_key [source_key ...]

127.0.0.1:6379> padd myh1 a b b
(error) ERR unknown command 'padd'
127.0.0.1:6379> pfadd myh1 a b b
(integer) 1
127.0.0.1:6379> pfadd myh2 c d e d d f
(integer) 1
127.0.0.1:6379> pfmerge myh3 myh1 myh2
OK
127.0.0.1:6379> pfcount myh3
(integer) 6

geo

在 Redis 3.2 及以上版本中,geo 可用于存储地理位置信息。geo 并不是一种新的数据结构,它是基于 zset 实现的。

应用场景

  • 搜索匹配附近的人

常用命令

geoadd 命令用于存储指定的地理空间位置,可将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的键中。

语法:geoadd key longitude latitude member [longitude latitude member ...]

geoadd myg 116.41667 39.91667 beijing
geoadd myg 121.43333 34.50000 shanghai

geodist 命令用于返回两个指定元素之间的距离。

语法:geodist key member1 member2 [m|km|ft|mi]

距离度量单位支持如下参数:

  • m: 米(默认值)
  • km: 千米
  • ft: 英尺
  • mi:英里
geodist myg beijing shanghai

geopos 命令用于返回指定元素(member)对应的位置信息(经度和纬度)。

语法:geopos key member [member ...]

geopos myg beijing

geohash 命令用于返回 geohash 编码转换后的 11 位字符串表示形式,兼容 geohash.org 规范。

语法:geohash key member [member ...]

geohash myg beijing

georadius 命令用于查询距离指定位置某个距离内的元素。

语法:georadius key longitude latitude radius m|km|ft|mi

bloomfilter

详情可查看这里

stream

详情可查看这里

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值