1.Redis 的常用命令
1.1 基本全局命令
- keys
bash
keys pattern
返回所有满⾜样式(pattern)的key。⽀持如下统配样式。
- h?llo 匹配 hello, hallo 和 hxllo
- h*llo 匹配 hllo 和 heeeello
- h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
- h[^e]llo 匹配 hallo , hbllo ,...但不匹配 hello (排除的意思)
- h[a-b]llo 匹配 hallo 和 hbllo
- exists
- 判断某个key是否存在。
- 返回 key 存在的个数
java
exists key [key ...]
- del
- 删除 key
java
del key [key ...]
- expire
- 设置过期时间(以秒为单位)
java
expire key seconds
- ttl
- 获取指定 key 的过期时间(以秒为单位)
- 返回值:剩余过期时间。-1表⽰没有关联过期时间,-2表⽰key不存在。
java
ttl key
- type
- 返回 key 对应 value 的数据类型。
- 返回:none , string , list , set , zset , hash。
java
type key
- object encoding
- 返回对应 key 的内部编码
java
object encoding key
- flushall
- 一键清空所有的键值对,谨慎使用。
java
flushall
1.2 String数据结构
字符串类型是Redis
最基础的数据类型,字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似JSON
、XML
格式的字符串;数字,可以是整型或者浮点型;甚⾄是⼆进制流数据,例如图⽚、⾳频、视频等。不过⼀个字符串的最⼤值不能超过512MB
。
- set
- 将
string
类型的value
设置到key
中。如果key
之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此key
的TTL
也全部失效。- EX seconds⸺使⽤秒作为单位设置key的过期时间。
- PX milliseconds⸺使⽤毫秒作为单位设置key的过期时间。
- NX ⸺只在key不存在时才进⾏设置,即如果key之前已经存在,设置不执⾏。
- XX ⸺只在key存在时才进⾏设置,即如果key之前不存在,设置不执⾏
java
set key value [expiration EX seconds|PX milliseconds] [NX|XX]
直接设置超时:
- get
- 获取
key
对应的value
。如果key
不存在,返回nil
。如果value
的数据类型不是string
,会报错。
java
get key
- mget
- ⼀次性获取多个
key
的值。如果对应的key
不存在或者对应的数据类型不是string
,返回nil
。
java
mget key [key ......]
- mset
- 一次性设置多个
key
值
java
MSET key value [key value ...]
- setnx
- 设置
key-value
但只允许在key
之前不存在的情况下。
java
setnx key value
- incr
- 将
key
对应的string
表⽰的数字加⼀。如果key
不存在,则视为key
对应的value
是0
。如果key
对应的string
不是⼀个整型或者范围超过了64
位有符号整型,则报错。
java
incr key
- incrby
- 将
key
对应的string
表⽰的数字加上对应的值。如果key
不存在,则视为key
对应的value
是0
。如果key
对应的string
不是⼀个整型或者范围超过了64
位有符号整型,则报错。
java
incrby key decrement
- decr
- 将
key
对应的string
表⽰的数字减⼀。如果key
不存在,则视为key
对应的value
是0
。如果key
对应的string
不是⼀个整型或者范围超过了64
位有符号整型,则报错。
java
decr key
- decrby
- 将
key
对应的string
表⽰的数字减去对应的值。如果key
不存在,则视为key
对应的value
是0
。如果key
对应的string
不是⼀个整型或者范围超过了64
位有符号整型,则报错。
java
decrby key decrement
- incrbyfloat
- 将
key
对应的string
表⽰的浮点数加上对应的值。如key
不存在,则视为key
对应的value
是0。如果key
对应的不是string
,或者不是⼀个浮点数,则报错。允许采⽤科学计数法表⽰浮点数。
java
incrbyfloat key increment
- append
- 如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。
java
append key value
- getreange
- 返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1代表倒数第⼀个字符,-2代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的⻓度调整成正确的值。
java
getrange key start end
- setreange
- 覆盖字符串的⼀部分,从指定的偏移开始。
java
setreange key offset value
- strlen
- 获取key对应的string的⻓度。
java
strlen key
- 内部编码
字符串类型的内部编码有3种:
- int:8个字节的⻓整型。
- embstr:⼩于等于39个字节的字符串。
- raw:⼤于39个字节的字符串。
Redis会根据当前值的类型和⻓度动态决定使⽤哪种内部编码实现。
1.3 Hash哈希
在 Redis 中,哈希类型是指值本⾝⼜是⼀个键值对结构,形如 key="key",value={{field1,value1},...,{fieldN,valueN}},Redis 键值对和哈希类型⼆者的关系可以⽤下图来表⽰:
哈希类型中的映射关系通常称为field-value,⽤于区分Redis整体的键值对(key-value)。
- hset
- 设置hash中指定的字段(field)的值(value)。
java
hset key field value [field value ...]
- hget
- 获取 hash 中指定字段的值
java
hget key field
- hexists
- 判断 hash 中是否有指定的字段
java
hexists key field
- hdel
- 删除 hash 中的字段
java
hdel key field [field ...]
- hkeys
- 获取 hash 中所有的字段
java
hkeys key
- hvals
- 获取 hash 中的所有的值
java
hvals key
- hgetall
- 获取 hash 所有字段以及对应的值
java
hgetall key
- hmget
- 一次获取 hash 中多个字段的值
java
hmget key field [field ...]
- hlen
- 获取 hash 中的所有字段的个数
java
hlen key
- hsetnx
- 在字段不存在的情况下,设置 hash 中的字段和值。
java
HSETNX key field value
- hincrby
- 将 hash 中字段对应的数值添加指定的值。
java
hincrby key field increment
- hincrbyfloat
- 将 hash 中字段对应的数值添加指定的浮点数值。
java
hincrbyfloat key field increment
- 内部编码
两种:
-
ziplist
(压缩列表):当哈希类型元素个数⼩于hash-max-ziplist-entries
配置(默认512个)、同时所有值都⼩于hash-max-ziplist-value
配置(默认64字节)时,Redis
会使⽤ziplist
作为哈希的内部实现,ziplist
使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐hashtable
更加优秀。 -
hashtable
(哈希表):当哈希类型⽆法满⾜ziplist
的条件时,Redis
会使⽤hashtable
作为哈希的内部实现,因为此时ziplist
的读写效率会下降,⽽hashtable
的读写时间复杂度为O(1)。
1.4 List列表
列表类型是⽤来存储多个的字符串,⼀个列表最多可以存储 <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 32 − 1 2^{32} - 1 </math>232−1 个元素。
- lpush
- 将一个或者多个元素从左侧放入 list 中
java
lpush key element [element ...]
- lpushx
- 在key存在时,将⼀个或者多个元素从左侧放⼊(头插)到list中。
java
lpushx key element [element ...]
- rpush
- 将⼀个或者多个元素从右侧放⼊(尾插)到list中。
java
RPUSH key element [element ...]
- rpushx
- 在 key 存在时,将⼀个或者多个元素从右侧放⼊(尾插)到 list 中。
java
rpushx key element [element ...]
- lrange
- 获取从 start 到 end 区间的所有元素,左闭右闭。
java
lrange key start stop
- lpop
- 从 list 左侧取出元素(即头删)
java
lpop key
- rpop
- 从list左侧取出元素(即头删)。
java
rpop key
- lindex
- 获取从左数第 index 位置的元素。
java
lindex key index
- linsert
- 在特定位置插⼊元素。
java
LINSERT key <BEFORE | AFTER> pivot element
<BEFORE | AFTER>
: 指定插入位置,可选的参数,表示在 pivot 元素之前还是之后插入新元素。
- llen
- 获取 list 长度
java
list key
- blpop
- LPOP的阻塞版本。
java
BLPOP key [key ...] timeout
- 如果列表中没有元素,阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态。
- brpop
- RPOP的阻塞版本。
java
BRPOP key [key ...] timeout
- 内部编码
-
ziplist
(压缩列表):当列表的元素个数⼩于list-max-ziplist-entries
配置(默认512个),同时列表中每个元素的⻓度都⼩于list-max-ziplist-value
配置(默认64字节)时,Redis
会选⽤ziplist
来作为列表的内部编码实现来减少内存消耗。 -
linkedlist
(链表):当列表类型⽆法满⾜ziplist
的条件时,Redis
会使⽤linkedlist
作为列表的内部实现。
1.5 Set集合
1.5.1 增删查改命令
集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中元素之间是⽆序、不允许重复的。Redis 除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集。
- sadd
- 将⼀个或者多个元素添加到 set 中。
java
SADD key member [member ...]
- smembers
- 获取⼀个 set 中的所有元素,元素间的顺序是⽆序的。
java
SMEMBERS key
- sismember
- 判断⼀个元素在不在set中。
java
SISMEMBER key member
- scard
- 获取set中的元素个数。
java
scard key
- spop
- 从set中删除并返回⼀个或者多个元素。由于set内的元素是⽆序的,所以取出哪个元素实际是未定义⾏为,即可以看作随机的。
java
spop key [count]
- smove
- 将⼀个元素从源set取出并放⼊⽬标set中。
java
SMOVE source destination member
- srem
- 将指定的元素从 set 中删除。
java
SREM key member [member ...]
1.5.2 Set集合间的操作
- sinter
- 获取给定set的交集中的元素。
java
SINTER key [key ...]
- sinterstore
- 获取给定 set 的交集中的元素并保存到⽬标set中。
java
SINTERSTORE destination key [key ...]
- sunion
- 获取给定 set 的并集中的元素。
java
SUNION key [key ...]
- sunionstore
- 获取给定set的并集中的元素并保存到⽬标set中。
java
SUNIONSTORE destination key [key ...]
- sdiff
- 获取给定set的差集中的元素。
- 差集是指从一个集合中去除另一个集合中的所有元素后所得到的集合。假设有集合 A 和集合 B,A 减去 B 的差集表示为 A - B,意思是包含在集合 A 中但不在集合 B 中的所有元素的集合。
java
SDIFF key [key ...]
- sdiffstore
- 获取给定set的差集中的元素并保存到⽬标set中。
java
SDIFFSTORE destination key [key ...]
- intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于 set-max-intset-entries 配置(默认512个)时,Redis 会选⽤ intset 来作为集合的内部实现,从⽽减少内存的使⽤。
- hashtable(哈希表):当集合类型⽆法满⾜ intset 的条件时,Redis 会使⽤ hashtable 作为集合的内部实现。
1.6 Zset有序集合
它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数。
1.6.1 增删查改
- zadd
- 添加或者更新指定的元素以及关联的分数到zset中,分数应该符合double类型,+inf/-inf为正负极限。
- XX:仅⽤于更新已经存在的元素,不会添加新元素。
- NX:仅⽤于添加新元素,不会更新已经存在的元素。
- GT | LT: 可选参数,用于筛选添加操作,只有分值大于或小于给定分值的成员才会被添加。
GT
表示只添加分值大于给定分值的成员,LT
表示只添加分值小于给定分值的成员。 - INCR:此时命令类似 ZINCRBY 的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。
java
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
对zhangsan
增加 60
- zcard
- 获取 zset 中的元素个数
java
zcard key
- zcount
- 返回分数在min和max之间的元素个数,默认情况下,min和max都是包含的。
java
zcount key min max
- zrange
- 返回指定区间⾥的元素,分数按照升序。加上 WITHSCORES 可以把分数返回。
java
ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
-
[BYSCORE|BYLEX]:这部分指定范围是由分数(与每个成员关联的数值)还是按字典顺序(成员按字母顺序排序时的顺序)确定的。
-
[REV]:这是一个可选参数。如果指定,则表示结果应以相反的顺序返回(从最高到最低)。
-
[LIMIT offset count]:也是可选的参数,允许你限制返回的结果数量。offset 指定在开始返回元素之前要跳过多少个元素,count 指定要返回的最大元素数。
-
[WITHSCORES]:另一个可选参数。如果指定,Redis 将返回元素及其关联的分数。否则,只返回元素。
注意,这里如果添加了 byscore
,那么就是根据分数匹配。
- zrevrange
- 返回指定区间⾥的元素,分数按照降序。带上 WITHSCORES 可以把分数也返回。
java
ZREVRANGE key start stop [WITHSCORES]
- zrangebyscore
- 返回分数在min和max之间的元素,默认情况下,min和max都是包含的。
java
ZRANGEBYSCORE key min max [WITHSCORES]
- zpopmax
- 删除并返回分数最⾼的count个元素,如果不写,默认为 1。
java
ZPOPMAX key [count]
- bzpopmax
- ZPOPMAX的阻塞版本。
java
BZPOPMAX key [key ...] timeout
- zpopmin
- 删除并返回分数最低的count个元素。
java
ZPOPMIN key [count]
- bzpopmin
- ZPOPMIN的阻塞版本。
java
BZPOPMIN key [key ...] timeout
- zrank
- 返回指定元素的排名,升序。
java
zrank key member
- zrevrank
- 返回指定元素的排名,降序。
java
ZREVRANK key member
- zscore
- 返回指定元素的分数。
java
ZSCORE key member
- zrem
- 删除指定的元素
java
ZREM key member [member ...]
- zremrangebyrank
- 按照排序,升序删除指定范围的元素,左闭右闭。
java
ZREMRANGEBYRANK key start stop
- zremrangebyscore
- 按照分数删除指定范围的元素,左闭右闭。
java
ZREMRANGEBYSCORE key min max
- zincrby
- 为指定的元素的关联分数添加指定的分数值。
java
ZINCRBY key increment member
1.6.2 Zset集合间操作
- zinterstore
- 求出给定有序集合中元素的交集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数。
java
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
destination
: 存储交集结果的目标有序集合的键名。numkeys
: 这是指定参与交集计算的有序集合的数量。key
: 这是参与交集计算的有序集合的键名,可以有一个或多个。[WEIGHTS weight]
: 这是一个可选参数,用于指定每个有序集合的权重,权重可以是整数或浮点数,用于对有序集合的分值进行加权计算。[AGGREGATE SUM|MIN|MAX]
: 这是另一个可选参数,用于指定计算交集时采用的聚合方式。可以是 SUM(求和)、MIN(最小值)或 MAX(最大值),默认是 SUM。
这个指令表示计算 zset1 和 zset2 两个有序集合的交集,并将结果存储在名为 zset3 的新有序集合中。在计算交集时,zset1 中的分值将乘以 2,zset2 中的分值将乘以 3,并且使用 SUM 聚合函数对交集的分值进行求和(没有写 AGGREGATE 的情况下,默认是 sum)。
- zunionstore
- 求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数。
java
zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
这里与 zinterstore 唯一不同的就是取了并集。
内部编码:
-
ziplist(压缩列表):当有序集合的元素个数⼩于 zset-max-ziplist-entries 配置(默认128个),同时每个元素的值都⼩于 zset-max-ziplist-value 配置(默认64字节)时,Redis 会⽤ ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。
-
skiplist(跳表):当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时 ziplist 的操作效率会下降。
1.9 操作数据库的指令
- select
- 切换数据库
java
select dbIndex
Redis 默认配置中是有 16 个数据库。select 0 操作会切换到第⼀个数据库,select 15 会切换到最后⼀个数据库。
- flushdb/flushall
- 清除数据库,flushdb 只清除当前数据库,flushall 会清楚所有数 据库。
java
flushdb/flushall
2.Redis 过期删除策略
Redis 中的过期数据不会在过期时立刻被删除,而是通过以下策略:
- 惰性删除:Redis 不会主动地、周期性地检查和删除所有过期的键。惰性删除是指在Redis 访问某个键值时,才会检查该键是否已经过期,如果已过期,则返回 NULL,并同时删除它。
- 定期删除:每隔一段时间检查一次数据库,随机删除一些过期键。定期删除在 redis.conf 配置文件中配置如下:hz 10 表示每秒删除10次。
-
定期删除的过程(每一次):
- 从过期字典中随机取出 20 个键。
- 删除这 20 个键中过期的键。
- 如果过期键的比例超过 25%,重复步骤 1
-
Redis 采用的是惰性与定期相结合的方式。
3.Redis 为什么这么快?
- 纯内存操作:Redis 将所有数据存储在内存中,这意味着对数据的读写操作直接在内容中进行,而内存的访问速度远远高于磁盘。
- 单线程模型:Redis 使用单线程模型来处理客户端请求。避免了多线程频繁的切换和竞争带来的开销。
- I/O 多路复用:Redis 使用了I/O多路复用技术。就是单个线程同时监听多个客户端连接,只有当前网络事件发生时才会进行实际的 I/O 操作,减少等待时间。