目录
- Redis的基本类型
- 字符串
- 哈希
- 列表
- 集合
- 有序集合
- 其他
Redis的基本类型
本文使用的Redis版本为: Redis 3.0.503 (00000000/0) 64 bit / windows 环境 下载链接 l点击这里下载
概述
Redis有五种数据结构:字符串、哈希、列表、集合、有序集合
Redis可以用来干嘛:缓存、排行榜系统(热度排行)、计数器应用(视频播放量)、社交网络(点赞和踩)、消息队列
Redis不可以用来干嘛:Redis不适合数据量较大的储存
Redis为什么这么快:
1 纯内存访问,Redis将所有数据都放在内存中,内存响应时间快
2 非阻塞I/O,Redis使用epoll作为I/O多路复用技术,Redis自身的时间处理模型将epoll中的连接读写关闭都转换为时间,不在网络I/O上浪费过多的时间
3 单线程避免了线程切换和竞态产生的消耗 (如果某个命令执行时间过长会造成其他命令的阻塞)
Redis通用的命令:
命令 | 命令作用 | 返回值 |
keys * | 查看所有的建 | 键 的所有集合/empty |
dbsize | 查看键的数量 | 键的数量/empty |
exists key | 查看键是否存在 | 1/0 |
del key [key...] | 删除键,可以删除多个 | 返回删除键的数量/0 |
expire key seconds | 设置键的过期时间,到期自动删除 | 1/0 |
ttl key | 查看键的剩余过期时间 | 剩余时间/-2(表示已被删除)/-1(表示没有设置过期时间) |
type key | 查看键的数据结构类型 | 五种类型/none |
字符串
字符串是redis最基础的数据结构
字符串的实际值可以是:字符串(简单的字符串,复杂的字符串(xml json)),数字(整数,浮点数),二进制(图片,音频) 但是最大值不能超过512MB
字符串的基本命令
- 常用命令:
- 设置值 set key value [ex +x秒] [px+x毫秒] [nx|xx]
ex 后面+设置过期的秒数 px 后面+过期的毫秒数
nx 键值必须不存在才可以设置成功,用于添加
xx 键值必须存在才可以设置成功,用于更新
127.0.0.1:6379[1]> set a 1 ex 10000 nx
OK
127.0.0.1:6379[1]> ttl a
(integer) 9997
127.0.0.1:6379[1]> set a 2 nx
(nil)
127.0.0.1:6379[1]> set a 2 xx
OK
127.0.0.1:6379[1]> keys *
1) "a"
127.0.0.1:6379[1]> ttl a
(integer) -1
127.0.0.1:6379[1]> set a 1 ex 10000 nx
OK
127.0.0.1:6379[1]> ttl a
(integer) 9997
127.0.0.1:6379[1]> set a 2 nx
(nil)
127.0.0.1:6379[1]> set a 2 xx
OK
127.0.0.1:6379[1]> keys *
1) "a"
127.0.0.1:6379[1]> ttl a
(integer) -1
注意:当使用set更新键的时候 ex 设置的过期时间将无效
- 获取值 get key
127.0.0.1:6379[1]> get a
"2"
127.0.0.1:6379[1]> get b
(nil)// 不存在将返回 nil
127.0.0.1:6379[1]> get a
"2"
127.0.0.1:6379[1]> get b
(nil)// 不存在将返回 nil
- 批量设置值 mset key value [key value...]
- 批量获取值mget key [key...]
127.0.0.1:6379[1]> mset b 2 c 3 d 4
OK
127.0.0.1:6379[1]> keys *
1) "b"
2) "a"
3) "d"
4) "c"
127.0.0.1:6379[1]> mget a b c d e
1) "2"
2) "2"
3) "3"
4) "4"
5) (nil)//不存在返回 nil不常用的命令
127.0.0.1:6379[1]> mset b 2 c 3 d 4
OK
127.0.0.1:6379[1]> keys *
1) "b"
2) "a"
3) "d"
4) "c"
127.0.0.1:6379[1]> mget a b c d e
1) "2"
2) "2"
3) "3"
4) "4"
5) (nil)//不存在返回 nil不常用的命令
- 计数 incr key
127.0.0.1:6379[1]> incr b
(integer) 3
127.0.0.1:6379[1]> get b
"3"
127.0.0.1:6379[1]> incr b
(integer) 4
127.0.0.1:6379[1]> get b
"4"
127.0.0.1:6379[1]> incr b
(integer) 3
127.0.0.1:6379[1]> get b
"3"
127.0.0.1:6379[1]> incr b
(integer) 4
127.0.0.1:6379[1]> get b
"4"
decr(自减) incrby (增加指定的数值) decrby(减少指定的数值) incrbyfloat (增加浮点数)
127.0.0.1:6379[1]> incrby b 10
(integer) 14
127.0.0.1:6379[1]> get b
"14"
127.0.0.1:6379[1]> decrby b 9
(integer) 5
127.0.0.1:6379[1]> get b
"5"
127.0.0.1:6379[1]> incrbyfloat b 0.5
"5.5"
127.0.0.1:6379[1]> incrby b 10
(integer) 14
127.0.0.1:6379[1]> get b
"14"
127.0.0.1:6379[1]> decrby b 9
(integer) 5
127.0.0.1:6379[1]> get b
"5"
127.0.0.1:6379[1]> incrbyfloat b 0.5
"5.5"
- 不常用的命令
- 追加值 append key value
127.0.0.1:6379[1]> append a 2
(integer) 2
127.0.0.1:6379[1]> get a
"22"
127.0.0.1:6379[1]> append a 2
(integer) 2
127.0.0.1:6379[1]> get a
"22"
- 字符串长度 strlen key
127.0.0.1:6379[1]> strlen a
(integer) 2 // 返回长度
127.0.0.1:6379[1]> strlen a
(integer) 2 // 返回长度
- 设置并返回原值 getset key value
127.0.0.1:6379[1]> getset a 1
"22"
127.0.0.1:6379[1]> get a
"1"
127.0.0.1:6379[1]> getset a 1
"22"
127.0.0.1:6379[1]> get a
"1"
- 设置指定位置的字符 setrange key 下标 value
127.0.0.1:6379[1]> setrange a 0 2
(integer) 1
127.0.0.1:6379[1]> get a
"2"
127.0.0.1:6379[1]> setrange a 0 2
(integer) 1
127.0.0.1:6379[1]> get a
"2"
- 获取部分字符串 getrange key start end
127.0.0.1:6379[1]> set a 123456789
OK
127.0.0.1:6379[1]> get a
"123456789"
127.0.0.1:6379[1]> getrange a 1 4
"2345"
127.0.0.1:6379[1]> set a 123456789
OK
127.0.0.1:6379[1]> get a
"123456789"
127.0.0.1:6379[1]> getrange a 1 4
"2345"
- 命令的复杂度
命令 | 作用 | 复杂度 |
set key value | 设置单个属性 | O(1) |
get key | 获取单个属性的值 | O(1) |
del key ... | 删除键值 | O(k) k是元素个数 |
mset key value ... | 设置多个键值的值 | O(k) k是元素个数 |
mget key... | 得到多个键值的值 | O(k) k是元素个数 |
incr key / incrby key | 增 | O(1) |
decr key / dectby key | 减 | O(1) |
incrbyfloat key value | 增加浮点数 | O(1) |
append key value | 末尾增加 | O(1) |
strlen key | 得到字符串长度 | O(1) |
setrange key offset value | 更新某个位置值 | O(1) |
getrange key start end | 获取一段的值 | O(n) n是字符串长度 |
字符串的内部编码
- int :8个字节的长整型
- embstr :小于等于39个字节的字符串
- raw : 大于39个字节的字符串
使用场景
- 缓存功能 ,Redis作为缓存层,MySQL作为储存层 在高并发的请求中我们把用户信息储存到redis中可以快速获取用户信息
- 计数我们可以用redis 记录视频的播放次数
- 共享session 在分布式web服务中心将用户的session信息用redis集中进行管理,每次用户更新或者查询登录信息时都可以直接去redis 中获取
- 限速,可以限制用户手机验证码的频繁获取
哈希
哈希类型是指键值本身又是一个键值对结构,形如value{{key1,value1},{key2 value2}} 就相当于 一个 Java中的类 一个person类中有人的 名字年龄等等一些信息
命令
- 设置值 hset key field value
127.0.0.1:6379[1]> hset person name zhangsan
(integer) 1
127.0.0.1:6379[1]> hset person name zhangsan
(integer) 1
- 获取值 hget key field
127.0.0.1:6379[1]> hget person name
"zhangsan"
127.0.0.1:6379[1]> hget person age
(nil)// 不存在返回nil
127.0.0.1:6379[1]> hget person name
"zhangsan"
127.0.0.1:6379[1]> hget person age
(nil)// 不存在返回nil
- 删除 hdel key field [field...]
127.0.0.1:6379[1]> hset person age 12
(integer) 1
127.0.0.1:6379[1]> hset person sex 1
(integer) 1
127.0.0.1:6379[1]> hkeys person // 查询所有键值
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379[1]> hdel person age sex
(integer) 2
127.0.0.1:6379[1]> hkeys person
1) "name"
127.0.0.1:6379[1]> hdel person city
(integer) 0 // 删除不存在的键的返回值
127.0.0.1:6379[1]> hset person age 12
(integer) 1
127.0.0.1:6379[1]> hset person sex 1
(integer) 1
127.0.0.1:6379[1]> hkeys person // 查询所有键值
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379[1]> hdel person age sex
(integer) 2
127.0.0.1:6379[1]> hkeys person
1) "name"
127.0.0.1:6379[1]> hdel person city
(integer) 0 // 删除不存在的键的返回值
- 计算field 的个数 hlen key
127.0.0.1:6379[1]> hlen person
(integer) 1 // 说明剩余一个
127.0.0.1:6379[1]> hset person city Beijing
(integer) 1
127.0.0.1:6379[1]> hlen person
(integer) 2
127.0.0.1:6379[1]> hlen person
(integer) 1 // 说明剩余一个
127.0.0.1:6379[1]> hset person city Beijing
(integer) 1
127.0.0.1:6379[1]> hlen person
(integer) 2
- 批量设置或批量获取
hmset key field value [...]
hget key field value [...]
127.0.0.1:6379[1]> hmset student name zhangsan age 21 sex 1
OK
127.0.0.1:6379[1]> hmget student name age sex
1) "zhangsan"
2) "21"
3) "1"
127.0.0.1:6379[1]> hmset student name zhangsan age 21 sex 1
OK
127.0.0.1:6379[1]> hmget student name age sex
1) "zhangsan"
2) "21"
3) "1"
- 判断field是否存在 hexists key field
127.0.0.1:6379[1]> hexists student name
(integer) 1 // 存在
127.0.0.1:6379[1]> hexists student address
(integer) 0 // 不存在
127.0.0.1:6379[1]> hexists student name
(integer) 1 // 存在
127.0.0.1:6379[1]> hexists student address
(integer) 0 // 不存在
- 获取所有的field hkeys key
127.0.0.1:6379[1]> hkeys student
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379[1]> hkeys student
1) "name"
2) "age"
3) "sex"
- 获取所有的value hvals key
127.0.0.1:6379[1]> hvals student
1) "zhangsan"
2) "21"
3) "1"
127.0.0.1:6379[1]> hvals student
1) "zhangsan"
2) "21"
3) "1"
- 获取所有的 field-value hgetall key
127.0.0.1:6379[1]> hgetall student
1) "name"
2) "zhangsan"
3) "age"
4) "21"
5) "sex"
6) "1"
127.0.0.1:6379[1]> hgetall student
1) "name"
2) "zhangsan"
3) "age"
4) "21"
5) "sex"
6) "1"
- hincrby hincrbyfloat
127.0.0.1:6379[1]> hset student score 50
(integer) 1
127.0.0.1:6379[1]> hincrby student score 1 //后面加上自定义的数值
(integer) 51 // 返回值为更新过后的值
127.0.0.1:6379[1]> hincrbyfloat student score 1.5
"52.5"
127.0.0.1:6379[1]> hget student score
"52.5"
127.0.0.1:6379[1]> hset student score 50
(integer) 1
127.0.0.1:6379[1]> hincrby student score 1 //后面加上自定义的数值
(integer) 51 // 返回值为更新过后的值
127.0.0.1:6379[1]> hincrbyfloat student score 1.5
"52.5"
127.0.0.1:6379[1]> hget student score
"52.5"
- 命令复杂度分析
命令 | 命令作用 | 复杂度 |
hset key field value | 设置 key 的单个属性的值 | O(1) |
hget key field value | 得到key 的单个属性的值 | O(1) |
hdel key field ... | 批量删除key 的属性 | O(k) k是field的个数 |
hlen key | 得到key中属性的个数 | O(k) k是field的个数 |
hmset key field value ... | 批量设置key 属性 | O(k) k是field的个数 |
hmget key field ... | 批量得到key 属性的值 | O(k) k是field的个数 |
hexists key field | 判断key 中的属性是否存在 | O(1) |
hkeys key | 得到所有key中的属性 | O(n) n是field的个数 |
hvals key | 得到所有key 中的属性的值 | O(n) n是field的个数 |
hgetall | 得到key中所有属性和值 | O(1) |
hincrby/hincrbyfloat | 增加 | O(1) |
内部编码
- ziplist(压缩列表) 当hash 类型元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64字节)Redis会使用ziplist作为hash的内部实现 ziplist 比较节省内存
- hashtable (哈希表) 当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,hashtable 的读写速度为O(1)
使用场景
- 利用Redis的hash储存用户的属性,这样更加直观,操作时更加便捷
列表
列表类型是用来储存多个有序字符串,列表中的元素可以通过下标来获取,列表中的元素可以重复,一个列表最多可以储存232 -1 个元素 list 可以充当队列或者栈使用
命令
- 在某个元素之前或者之后插入 linsert key before/after pivot value
127.0.0.1:6379[1]> linsert list1 before 6 7
(integer) 7
127.0.0.1:6379[1]> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "1"
6) "2"
7) "3"
127.0.0.1:6379[1]> linsert list1 after 3 4
(integer) 8
127.0.0.1:6379[1]> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379[1]> linsert list1 before 6 7
(integer) 7
127.0.0.1:6379[1]> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "1"
6) "2"
7) "3"
127.0.0.1:6379[1]> linsert list1 after 3 4
(integer) 8
127.0.0.1:6379[1]> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "1"
6) "2"
7) "3"
8) "4"
- 查找获取指定范围的列表 lrange list1 start end
127.0.0.1:6379[1]> lrange list1 1 3 // 类似于Python的切片
1) "6"
2) "5"
3) "4"
127.0.0.1:6379[1]> lrange list1 1 3 // 类似于Python的切片
1) "6"
2) "5"
3) "4"
- 获取列表指定索引下标的元素 lindex key index
127.0.0.1:6379[1]> lindex list1 0
"7"
127.0.0.1:6379[1]> lindex list1 0
"7"
- 获取列表长度 llen key
127.0.0.1:6379[1]> llen list1
(integer) 8
127.0.0.1:6379[1]> llen list1
(integer) 8
- 删除元素 lpop/rpop key
127.0.0.1:6379[1]> lpop list1
"7"
127.0.0.1:6379[1]> rpop list1
"4"
127.0.0.1:6379[1]> lpop list1
"7"
127.0.0.1:6379[1]> rpop list1
"4"
- 删除指定元素 lrem key count
- count>0 从左到右,删除最多count 个元素
- count<0 从右到左,删除最多count个元素
- count=0 删除所有
127.0.0.1:6379[1]> lpush list1 1 1 1 1
(integer) 10
127.0.0.1:6379[1]> rpush list1 1 1 1 1
(integer) 14
127.0.0.1:6379[1]> lrange list1 0 -1
1) "1"
2) "1"
3) "1"
4) "1"
5) "6"
6) "5"
7) "4"
8) "1"
9) "2"
10) "3"
11) "1"
12) "1"
13) "1"
14) "1"
127.0.0.1:6379[1]> lrem list1 4 1
(integer) 4
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
4) "1"
5) "2"
6) "3"
7) "1"
8) "1"
9) "1"
10) "1"
127.0.0.1:6379[1]> lrem list1 -4 1
(integer) 4
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379[1]> lrem list1 0 1
(integer) 1
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
4) "2"
5) "3"
- 按照范围修剪列表 ltrim key start end
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
4) "2"
5) "3"
127.0.0.1:6379[1]> ltrim list1 0 2
OK
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
4) "2"
5) "3"
127.0.0.1:6379[1]> ltrim list1 0 2
OK
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
- 修改指定索引下标的元素 lset key index newValue
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
127.0.0.1:6379[1]> lset list1 0 1
OK
127.0.0.1:6379[1]> lrange list1 0 -1
1) "1"
2) "5"
3) "4"
127.0.0.1:6379[1]> lrange list1 0 -1
1) "6"
2) "5"
3) "4"
127.0.0.1:6379[1]> lset list1 0 1
OK
127.0.0.1:6379[1]> lrange list1 0 -1
1) "1"
2) "5"
3) "4"
- 阻塞时弹出操作
- blpop/ brpop key [key ...] timeout
timeout 表示阻塞时间
- 如果列表为空 timeout ==3 那么客户端1会等三秒返回, 如果在此期间另一个客户端 客户端2从中添加一个元素后,客户端1会立即返回客户端2添加的元素
- 如果timeout==0 当前list 为空 就会一直等待下去 直到获取到值为止
- 如果不为空客户端1会立即返回
如图所示
客户端1:127.0.0.1:6379> brpop t 0
1) "t"
2) "1"
(6.67s) // 等待的时间
客户端1:127.0.0.1:6379> brpop t 0
1) "t"
2) "1"
(6.67s) // 等待的时间
客户端2:127.0.0.1:6379> lpush t 1
(integer) 1
客户端2:127.0.0.1:6379> lpush t 1
(integer) 1
- 如果有多个客户端执行brpop 会按照 执行brpop命令的先后顺序 得到元素
- 命令复杂度分析
命令 | 命令作用 | 时间复杂度 |
rpush key value ... | 列表右侧添加多个元素 | O(k) k为添加元素的个数 |
lpush key value ... | 列表左侧添加多个元素 | O(k) k为添加元素的个数 |
linsert key after/before pivot value | 在列表某个元素之前后插入元素 | O(n) n为pivot到列表头或尾的距离 |
lrange key start end | 查找指定范围的值 | O(s+n) s是start偏移量,n是start到end的范围 |
lindex key lindex | 查找对应下标的值 | O(n) n是索引的偏移量 |
llen key | 获取列表的长度 | O(1) |
lpop | 从左侧删除 | O(1) |
rpop | 从右侧删除 | O(1) |
lrem key count value | 删除 一些元素 | O(n) n是列表长度 |
ltrim key start end | 剪切列表 | O(n) n为要裁剪的元素总数 |
lset key index value | 修改指定位置的元素的值 | O(n) 你是索引偏移量 |
brpop blpop | 阻塞弹出操作 | O(1) |
内部编码
1. ziplist(压缩列表) 当hash 类型元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64字节)Redis会使用ziplist作为hash的内部实现 ziplist 比较节省内存
2. linkedlist(链表)当列表类型无法满足ziplist的条件时,Redis会选用linkedlist 作为内部实现
3. Redis3.2以上的 版本提供了quicklist 是ziplist和linkedlist优势的结合
使用场景
1. 消息队列 redis的lpush+brpop 命令组合可以实现阻塞队列,生产者 负责生产元素,消费者客户端使用brpop命令阻塞式的“抢:列表内部的元素,多个客户端保证了消费的复杂均衡
2. 文章列表 每篇文章可以用hash 存储 我们可以把文章放进列表里 分页获取文章列表
集合
集合也是用来保存多个字符串元素,但和列表不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标来获取元素,一个集合最多储存 2 32 -1个元素,集合支持 交集,并集,差集
命令
- 添加元素 sadd key element
127.0.0.1:6379[1]> sadd myset1 1 2 3
(integer) 3 //返回插入成功的数量
127.0.0.1:6379[1]> sadd myset1 3
(integer) 0
127.0.0.1:6379[1]> sadd myset1 1 2 3
(integer) 3 //返回插入成功的数量
127.0.0.1:6379[1]> sadd myset1 3
(integer) 0
- 删除元素 srem key element
127.0.0.1:6379[1]> srem myset1 1 2 3
(integer) 3
127.0.0.1:6379[1]> srem myset1 1 2 3
(integer) 3
- 计算元素个数 scard key
(integer) 0
127.0.0.1:6379[1]> sadd myset1 1 2 3
(integer) 3
127.0.0.1:6379[1]> scard myset1
(integer) 3
(integer) 0
127.0.0.1:6379[1]> sadd myset1 1 2 3
(integer) 3
127.0.0.1:6379[1]> scard myset1
(integer) 3
- 判断元素是否存在集合之中 sismember key element
127.0.0.1:6379[1]> sismember myset1 1
(integer) 1
127.0.0.1:6379[1]> sismember myset1 4
(integer) 0
127.0.0.1:6379[1]> sismember myset1 1
(integer) 1
127.0.0.1:6379[1]> sismember myset1 4
(integer) 0
- 随机从集合返回指定个数元素 srandmember key [count] // count 默认为1
127.0.0.1:6379[1]> srandmember myset1 2
1) "1"
2) "3"
127.0.0.1:6379[1]> srandmember myset1 2
1) "1"
2) "3"
- 从集合中随机弹出元素 :spop key
127.0.0.1:6379[1]> spop myset1
"1"
127.0.0.1:6379[1]> spop myset1
"1"
- 获取所有元素: smembers key
127.0.0.1:6379[1]> smembers myset1
1) "2"
2) "3"
127.0.0.1:6379[1]> smembers myset1
1) "2"
2) "3"
- 求多个集合的交集: sinter key ... // 后面可以跟多个键
127.0.0.1:6379[1]> sadd myset2 2 3 4
(integer) 3
127.0.0.1:6379[1]> smembers myset1
1) "2"
2) "3"
127.0.0.1:6379[1]> smembers myset2
1) "2"
2) "3"
3) "4"
127.0.0.1:6379[1]> sinter myset1 myset2
1) "2"
2) "3"
127.0.0.1:6379[1]> sadd myset2 2 3 4
(integer) 3
127.0.0.1:6379[1]> smembers myset1
1) "2"
2) "3"
127.0.0.1:6379[1]> smembers myset2
1) "2"
2) "3"
3) "4"
127.0.0.1:6379[1]> sinter myset1 myset2
1) "2"
2) "3"
- 求多个集合的并集 : sunion key ...
127.0.0.1:6379[1]> sadd myset1 1
(integer) 1 // 为了好区分 在 set中插入一个1
127.0.0.1:6379[1]> sunion myset1 myset2
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379[1]> sadd myset1 1
(integer) 1 // 为了好区分 在 set中插入一个1
127.0.0.1:6379[1]> sunion myset1 myset2
1) "1"
2) "2"
3) "3"
4) "4"
- 求多个集合的差集 : sdiff key...
127.0.0.1:6379[1]> sdiff myset1 myset2
1) "1"
127.0.0.1:6379[1]> sdiff myset1 myset2
1) "1"
- 将集合的 交并差结果保存 : sinterstore(交)/suinonstore(并)/sdiffstore(差)+ 保存的键的名字 key ...
127.0.0.1:6379[1]> sinterstore mysetinter myset1 myset2
(integer) 2
127.0.0.1:6379[1]> smembers mysetinter
1) "2"
2) "3"
// 剩下两个不再掩演示
127.0.0.1:6379[1]> sinterstore mysetinter myset1 myset2
(integer) 2
127.0.0.1:6379[1]> smembers mysetinter
1) "2"
2) "3"
// 剩下两个不再掩演示
- 命令的时间复杂度
命令 | 命令作用 | 时间复杂度 |
sadd key element... | 添加元素 | O(k) k是元素个数 |
srem key element | 删除元素 | O(k) k是元素个数 |
scard key | 计算元素数量 | O(1) |
sismember key element | 元素是否存在集合 | O(1) |
srandmember key count | 随机返回指定个数元素 | O(count) |
spop key | 弹出元素 | O(1) |
smembers key | 所有元素 | O(n) n是元素个数 |
sinter key ... /sinterstore | 交集 | O(m*k) m 集合中元素最少的 k集合中元素最多的 |
suinon key ... /suinonstroe | 并集 | O(k) k是多个集合元素个数和 |
sdiff key ... /sdiffstore | 差集 | O(k) k是多个集合元素个数和 |
内部编码
- intset(整数集合) 当集合中的元素都是整数,且元素个数小于set-max-intset-entries 配置(默认512个) redis会选用intset 作为内部实现,节省内存的使用
- hashtable (哈希表) 当集合类型无法满足时 使用hashtable
使用场景
- 标签 用户可能对娱乐,体育比较感兴趣,另一个用户对新闻,动漫感兴趣,这些兴趣都是标签,有了这些数据 可以得到喜欢同一个标签的人,以及用户的共同喜好,可以用这些数据增强用户粘度和用户体验
有序集合
命令
- 添加元素 zadd key score member [score member...]
127.0.0.1:6379[1]> zadd rank1 1 zhangsan 2 lisi 3 wangwu
(integer) 3 //成功添加的个数
127.0.0.1:6379[1]> zadd rank1 1 zhangsan 2 lisi 3 wangwu
(integer) 3 //成功添加的个数
- 计算成员个数 :zcard key
127.0.0.1:6379[1]> zcard rank1
(integer) 3
127.0.0.1:6379[1]> zcard rank1
(integer) 3
- 计算某个成员的分数:zscore key member
127.0.0.1:6379[1]> zscore rank1 zhangsan
"1"
127.0.0.1:6379[1]> zscore rank1 zhangsan
"1"
- 计算成员的排名 zrank/zrevrank key member
127.0.0.1:6379[1]> zrank rank1 zhangsan
(integer) 0
127.0.0.1:6379[1]> zrevrank rank1 zhangsan
(integer) 2
127.0.0.1:6379[1]> zrank rank1 zhangsan
(integer) 0
127.0.0.1:6379[1]> zrevrank rank1 zhangsan
(integer) 2
- 删除成员 zrem key member [member ...]
127.0.0.1:6379[1]> zrem rank1 zhangsan
(integer) 1
127.0.0.1:6379[1]> zrem rank1 zhangsan
(integer) 1
- 增加成员的分数 zincrby key increment member
127.0.0.1:6379[1]> zincrby rank1 10 lisi
"12" //返回增加后的数值
127.0.0.1:6379[1]> zincrby rank1 10 lisi
"12" //返回增加后的数值
- 返回指定排名范围的成员: zrange/zrevrange key start end [withscores]
127.0.0.1:6379[1]> zrange rank1 1 3 withscores // withscores 会带上分数
1) "wangwu"
2) "3"
3) "maliu"
4) "4"
5) "lisi"
6) "12"
127.0.0.1:6379[1]> zrevrange rank1 1 3
1) "maliu"
2) "wangwu"
3) "zhangsan"
127.0.0.1:6379[1]> zrange rank1 1 3 withscores // withscores 会带上分数
1) "wangwu"
2) "3"
3) "maliu"
4) "4"
5) "lisi"
6) "12"
127.0.0.1:6379[1]> zrevrange rank1 1 3
1) "maliu"
2) "wangwu"
3) "zhangsan"
- 返回指定分数范围的成员 :zrangebyscore/zrevrangebyscore key min/max max/min [withscores] [limit offset count // 限制输出的起始位置和个数]
127.0.0.1:6379[1]> zrangebyscore rank1 1 3 withscores
1) "zhangsan"
2) "1"
3) "wangwu"
4) "3"
127.0.0.1:6379[1]> zrevrangebyscore rank1 4 3 withscores
1) "maliu"
2) "4"
3) "wangwu"
4) "3"
127.0.0.1:6379[1]> zrangebyscore rank1 1 3 withscores
1) "zhangsan"
2) "1"
3) "wangwu"
4) "3"
127.0.0.1:6379[1]> zrevrangebyscore rank1 4 3 withscores
1) "maliu"
2) "4"
3) "wangwu"
4) "3"
- 返回指定分数范围成员个数 zcount key min max
127.0.0.1:6379[1]> zcount rank1 1 3
(integer) 2
127.0.0.1:6379[1]> zcount rank1 1 3
(integer) 2
- 删除指定排名内的升序元素 zremrangebyrank key start end
127.0.0.1:6379[1]> zremrangebyrank rank1 1 2
(integer) 2
127.0.0.1:6379[1]> zrange rank1 0 10
1) "zhangsan"
2) "lisi"
127.0.0.1:6379[1]> zremrangebyrank rank1 1 2
(integer) 2
127.0.0.1:6379[1]> zrange rank1 0 10
1) "zhangsan"
2) "lisi"
- 删除指定分数范围的成员 zremrangebyscore key min max
127.0.0.1:6379[1]> zremrangebyscore rank1 10 14
(integer) 1
127.0.0.1:6379[1]> zrange rank1 0 10
1) "zhangsan"
127.0.0.1:6379[1]> zremrangebyscore rank1 10 14
(integer) 1
127.0.0.1:6379[1]> zrange rank1 0 10
1) "zhangsan"
- 交集 zinterstore destination numkeys key [key...] [weights weight [weight...]] [aggregate sum|max|min]
destination :交集计算结果保存的键
numkeys:需要做交集计算的个数
key[key..] 需要做交集计算的键
weights weight [weight ...] 每个键的权重,在做交集计算
127.0.0.1:6379[1]> zrange rank1 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "2"
5) "lihua"
6) "10"
127.0.0.1:6379[1]> zrange rank2 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "3"
5) "xiaohong"
6) "5"
7) "xiaoming"
8) "6"
127.0.0.1:6379[1]> zinterstore interrank1andrank2 2 rank1 rank2
(integer) 2
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1
1) "zhangsan"
2) "lisi"
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1 withscroes
(error) ERR syntax error
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1 withscores
1) "zhangsan"
2) "2"
3) "lisi"
4) "5"
127.0.0.1:6379[1]> zinterstore interrank 2 rank1 rank2 weights 1 0.5 aggregate max // rank1 的 score*1.0 rank2 的score*0.5 然后取两者中最大的
(integer) 2
127.0.0.1:6379[1]> zrange interrank 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "2"
127.0.0.1:6379[1]> zrange rank1 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "2"
5) "lihua"
6) "10"
127.0.0.1:6379[1]> zrange rank2 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "3"
5) "xiaohong"
6) "5"
7) "xiaoming"
8) "6"
127.0.0.1:6379[1]> zinterstore interrank1andrank2 2 rank1 rank2
(integer) 2
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1
1) "zhangsan"
2) "lisi"
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1 withscroes
(error) ERR syntax error
127.0.0.1:6379[1]> zrange interrank1andrank2 0 -1 withscores
1) "zhangsan"
2) "2"
3) "lisi"
4) "5"
127.0.0.1:6379[1]> zinterstore interrank 2 rank1 rank2 weights 1 0.5 aggregate max // rank1 的 score*1.0 rank2 的score*0.5 然后取两者中最大的
(integer) 2
127.0.0.1:6379[1]> zrange interrank 0 -1 withscores
1) "zhangsan"
2) "1"
3) "lisi"
4) "2"
- 并集 zunionstore destination numkeys key [key...] [weights weight [weight...]] [aggregate sum|max|min]
destination :交集计算结果保存的键
numkeys:需要做交集计算的个数
key[key..] 需要做交集计算的键
weights weight [weight ...] 每个键的权重,在做交集计算
代码不做演示和 交集一样- 命令复杂度分析
命令 | 作用 | 时间复杂度 |
zadd key score member ... | 批量添加 | O(k*logn) k是添加成员个数 n是当前集合成员个数 |
zcard key | 计算成员个数 | O(1) |
zscore key member | 计算成员的分数 | O(1) |
zrank/zrevrank key member | 查看成员的rank | O(logn) n当前有序集合成员个数 |
zrem key member | 删除成员 | O(k*logn) k删除成员个数 n当前集合个数 |
zincrby key increment member | 增长 | O(logn)n当前集合个数 |
zrange/zrevrange key satrt end withscores | 返回指定rank范围成员 | O(logn+k) k要获取的成员个数 n集合的成员个数 |
zrangebyscore/zrevrangebyscore key min/max max/min [withscores] | 返回指定分数范围成员 | O(logn+k) k要获取的成员个数 n集合的成员个数 |
zcount key min max | 计算分数范围的成员个数 | O(logn) n当前集合成员个数 |
zremrangebyrank key start end | 删除指定排名成员 | O(logn+k) k要删除的成员个数 n集合的成员个数 |
zremrangebyscore key min max | 删除指定分数成员 | O(logn+k) k要删除的成员个数 n集合的成员个数 |
zinterstore/zunionstroe destination numkeys key [key...] | 交集/并集 | O(n*k)+O(m*logm) n最小集合的成员个数 k有序集合的个数 m是结果集中成员个数/ O(n)+O(m*logm) n所有集合成员个数 m是结果集中成员个数 |
内部编码
- ziplist ziplist(压缩列表) 当hash 类型元素个数小于zset-max-ziplist-entries配置(默认128个),同时所有值都小于hash-max-ziplist-value配置(默认64字节)Redis会使用ziplist作为hash的内部实现 ziplist 比较节省内存
- skiplist(跳表)
使用场景
- 热度排行榜
- 用户点赞数
其他
- 键重命名 rename key newkey
如果当前键名已存在会覆盖掉之前的键
redis提供了renamenx 命令 ex:renamenx key value
- 重命名期间执行del删除旧键时,如果键对应的值较大,会存在阻塞
- 随机返回一个键 randomkey
- persist 命令可以消除 键的过期时间 persist key
- 对于字符串类型在进行set 时 会去掉过期时间
- scan 渐进式遍历键 scan x
127.0.0.1:6379[1]> scan 0
1) "3"
2) 1) "rank1"
2) "interrank"
3) "list1"
4) "d"
5) "person"
6) "myset2"
7) "a"
8) "interrank1andrank2"
9) "mysetinter"
10) "mtyset1"
11) "myset1"
127.0.0.1:6379[1]> scan 3
1) "0"
2) 1) "c"
2) "b"
3) "rank2"
4) "student"
127.0.0.1:6379[1]> keys *
1) "rank1"
2) "d"
3) "person"
4) "c"
5) "interrank1andrank2"
6) "mysetinter"
7) "b"
8) "myset2"
9) "a"
10) "interrank"
11) "list1"
12) "mtyset1"
13) "myset1"
14) "rank2"
15) "student"
127.0.0.1:6379[1]> scan 0
1) "3"
2) 1) "rank1"
2) "interrank"
3) "list1"
4) "d"
5) "person"
6) "myset2"
7) "a"
8) "interrank1andrank2"
9) "mysetinter"
10) "mtyset1"
11) "myset1"
127.0.0.1:6379[1]> scan 3
1) "0"
2) 1) "c"
2) "b"
3) "rank2"
4) "student"
127.0.0.1:6379[1]> keys *
1) "rank1"
2) "d"
3) "person"
4) "c"
5) "interrank1andrank2"
6) "mysetinter"
7) "b"
8) "myset2"
9) "a"
10) "interrank"
11) "list1"
12) "mtyset1"
13) "myset1"
14) "rank2"
15) "student"
- 清空数据库
flushdb/flushall
前者清空当前数据库 后者全部清空