4.Redis基本操作与数据类型
[toc]
数据类型
Redis通用命令
String: 字符串类型
Hash: 哈希类型
List: 列表类型
Set: 集合类型
Sorted set: 顺序集合类型
Redis通用命令
连接Redis
1 | # 连接redis |
库操作
1 | # 切换库[1-15] |
数据操作
增
1
2
3
4
5# 追加数据(在value后追加指定值)
127.0.0.1:6379> APPEND name BB
(integer) 1
127.0.0.1:6379> get name
"ChenlinBB"删
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 删除所在库的数据
127.0.0.1:6379> flushdb
# 删除所有库的数据
127.0.0.1:6379> flushall
# 貌似和del一样(根据value选择非阻塞删除仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。)
127.0.0.1:6379> UNLINK ke
(integer) 1
# 删除一条"key"
127.0.0.1:6379> del name
(integer) 1
# 同时删除多条"key"
127.0.0.1:6379> del k1 k2 k3
(integer) 3改
1
2
3
4
5
6# 临时修改redis配置
127.0.0.1:6379> CONFIG SET protected-mode yes
# 修改"key"的名字(将chenlin改成cl)
127.0.0.1:6379> RENAME chenlin cl
OK查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# 查看所有的数据(注意!不要轻易使用,如想查看数据,先查看数据量DBSIZE)
127.0.0.1:6379> keys *
1) "name"
# 查看数据量
127.0.0.1:6379> DBSIZE
(integer) 1
# 查看单个数据(有数据)
127.0.0.1:6379> KEYS name
1) "name"
# 查看单个数据(无数据)
127.0.0.1:6379> KEYS xxx
(empty array)
# 查看所有的配置
CONFIG GET *
# 查看指定配置
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "10.0.0.51 172.16.1.51 127.0.0.1"
密码的配置与修改
配置文件配置密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 修改配置文件
vim redis.conf
requirepass 123
# 使用密码连接
redis-cli -a 123
# 登陆后输入密码
redis-cli
127.0.0.1:6379> AUTH 123
OK
127.0.0.1:6379> DBSIZE
(integer) 1
# redis连接后获取密码
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "123"redis连接后修改密码
1
2
3
4
5
6
7
8
9
10
11# 修改redis密码为234
127.0.0.1:6379> CONFIG SET requirepass 234
OK
127.0.0.1:6379> exit
# 测试登录
redis-cli
127.0.0.1:6379> DBSIZE
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 234
OK
配置文件
1 | # 编辑配置文件 |
Redis数据结构之字符串(String)
数据结构
String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。
是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.
如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len
当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。
需要注意的是字符串最大长度为512M。
- String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。
- String类型是二进制安全的。意味着Redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
- String类型可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。
命令行模式
1 | # 进入命令行模式: |
查看命令帮助
1 | 127.0.0.1:6379> help @string |
String数据结构中键(key)操作命令
增
set
语法格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 语法格式
set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
* NX:当数据库中key不存在时,可以将key-value添加数据库
* XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
* EX:key的超时秒数
* PX:key的超时毫秒数,与EX互斥
* NX:key不存在时创建,已存在则忽略。
* XX:key存在则更新,不存在则忽略。
# 增加数据的命令有以下几个:
* set :标准命令,"key"不存在时创建,已存在则更新。
* mset :批量创建"key",所有"key"不存在时创建,已存在则更新。
* setex :增加key并设置生存时间(单位为秒)
* psetex:增加key并设置生存时间(以毫秒为单位,1s=1000ms)
* setnx :"key"不存在时创建,已存在则忽略。
* msetnx:批量创建"key",所有"key"key不存在时创建,已存在则忽略。基础用法
1
2
3
4
5
6
7# 增加key
127.0.0.1:6379> set name cl
OK
# 设置多个key
127.0.0.1:6379> MSET name1 cl age1 18
OK使用set命令结合”EX”,”PX”的用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 增加key并设置生存时间(单位为秒)
127.0.0.1:6379> set name cl ex 10
OK
# "set"和"ex"合并成"setex"
127.0.0.1:6379> SETEX name 10 cl
OK
# 增加key并设置生存时间(以毫秒为单位,1s=1000ms)
127.0.0.1:6379> set name cl px 10
OK
# "set"和"px"合并成"psetex"
127.0.0.1:6379> PSETEX name 15 cl
OK使用set命令结合”NX”,”XX”的用法
1
2
3
4
5
6
7
8
9
10
11
12
13# 使用"nx"后:"key"不存在时创建,已存在则忽略。
127.0.0.1:6379> set name cl nx
OK
127.0.0.1:6379> set name cl1 nx
(nil)
127.0.0.1:6379> get name
"cl"
# "set"与"nx"合并成“setnx”
127.0.0.1:6379> SETNX name cl1
(integer) 0
127.0.0.1:6379> get name
"cl"批量增加多个”key”,同时定义多个键值对,”mset”也可以和”nx”一起用。
1
2
3
4
5# 批量创建"key",所有"key"不存在时创建,已存在则更新。
mset key1 value1 [key2 value2...]
# 批量创建"key",所有"key"不存在时创建,已存在则忽略。
msetnx key1 value1 [key2 value2...]
追加数据
基础用法
1
2
3
4
5
6
7
8
9# 使用setrange在第"num"个字符处更新数据(从0开始算起)
127.0.0.1:6379> SETRANGE name 3 cccccc
(integer) 9
127.0.0.1:6379> get name
"123cccccc"
# 在指定"key"的"value"后追加字符,如果"key"不存在则创建
127.0.0.1:6379> append name BB
"chenlinBB"
计数
整数递增
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 使用规则
* 如果key不存在,则初始值为0,incr之后其值为1
* 如果value非整型(如hello),则执行失败并返回错误信息。
* 步长increment为整数,当为负数时效果等于递减
# 对指定的"key"的"value"递增,递增步长默认1
127.0.0.1:6379> INCR num
1
127.0.0.1:6379> INCR num
2
# 对指定的"key"的"value"递增,并指定递增步长
127.0.0.1:6379> incrby num 2
4
127.0.0.1:6379> incrby num 2
6
# 对指定的"key"的"value"递增,并指定递增步长
127.0.0.1:6379> incrbyfloat num 0.2
0.4
127.0.0.1:6379> incrbyfloat num 0.2
0.6小数递增
1
2
3
4
5
6
7
8
9
10# 使用规则
* 如果key不存在,则初始值为0,incr之后其值为1
* 如果value非整型(如hello),则执行失败并返回错误信息。
* 步长increment为小数,当为负数时效果等于递减
# 对指定的"key"的"value"递增,并指定递增步长
127.0.0.1:6379> incrbyfloat num 0.2
0.4
127.0.0.1:6379> incrbyfloat num 0.2
0.6整数递减
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 使用规则
* 如果key不存在,则初始值为0,incr之后其值为1
* 如果value非整型(如hello),则执行失败并返回错误信息。
* 步长increment为整数,当为负数时效果等于递减
# 对指定的"key"的"value"递减,递减步长默认1
127.0.0.1:6379> DECR num
1
127.0.0.1:6379> DECR num
0
# 对指定的"key"的"value"递减,并指定递减步长
127.0.0.1:6379> decrby num 2
8
127.0.0.1:6379> decrby num 2
6
改
修改”key”和”value”
1
2
3
4
5
6
7
8
9
10# 将"key"的值(将"cl"改成"chenlin")
127.0.0.1:6379> set name chenlin
OK
# 使用getset命令修改数据
## 等同于"get"+"set",先执行"get",再执行"set"
127.0.0.1:6379> GETSET name chenlin
"cl"
127.0.0.1:6379> get name
"chenlin"修改生存时间
1
2
3
4
5
6
7# 修改生存时间(将指定key的生存时间修改为"200")
127.0.0.1:6379> EXPIRE cl 200
(integer) 1
# 取消生存时间(将指定key的生存时间取消)
127.0.0.1:6379> PERSIST jh
(integer) 1
查
查看”key”和”value”值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31# 查看所有的数据(注意!不要轻易使用,如想查看数据,先查看数据量DBSIZE)
127.0.0.1:6379> keys *
1) "name"
# 查看数据量
127.0.0.1:6379> DBSIZE
(integer) 1
# 查看"key"的值"value"
127.0.0.1:6379> get name
"cl"
# 批量查看"key"的值"value"
127.0.0.1:6379> mget k1 k2 k3
1) "a"
2) "b"
3) "c"
# 匹配key(键)cl
127.0.0.1:6379> keys *cl
1) "cl"
# 随机返回一个key
127.0.0.1:6379> RANDOMKEY
"cl2"
# 使用setrange在第"num"个字符处更新数据(从0开始算起)
# 从指定的字符范围截取字符串(从0开始算起)
getrange key start end
127.0.0.1:6379> GETRANGE name 1 4
"henl"查看生存时间
1
2
3
4
5
6
7
8
9
10
11# 以秒为单位查看key生存时间倒计时
## "-1"=未设置生存时间,永不过期
## "-2"=生存时间已到期
127.0.0.1:6379> TTL cl
(integer) 16
# 以毫秒为单位查看key生存时间倒计时
## "-1"=未设置生存时间,永不过期
## "-2"=生存时间已到期
127.0.0.1:6379> PTTL cl
(integer) 12199查看”key”,”value”属性
1
2
3
4
5
6
7
8
9
10
11
12
13# 查看key是否存在(存在:1 不存在:0)
127.0.0.1:6379> EXISTS k1
(integer) 1
127.0.0.1:6379> EXISTS k2
(integer) 0
# 查看指定key数据类型
127.0.0.1:6379> TYPE cl
string
# 查看字符的长度
127.0.0.1:6379> strlen name
(integer) 2
Redis数据结构之哈希(Hash)
数据结构
Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似于python中的dict和java中的map集合。
- 应用场景:
- 存储部分变更的数据,如用户信息,商品信息等。
- 最接近表结构的一种类型。
- 数据结构
- Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:
- 方法一
- 每次修改用户的某个属性需要,先反序列化改好后再序列化回去。开销较大。
- 方法二
- 用户ID数据冗余
- Hash方案
- 通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题
查看命令帮助
1 | 127.0.0.1:6379> help @hash |
String数据结构中键(key)操作命令
增
增加数据
语法格式
1
2
3
4
5
6
7
8
9
10# 语法格式
HSET key field value [field value ...]
HSETNX key field value
* NX:当数据库中key不存在时,可以将key-value添加数据库
# 增加数据的命令有以下几个:
* hset :标准命令,"key"不存在时创建,已存在则更新。
* hmset :批量创建"key",等同于"hset"
* hsetnx :单个创建,"hash表"或"key"不存在则创建,已存在则忽略。基础用法
1
2
3
4
5
6
7# 增加hash类型的单个field或增加多个field
127.0.0.1:6379> hset test id 1 name cl company 上海
(integer) 3
# 单个创建,"hash表"或"key"不存在则创建,已存在则忽略。
127.0.0.1:6379> HSETNX test id 1
(integer) 0
计数
hincrby
1
2
3
4
5
6
7
8
9
10
11
12# hincrby可以对hash对象的指定的field的value做递增操作
# 语法格式
HINCRBY key field increment
* 如果key不存在,则初始值为0,incr之后其值为1
* 对hash对象的指定的field的value做递增操作
* value必须是整型,否则执行失败并返回错误信息。
* 步长increment必须是整数,当increment为负数时为递减操作
# 示例
127.0.0.1:6379> HINCRBY test id 10
11hincrbyfloat
1
2
3
4
5
6
7
8
9
10
11
12# hincrbyfloat可以对hash对象的指定的field的value做递增操作
# 语法格式
HINCRBYFLOAT key field increment
* 如果key不存在,则初始值为0,incr之后其值为1
* 对hash对象的指定的field的value做递增操作
* value必须是数字类型,否则执行失败并返回错误信息。
* 步长increment必须是整数或浮点数,当increment为负数时为递减操作
# 示例
127.0.0.1:6379> HINCRBYFLOAT test id 10.9
21.9
过期策略(类似于生存时间)
1
2
3
4
5
6
7
8
9
10# hash类型可以使用全局函数expire做过期策略。
# 语法格式
expire key seconds
# 示例
127.0.0.1:6379> EXPIRE test 1000
1
127.0.0.1:6379> ttl test
993
删
基础用法
1
2
3
4
5
6
7
8# 使用hdel命令删除hash类型的value中的fields,可批量或单个删除
# 语法格式
HDEL key field1 [field2 ...]
# 示例
127.0.0.1:6379> HDEL test name
1
改
基础用法
1
2
3
4
5
6
7
8# 修改hash类型中指定的field的值
# 语法格式
HSET key field value [field value ...]
# 示例
127.0.0.1:6379> HSET test name cl
0
查
查询”field”或”value”值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29# 查询指定hash类型的field对应的值
127.0.0.1:6379> Hget test name
cl
# 查询指定hash类型的多个field对应的值
127.0.0.1:6379> hmget test name company
1) "cl"
2) "上海"
# 查询指定hash类型对象的全部field和对应的value值
127.0.0.1:6379> HGETALL test
1) "id"
2) "1"
3) "name"
4) "chenlin"
5) "company"
6) "上海"
# 查询指定hash类型对象的全部field
127.0.0.1:6379> HKEYS test
1) "id"
2) "name"
3) "company"
# 查询指定hash类型对象的全部field的values值
127.0.0.1:6379> HVALS test
1) "1"
2) "chenlin"
3) "上海"查询”field”或”value”属性
1
2
3
4
5
6
7
8
9
10
11# 查看hash类型的key中指定的field是否存在(存在:1 不存在:0)
127.0.0.1:6379> HEXISTS test name
1
# 查询hash类型中field的数量
127.0.0.1:6379> HLEN test
3
# 查询hash类型中指定filed对应的value的字符长度
127.0.0.1:6379> HSTRLEN test name
7
Redis数据结构之列表(List)
单键多值
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
数据结构
List的数据结构为快速链表quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。
Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
查看命令帮助
1 | help @list |
操作命令
增
增加元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37# 从左边插入元素,从左边依次追加进栈,先进后出,后进先出
127.0.0.1:6379> LPUSH name xxx yyy
(integer) 2
127.0.0.1:6379> LPUSH name zzz
(integer) 3
127.0.0.1:6379> LRANGE name 0 -1
1) "zzz"
2) "yyy"
3) "xxx"
# 从右边插入元素,从右边依次追加进队列,先进先出,后进后出。
127.0.0.1:6379> rpush name xxx yyy
(integer) 2
127.0.0.1:6379> rpush name zzz
(integer) 3
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "yyy"
3) "zzz"
# 从左边追加元素,只有list存在时才会执行
127.0.0.1:6379> LPUSHX name cl
(integer) 4
127.0.0.1:6379> LRANGE mylist 0 -1
1) "cl"
2) "xxx"
3) "yyy"
4) "zzz"
# 从右边追加元素,只有list存在时才会执行
127.0.0.1:6379> LPUSHX name cl
(integer) 4
127.0.0.1:6379> LRANGE mylist 0 -1
1) "xxx"
2) "yyy"
3) "zzz"
4) "cl"插入元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# 从list中指定的元素的前/后 插入一个新元素
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "yyy"
3) "zzz"
# 在某个KEY值之前插入一个值
127.0.0.1:6379> LINSERT name before zzz cl
(integer) 4
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "yyy"
3) "cl"
4) "zzz"
# 在某个KEY值后面添加一个值
127.0.0.1:6379> LINSERT name after xxx chenlin
(integer) 5
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "chenlin"
3) "yyy"
4) "cl"
5) "zzz"消费和消费追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56# 从左边消费列表中的元素,消费完之后从列表中删除。
127.0.0.1:6379> LRANGE mylist 0 -1
1) "19"
2) "1616"
3) "1615"
4) "jh"
5) "python"
6) "linux"
127.0.0.1:6379> LPOP mylist
"19"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "1616"
2) "1615"
3) "jh"
4) "python"
5) "linux"
# 从右边消费列表中的元素,消费完之后从列表中删除。
127.0.0.1:6379> LRANGE mylist 0 -1
1) "1616"
2) "1615"
3) "jh"
4) "python"
5) "linux"
127.0.0.1:6379> RPOP mylist
"linux"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "1616"
2) "1615"
3) "jh"
4) "python"
# 消费列表A的最右边的元素返回,然后追加到列表B的最左边。
127.0.0.1:6379> LRANGE mylist 0 -1
1) "1616"
2) "1615"
3) "jh"
4) "python"
127.0.0.1:6379> RPOPLPUSH mylist mylist
"python"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "python"
2) "1616"
3) "1615"
4) "jh"
# 从列表中左侧查询元素,返回列表的key和左侧第一个元素,若所有查询的列表中都没有元素,则会阻塞等待至设置的timeout秒之后返回空,若在这期间,这些列表新增了元素,则会立刻消费并返回该元素。
127.0.0.1:6379> BLPOP mylist 10
1) "mylist"
2) "1616"
127.0.0.1:6379> BLPOP mylist 10
1) "mylist"
2) "1615"
127.0.0.1:6379> BLPOP mylist 10
1) "mylist"
2) "jh"
删
删除数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25# 从列表左侧,删除指定"个数"的"值"
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "chenlin"
3) "yyy"
4) "cl"
5) "zzz"
127.0.0.1:6379> LREM name 1 cl
(integer) 1
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "chenlin"
3) "yyy"
4) "zzz"
# 从列表左侧,删除指定范围之外的数据
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "chenlin"
3) "yyy"
127.0.0.1:6379> LTRIM name 0 1
OK
127.0.0.1:6379> LRANGE name 0 -1
1) "xxx"
2) "chenlin"
改
修改元素
1
2
3
4
5
6
7
8
9
10
11
12# 修改元素内容(将左边第3个元素修改为19)
127.0.0.1:6379> LSET mylist 2 19
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "Shanghai7"
2) "shanghai"
3) "19"
4) "1616"
5) "1615"
6) "jh"
7) "python"
8) "linux"
查
查询数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 查看列表中元素的个数
127.0.0.1:6379> LLEN name
(integer) 4
# 根据起止下标范围查询列表元素
## 查询全部元素
127.0.0.1:6379> lrange mylist 0 -1
1) "19"
2) "1616"
3) "1615"
4) "jh"
5) "python"
6) "linux"
## 查询最右边的元素
127.0.0.1:6379> lrange mylist -1 -1
1) "linux"
# 根据指定的index下标查看列表中的元素
127.0.0.1:6379> LINDEX mylist 3
"jh"
Redis数据结构之无序集合(Set)
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的复杂度都是O(1)。一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变。集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
数据结构
Set数据结构是dict字典,字典是用哈希表实现的。
Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。
查看帮助命令
1 | # 使用Redis命令手册查看 |
操作命令
增
增加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 给集合内新增成员,若集合不存在则创建集合并新增成员。
SADD key member [member ...]
# 增加一条member
127.0.0.1:6379> SADD fan 1
(integer) 1
127.0.0.1:6379> SMEMBERS fan
1) "1"
# 增加多条member
127.0.0.1:6379> SADD fan 2 3 4 5
(integer) 4
127.0.0.1:6379> SMEMBERS fan
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
删
删除数据
1
2
3
4
5
6
7
8
9# 从集合中删除指定的成员,返回删除的个数。
SREM key member [member ...]
# 示例
127.0.0.1:6379> SREM myset 2 4
(integer) 2
127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "3"
改
修改数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#1.移动数据
SMOVE source destination member
#2.示例
127.0.0.1:6379> SADD myset1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> SADD myset2 one two three
(integer) 3
127.0.0.1:6379> SMOVE myset1 myset2 4
(integer) 1
127.0.0.1:6379> SMEMBERS myset1
1) "1"
2) "2"
3) "3"
4) "5"
127.0.0.1:6379> SMEMBERS myset2
1) "three"
2) "two"
3) "4"
4) "one"
查
查看数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41# 查看集合中所有的成员
127.0.0.1:6379> SMEMBERS myset1
1) "1"
2) "2"
3) "3"
4) "5"
# 返回集合中成员的个数
127.0.0.1:6379> SCARD myset1
(integer) 4
# 从集合中随机返回指定个数的成员
127.0.0.1:6379> SRANDMEMBER myset1 2
1) "3"
2) "2"
127.0.0.1:6379> SRANDMEMBER myset1 2
1) "5"
2) "3"
#4.判断对象是否是集合中的成员,1表示true,0表示false
SISMEMBER key member
127.0.0.1:6379> SISMEMBER myset1 6
(integer) 0
127.0.0.1:6379> SISMEMBER myset1 2
(integer) 1
#5.随机返回一个成员,从集合中随机弹出一个成员,返回该成员并从集合中删除该成员。
SPOP key
127.0.0.1:6379> SPOP myset2
"one"
127.0.0.1:6379> SPOP myset2
"two"
127.0.0.1:6379> SPOP myset2
"three"
127.0.0.1:6379> SMEMBERS myset2
1) "4"集合
交集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#1.取多个集合的交集,返回这些集合中共同拥有的成员。
SINTER key [key ...]
127.0.0.1:6379> sadd myseta 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd mysetb 4 5 6 7 8
(integer) 5
127.0.0.1:6379> sadd mysetc 5 6 7 8 9
(integer) 5
127.0.0.1:6379> SINTER myseta mysetb mysetc
1) "5"
#2.将多个集合的交集的结果保存为一个新的集合destination,返回新集合的成员个数。
SINTERSTORE destination key [key ...]
127.0.0.1:6379> SINTERSTORE mysetc mysetb myseta
(integer) 2
127.0.0.1:6379> SMEMBERS mysetc
1) "4"
2) "5"并集
1
2
3#1.取多个集合的并集,相同的成员会被去重。
SUNION key [key ...]
127.0.0.1:6379> SMEMBERS mysetb
- “4”
- “5”
- “6”
- “7”
- “8”
127.0.0.1:6379> SMEMBERS myseta
- “1”
- “2”
- “3”
- “4”
- “5”
127.0.0.1:6379> SUNION myseta mysetb
- “1”
- “2”
- “3”
- “4”
- “5”
- “6”
- “7”
- “8”
#2.将多个集合的并集的结果保存为一个新的集合
SUNIONSTORE destination key [key …]127.0.0.1:6379> SUNIONSTORE mysetc myseta mysetb
(integer) 8
127.0.0.1:6379> SMEMBERS mysetc- “1”
- “2”
- “3”
- “4”
- “5”
- “6”
- “7”
- “8”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 差集
```bash
# 取多个集合的差集,以最左边的为主集合,返回左集合中有而其他集合没有的成员。
127.0.0.1:6379> SDIFF myseta mysetb
1) "1"
2) "2"
3) "3"
#将多个集合的差集的结果保存为一个新的集合 ,返回新集合的成员个数 。
SDIFFSTORE destination key [key ...]
127.0.0.1:6379> SDIFFSTORE mysetc myseta mysetb
(integer) 3
127.0.0.1:6379> SMEMBERS mysetc
1) "1"
2) "2"
3) "3"
模拟发朋友圈
1 | 127.0.0.1:6379> lpush wechat 'zhouyi' |
Redis数据结构之有序集合Zset(sorted set)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
数据结构
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
- zset底层使用了两个数据结构:
- hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
- 跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
跳跃表(跳表)
简介
- 有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。Redis采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。
实例
对比有序链表和跳跃表,从链表中查询出51
有序链表
要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。
跳跃表
从第2层开始,1节点比51节点小,向后比较。
21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层
在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下
在第0层,51节点为要查找的节点,节点被找到,共查找4次。
从此可以看出跳跃表比有序链表效率要高
查看命令帮助
1 | @sorted_set help |
操作命令
增
增加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 往有序集合中新增成员,需要指定该成员的分数,分数可以是整形或浮点型,当分数相同时候,索引下标按照字典排序。
# 语法格式
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
# 增加一条数据
127.0.0.1:6379> ZADD myzset 1 jh
1
# 增加多条数据
127.0.0.1:6379> ZADD myzset 2 shanghai 3 beijing
2
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
shanghai
beijing
删
删除数据
1
2
3
4
5
6
7
8
9
10
11
12#1.移除指定的成员
ZREM key member [member ...]
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
shanghai
beijing
127.0.0.1:6379> ZREM myzset shanghai
1
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
beijing
改
修改数据
1
查
查看数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51# 获取有序集合的成员数
ZCARD key
127.0.0.1:6379> ZCARD myzset
3
# 获取指定分数区间内的成员数
从有序集合内获取指定分数区间内的成员数。
ZCOUNT key min max
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
shanghai
beijing
127.0.0.1:6379> ZCOUNT myzset 1 2
2
#3.字典排序
根据字典排序返回min ,max之间的数据量.
ZLEXCOUNT key min max
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
shanghai
beijing
127.0.0.1:6379> ZLEXCOUNT myzset [sh [zzz
0
#4.获取成员的分数值
返回有序集中,成员的分数值,不存在的成员返回空。
ZSCORE key member
127.0.0.1:6379> ZRANGE myzset 0 -1
jh
shanghai
beijing
127.0.0.1:6379> ZSCORE myzset shanghai
2
#5.迭代有序集合中的元素(包括元素成员和元素分值)
127.0.0.1:6379> ZSCAN myzset 0 match "sh*"
0
shanghai
2
127.0.0.1:6379> ZSCAN myzset 0 match "j*"
0
jh
1