文章目录
一、概述
1.1 简介
- Redis是一个开源的、基于内存的、支持持久化的、以 key-value形式存储的 NoSQL数据库。
- 支持包含 String(字符串)、List(链表)、Set(集合)、ZSet(有序集合)、Hash(哈希)等众多数据类型。
- 支持 set/ get、push/ pop、add/ remove、交集/ 并集/ 差集等丰富的操作,而且这些操作都是原子性的。
1.2 应用场景
- 最新 N个数据:通过 List实现按自然时间排序的数据
- 排行榜(TopN):利用 ZSet有序集合
- 时效性数据,比如手机验证码:利用键的 Expire过期属性
- 计数器,秒杀:利用原子性自增/ 自减方法 INCR、DECR
- 去重:利用 Set集合
- 构建队列:利用 List集合
- 发布订阅消息:利用 pub/ sub模式
1.3 键的操作
命令 | 说明 |
---|---|
keys * | 查看当前库所有的 key,还可以通过 key user* 进行模糊匹配 |
exists key | 判断某个 key是否存在 |
type key | 查看 key的类型 |
del key | 删除指定的key |
unlink key | 删除指定的key(非阻塞,仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。) |
expire key 10 | 为给定的 key设置过期时间(秒) |
ttl key | 查看剩余过期时间,-1表示永不过期,-2表示已过期 |
select [0-15] | 切换数据库 |
dbsize | 返回当前数据库的 key的数量 |
flushdb | 清空当前库 |
flushall | 清空所有库 |
二、基本数据类型
2.1 字符串
- 简介
- Redis最基本的类型,一个 key对应一个 value。
- String类型是二进制安全的,这意味着它可以包含任何数据,比如图片或者序列化的对象。
- String类型的 value最大可以达到 512M。
2.1.1 常用命令
命令 | 说明 |
---|---|
set key value | 设置对应键值 |
get key | 查询对应键值 |
append key value | 将给定的 value 追加到原值的末尾 |
strlen key | 获得值的长度 |
setnx key value | 只有在 key不存在时,才可以设置 key的值 |
incr key | 将 key中储存的数字值增 1;只能对数字值操作,如果为空,新增值为 1 |
decr key | 将 key中储存的数字值减 1;只能对数字值操作,如果为空,新增值为 -1 |
incrby/decrby key step | 将 key中储存的数字值增减,自定义步长 |
mset key1 value1 key2 value2 … | 同时设置一个或多个 key-value对 |
mget key1 key2 key3 … | 同时获取一个或多个 value |
msetnx key1 value1 key2 value2 … | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在时才可以成功 |
getrange key start-pos end-pos | 范围取值 |
setrange key start-pos value | 从 start-pos 开始,用 value 覆写 key 所储存的字符串值(索引从0开始) |
setex key expire-time value | 设置键值的同时,设置过期时间,单位秒 |
getset key value | 获得旧值的同时设置新值 |
- set
参数 | 说明 |
---|---|
EX | 超时秒数 |
PX | 超时毫秒数,与EX互斥 |
NX | 当数据库中 key不存在时,可以将 key-value添加数据库 |
XX | 当数据库中 key存在时,可以将 key-value添加数据库,与NX参数互斥 |
- getrange
redis:6379> get mykey
"This is a string"
redis:6379> getrange mykey 0 3
"This"
redis:6379>
- setrange
redis:6379> SET key1 "Hello World"
"OK"
redis:6379> SETRANGE key1 6 "Redis"
(integer) 11
redis:6379> GET key1
"Hello Redis"
redis:6379>
- getset
redis:6379> SET mykey "Hello"
"OK"
redis:6379> GETSET mykey "World"
"Hello"
redis:6379> GET mykey
"World"
redis:6379>
2.1.2 数据结构
- String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。
- 是可以修改的字符串,内部结构实现上类似于 Java的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
- 如图中所示,为当前字符串实际分配的空间 capacity一般要高于实际字符串长度 len。
- 当字符串长度小于 1M时,扩容都是加倍现有的空间;如果超过 1M,扩容时一次只会多扩 1M的空间(最大 512M)。
2.2 列表
- 简介
- List 是简单的字符串列表,可以为一个 key设置多个 value,按照插入顺序排序。
- 添加一个元素到列表时,可以从头部(左边)或者尾部(右边)进行添加。
- 它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
2.2.1 常用命令
命令 | 说明 |
---|---|
lpush/rpush key value1 value2 value3 … | 从左边/右边插入一个或多个值 |
lpop/rpop key | 从左边/右边吐出一个值(会删除),最后一个值吐出后键就不存在了 |
lindex key index | 从左到右按照索引下标获得元素(不会删除) |
llen key | 获得列表长度 |
linsert key before value newvalue | 在 value 的前插入 newvalue |
lrem key n value | 从从左到右删除 n个为 value的值,n = 0表示删除所有,n < 0表示从右往左 |
lset key index value | 将下标为 index的值替换成 value |
lrange key start stop | 从左到右获取指定范围内的数据,0 -1 表示获取所有数据 |
rpoplpush key1 key2 | 从 key1列表右边吐出一个值,插到 key2列表左边 |
- LINSERT
redis:6379> RPUSH mylist "Hello"
(integer) 1
redis:6379> RPUSH mylist "World"
(integer) 2
redis:6379> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis:6379> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
redis:6379>
- RPOPLPUSH
redis:6379> RPUSH mylist "one"
(integer) 1
redis:6379> RPUSH mylist "two"
(integer) 2
redis:6379> RPUSH mylist "three"
(integer) 3
redis:6379> RPOPLPUSH mylist myotherlist
"three"
redis:6379> LRANGE mylist 0 -1
1) "one"
2) "two"
redis:6379> LRANGE myotherlist 0 -1
1) "three"
redis:6379>
2.2.2 数据结构
- 列表元素较少的情况下会使用一块连续的内存存储,其结构为 ziplist(压缩列表);当数据量比较多的时候才会改成 quicklist。
- 普通链表需要的附加指针(prev和 next)空间太大,会比较浪费空间。
- Redis将链表和 ziplist结合起来组成了 quicklist:也就是将多个 ziplist使用双向指针串起来使用;这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
2.3 集合
- 简介
- Set 是 String类型的无序集合且不包含重复元素,对外提供判断某个成员是否在集合内的重要接口。
- 它底层其实是一个 value为 null的 hash表,其添加、删除、查找的复杂度都是 O(1)。
2.3.1 常用命令
命令 | 说明 |
---|---|
sadd key value1 value2 … | 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略 |
smembers key | 取出该集合的所有值 |
sismember key value | 判断集合 key 是否为含有该 value 值,有1,没有0 |
scard key | 返回该集合的元素个数 |
srem key value1 value2 … | 删除集合中的某个元素 |
spop key | 随机从该集合中吐出一个值 |
srandmember key n | 随机从该集合中取出n个值,不会从集合中删除 |
smove source destination value | 把集合中一个值从一个集合移动到另一个集合 |
sinter key1 key2 | 返回两个集合的交集元素 |
sunion key1 key2 | 返回两个集合的并集元素 |
sdiff key1 key2 | 返回两个集合的差集元素 |
2.3.2 数据结构
- Set数据结构是 dict字典,字典是用哈希表实现的。
- Java中 HashSet的内部实现使用的是 HashMap,只不过所有的 value都指向同一个对象。
- Redis的 set结构也是一样,它的内部也使用 hash结构,所有的 value都指向同一个内部值。
2.4 哈希
- 简介
- Redis hash 是一个键值对集合,类似 Java里面的 Map<String, Object>。
- Redis hash 是一个 string类型的 field和 value的映射表,hash特别适合用于存储对象。
2.4.1 常用命令
命令 | 说明 |
---|---|
hset key field value | 给 key 集合中的 field 键赋值 value |
hget key field | 从 key 集合 field 取出 value |
hmset key1 field1 value1 field2 value2 … | 批量设置 hash的值 |
hexists key1 field | 查看哈希表 key 中,给定域 field 是否存在 |
hkeys key | 列出该 hash集合的所有 field |
hvals key | 列出该 hash集合的所有 value |
hincrby key field value | 为哈希表 key 中的域 field 的值加上 value 的增量 |
hsetnx key field value | 当且仅当域 field 不存在时,将哈希表 key 中的域 field 的值设置为 value |
2.4.2 数据结构
- Hash类型对应的数据结构是两种:ziplist(压缩列表)和 hashtable(哈希表)。
- 当 field-value长度较短且个数较少时,使用 ziplist,否则使用 hashtable。
2.5 有序结合
- 简介
- zset 与普通集合 set非常相似,是一个没有重复元素的字符串集合。
- 不同之处是有序集合的每个成员都关联了一个评分(score),被用来按照
从最低分到最高分
的方式排序集合中的成员。 - 集合的成员是唯一的,但是评分可以是重复的,可以很快根据评分(score)或者次序(position)来获取一个范围的元素。
2.5.1 常用命令
命令 | 说明 |
---|---|
zadd key score1 value1 score2 value2 … | 将一个或多个 member 元素及其 score 值加入到有序集 key 当中 |
zrange key start stop [withscores] | 返回有序集 key 中,下标在 start stop 之间的元素(带WITHSCORES,可以让分数一起和值返回到结果集) |
zrevrange key start stop [withscores] | zrange 的倒序版 |
zrangebyscore key minmax [withscores] | 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max)的成员 |
zincrby key increment value | 为 key 中为 value 的元素的分数增加 increment |
zrem key value | 删除该集合下,指定值的元素 |
zcount key min max | 统计该集合,分数区间内的元素个数 |
zrank key value | 返回该值在集合中的排名,从0开始 |
2.5.2 数据结构
- SortedSet(zset) 是 Redis提供的一个非常特别的数据结构,一方面它等价于 Java的数据结构 Map<String, Double>,可以给每一个元素 value赋予一个权重 score,另一方面它又类似于 TreeSet,内部的元素会按照权重 score进行排序,可以得到每个元素的名次,还可以通过 score的范围来获取元素的列表。
- zset 底层使用了两个数据结构:hash,hash的作用就是关联元素 value和权重 score,保障元素 value的唯一性,可以通过元素 value找到相应的 score值;跳跃表,跳跃表的目的在于给元素 value排序,根据 score的范围获取元素列表。
三、扩展数据类型
3.1 Bitmap
- 简介
- Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value), 但单独提供了一套命令可以对字符串的位进行操作。
- 可以把它想象成一个以位为单位的数组, 数组的每个单元只能存储 0和 1,数组的下标在 Bitmaps中叫做偏移量。
- 命令
格式 | 说明 |
---|---|
setbit key offset 0/1 | 设置 bit位的值 |
getbit key offset | 获取 bit位的值(不存在时返回 0) |
bitcount key [start end BYTE/BIT] | 统计字符串被设置为 1的 bit数,BYTE/END 可以指定 start/end 的偏移计算方式 |
bitop and/or/not/xor dest-key src-key1 src-key2 [… src-keyN] | 对多个 bitmap 做逻辑操作结果存放在 dest-key |
bitcount
redis:6379> setbit user:daily 1 1
(integer) 0
redis:6379> setbit user:daily 5 1
(integer) 0
redis:6379> setbit user:daily 9 1
(integer) 0
redis:6379> setbit user:daily 13 1
(integer) 0
redis:6379> bitcount user:daily
(integer) 4
redis:6379> bitcount user:daily 0 1
(integer) 4
redis:6379> bitcount user:daily 0 9 BIT
(integer) 3
redis:6379>
bitop
redis:6379> setbit user:daily:0423 5 1
(integer) 0
redis:6379> setbit user:daily:0424 3 1
(integer) 0
redis:6379> bitop or user:weekly user:daily:0423 user:daily:0424
(integer) 1
redis:6379> bitcount user:weekly
(integer) 2
redis:6379>
3.2 HyperLogLog
- A HyperLogLog is a
probabilistic data structure
used in order to count unique things. - Usually counting unique items requires using an amount of memory proportional to the number of items you want to count.
- Redis uses a constant amount of
memory(< 12k)
and provides an estimated measure with a standarderror(< 1%)
.
- 命令
命令 | 说明 |
---|---|
pfadd key mem1 mem2 [… memN] | 添加元素 |
pfcount key | 统计非重复的元素 |
pfmerge destkey sourcekey sourcekey2 [… sourcekeyN] | 合并键 |
3.3 Geospatial
- 简介
- 该类型用于存储地理位置的坐标信息(经纬度)。
- 对外提供直线距离计算、范围查询等 API。
- 命令
命令 | 说明 |
---|---|
geoadd key longitude latitude member […] | 添加元素的经纬度信息 |
geopos key member […] | 获取元素的经纬度信息 |
geodist key member1 member2 [m|km|ft|mi] | 获取两个元素的直线距离( 米|千米|英里|英尺) |
georadius key longitude latitude radius [m|km|ft|mi] | 获取指定位置范围内所有的元素 |