redis第三章:数据结构

2020-02-02  本文已影响0人  阿桃_28e7

redis数据结构

键管理

# 查看键数量:DBSIZE
127.0.0.1:6379> dbsize
(integer) 18

# 查询匹配的键(过时):KEYS pattern (支持glob风格通配符格)(生产环境禁止使用)[已被SCAN命令取代]
127.0.0.1:6379> keys *
 1) "session:2018"
 2) "ls"
 3) "ss2"
 4) "\xac\xed\x00\x05t\x00\x02k2"
 5) "ls2"
 6) "k"
 7) "foo"
 8) "user:2:followers"
 9) "uid"
10) "num"
11) "myzset"
12) "user:1:following"
13) "mylsalpha"
14) "dsts"
15) "ss"
16) "k2"
17) "preredis中key和value的存储大小限制
18) "key"

# 查询匹配的键(流行):SCAN cursor [MATCH pattern] [COUNT number] [TYPE type]
# 第一次scan返回结果为空,但第二次不为空,cursor为0表示已经扫描完所有键
127.0.0.1:6379> scan 0 match key count 10
1) "22"
2) (empty list or set)
127.0.0.1:6379> scan 22 match key count 10
1) "0"
2) 1) "key"

# 判断键是否存在: EXISTS key [key ...] 
# 存在返回1, 否则返回0, 多个键作为参数则返回,其中已经存在的键的数量
127.0.0.1:6379> exists foo myzset fakekey
(integer) 2
127.0.0.1:6379> exists foo
(integer) 1
127.0.0.1:6379> exists fakekey
(integer) 0127.0.0.1:6379> exists foo
(integer) 1
127.0.0.1:6379> exists fakekey
(integer) 0

# 删除键(小key): DEL key [key ...]
# DEL命令的参数不支持通配符,可以结合linux的管道和xargs命令实现删除所有符合规则的键
127.0.0.1:6379> del foo
(integer) 1
127.0.0.1:6379> del fakekey
(integer) 0

# 删除键(大key): UNLINK key [key ...]
127.0.0.1:6379> unlink bigkey
(integer) 1
127.0.0.1:6379> unlink fakekey
(integer) 0

# 查询键值的数据类型: TYPE key
127.0.0.1:6379> type fakekey
none
127.0.0.1:6379> type mystring
string
### 特别注意: 单个数字在redis中也是用string类型存储的
127.0.0.1:6379> type numStr
string
127.0.0.1:6379> type ls
list
127.0.0.1:6379> type myzset
zset
127.0.0.1:6379> type numSet
set
127.0.0.1:6379> type userMap
hash
127.0.0.1:6379> type hll # HyperLogLog
string
127.0.0.1:6379>  type nearRestaurants # GEO
zset

# 查询值对象的内部编码方式:OBJECT ENCODING [arguments [arguments ...]]
127.0.0.1:6379> object encoding fakekey
(nil)
127.0.0.1:6379> object encoding mystring
"embstr"
127.0.0.1:6379> object encoding ls
"quicklist"
127.0.0.1:6379> object encoding myzset
"ziplist"
127.0.0.1:6379> object encoding numSet
"intset"
127.0.0.1:6379> object encoding userMap
"ziplist"
127.0.0.1:6379> object encoding hll # HyperLogLog
"raw"
127.0.0.1:6379> object encoding nearRestaurants # GEO
"ziplist"

glob风格通配符规则:

符号 意义
? 匹配一个字符
* 匹配任意个(包括0个)字符
[] 匹配括号内任一字符,可以使用"-"表示一个范围,如:a[b-d]可以匹配ab,ac,ad
\x 匹配字符x,用于转义符号.如要匹配"?",就需要使用?

DEL命令技巧: 要删除所有"user:"开头的键,可以执行(强大的xargs)

redis-cli KEYS "user:*" | xargs redis-cli DEL

另外,由于DEL命令支持多个键作为参数,所以可以执行(性能更好)

redis-cli DEL `redis-cli KEYS "user:*"`

字符串类型

字符串类型是redis最基本的数据类型,它能存储任何形式的字符串(数字),包括二进制数据,一个字符串类型的键允许存储的最大数据是512MB (内存总共就那么几G,一个键值就能占512MB,有点可怕)

object命令:http://www.redis.cn/commands/object.html

# 数字带不带“”, 都是int编码
127.0.0.1:6379> set numStrK 123
OK
127.0.0.1:6379> object encoding numStrK
"int"
127.0.0.1:6379> set numStrK "123"
OK
127.0.0.1:6379> object encoding numStrK
"int"

127.0.0.1:6379> set shortStrK "shortStr"
OK
127.0.0.1:6379> object encoding shortStrK
"embstr"

127.0.0.1:6379> set longStrK "i am a long string whose length is more than 44 bytes"
OK
127.0.0.1:6379> object encoding longStrK
"raw"

列表类型(队列、列表)

内部使用双向链表实现, 至多包含2^32-1个元素,可以作为列表、队列、栈

集合类型

集合中元素都是唯一且无序的,一个集合类型的键可以存储至多2^32-1个字符串;
内部实现是值为空的散列表,所以增/删/判断元素是否存在,时间复杂度都是O(1);
最方便的是集合之间还可以进行并/交/差的运算

集合类型 列表类型
存储内容 至多2^32-1个字符串 至多2^32-1个字符串
有序性
唯一性

有序集合

有序集合,英文名:Sorted set,意味着每个元素都有一个用于排序的权重(即为每个元素带上一个分数),虽然元素都是唯一的,但分数可以相同;这种原生有序特性使得我们可以按顺序从集合中获取元素,默认升序

有序集合和列表类型对比:

为什么有序集合只有ZINTERSTORE / ZUINONSTORE, 而没有ZINTER / ZUNION

有序集合常用的使用场景是大数据排序: 游戏的玩家排行榜,所以很少会需要获得键中的全部数据

Redis设计者认为在做完交集 、并集后大部分情况是将结果存入新的键中以便后续处理

# 可以通过事务实现ZINTER
MULTI
ZINTERSTORE tempkey ...
ZRANGE tempkey ...
DEL tempKey
EXEC

散列类型

散列表示字段和值之间的映射关系,类型java中hashmap;为了与redis的键区分,我们使用"字段"来表示散列中值对象所关联的键,散列类型对于存储对象属性是一种完美的数据类型,至多包含2^32-1个字段

HLL类型

redis我们可以使用集合来进行唯一计数,但是,当数据量增大到上千万时,就需要考虑内存消耗和性能下降问题。如果不需要获取数据集的内容,只是想要得到不同值的个数,就可以使用HyperLogLog(HLL)数据类型来优化使用集合类型时的内存和性能问题

HLL命令都是PF开头,向HLL的发明者Philippe Flajolet致敬;HLL的优势在于能够使用固定数量的内存(每个HLL键占用12kb内存,却可以计算出最多2^64个不同元素的基数)和常数时间复杂度(每个键O(1))进行唯一计数。不过HLL算法返回的基数可能不准确(标准差1%,HLL是cardinality counting基数计数的一种)

# 想要统计餐厅一个星期的独立访客数,可以每天生成一个HLL,然后用pfmerge把7天数据合并为一个
127.0.0.1:6379> pfadd myresturant_1 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10
(integer) 1
127.0.0.1:6379> pfadd myresturant_2 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15
(integer) 1
127.0.0.1:6379> pfadd myresturant_3 u1 u2 u3 u4 u5 u10 u20 u30 u40 u50
(integer) 1
127.0.0.1:6379> pfmerge myresturant_week myresturant_1 myresturant_2 myresturant_3
OK
127.0.0.1:6379> pfcount myresturant_week
(integer) 19

GEO类型

排序

SORT命令可对列表类型、集合类型、有序集合类型进行排序,可完成与关系数据库中的连接查询相类似的任务

# 对集合进行排序
127.0.0.1:6379> SADD uid 6 12 66 86 70 2
(integer) 6
127.0.0.1:6379> SORT uid
1) "2"
2) "6"
3) "12"
4) "66"
5) "70"
6) "86"
# 当集合元素都是整数,Redis第这种情况进行了优化:元素是有序的
127.0.0.1:6379> SMEMBERS uid
1) "2"
2) "6"
3) "12"
4) "66"
5) "70"
6) "86"

# 对列表进行排序
127.0.0.1:6379> LPUSH ls 4 2 6 1 3 7
(integer) 6
127.0.0.1:6379> LRANGE ls 0 -1
1) "7"
2) "3"
3) "1"
4) "6"
5) "2"
6) "4"
127.0.0.1:6379> SORT ls
1) "1"
2) "2"
3) "3"
4) "4"
5) "6"
6) "7"
#(结合前面的LRANGE结果,可以看出SORT并不会影响原列表)
127.0.0.1:6379> LRANGE ls 0 -1
1) "7"
2) "3"
3) "1"
4) "6"
5) "2"
6) "4"

# 对字符进行排序,要加上ALPHA参数
127.0.0.1:6379> LPUSH ls2 a c e d B C A
(integer) 7
127.0.0.1:6379> LRANGE ls2 0 -1
1) "A"
2) "C"
3) "B"
4) "d"
5) "e"
6) "c"
7) "a"
127.0.0.1:6379> SORT ls2
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> SORT ls2 ALPHA
1) "a"
2) "A"
3) "B"
4) "c"
5) "C"
6) "d"
7) "e"

# 反序
127.0.0.1:6379> SORT uid DESC
1) "86"
2) "70"
3) "66"
4) "12"
5) "6"
6) "2"
127.0.0.1:6379> SORT ls2 ALPHA DESC
1) "e"
2) "d"
3) "C"
4) "c"
5) "B"
6) "A"
7) "a"

# LIMIT offset count (top3)
127.0.0.1:6379> SORT ls DESC
1) "7"
2) "6"
3) "4"
4) "3"
5) "2"
6) "1"
127.0.0.1:6379> SORT ls DESC LIMIT 0 3
1) "7"
2) "6"
3) "4"
127.0.0.1:6379> 

限制

key:512MB

String类型:一个String类型的value最大可以存储512M

List类型:list的元素个数最多为2^32-1个,也就是4294967295个。

Set类型:元素个数最多为2^32-1个,也就是4294967295个。

Hash类型:键值对个数最多为2^32-1个,也就是4294967295个。

Sorted set类型:跟Set类型一致

问题

1、为什么redis基本类型里没有数字类型

2、为什么有set类型还要有HyperLogLog

3、如何利用redis实现循环队列

4、如何利用redis实现随机开奖

5、为什么有序集合修改成功后,返回0

6、删除有序集合分数最高和最低两个元素可以一次操作完成吗

7、为什么有序集合只有ZINTERSTORE / ZUINONSTORE, 而没有ZINTER / ZUNION

上一篇下一篇

猜你喜欢

热点阅读