Bootstrap

Linux下数据库学习过程之Redis数据库的数据类型(二)(持续更新中)

1.Set
  • Redis 的 Set 是 String 类型的无序集合。集合中成员是唯一的,这就意味着集合中不能出现重复的数据。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)
  • Set类型一般用于赞、踩、标签、好友关系等。

向集合添加一个或多个成员

127.0.0.1:6379> SADD myset 1 1 2 2 3 3 4 4
(integer) 4

返回集合中的所有成员

127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "2"
3) "3"
4) "4"

返回集合中一个或多个随机数

127.0.0.1:6379> SRANDMEMBER myset
"2"
127.0.0.1:6379> SRANDMEMBER myset 4
1) "1"
2) "2"
3) "3"
4) "4"

SCARD key获取集合的成员数

127.0.0.1:6379> SCARD myset
(integer) 4

判断 member 元素是否是集合 key 的成员

127.0.0.1:6379> SISMEMBER myset 5
(integer) 0
127.0.0.1:6379> SISMEMBER myset 3
(integer) 1

移除集合中一个或多个成员

127.0.0.1:6379> SREM myset 3 4
(integer) 2
127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "2"

测试数据准备

127.0.0.1:6379> SADD myset2 1 2 3 4
(integer) 4
127.0.0.1:6379> SMEMBERS myset2
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> sadd myset3  1 3 4 5
(integer) 4
127.0.0.1:6379> SMEMBERS myset3
1) "1"
2) "3"
3) "4"
4) "5"

返回给定所有集合的差集

127.0.0.1:6379> SDIFF myset2 myset3
1) "2"

返回给定所有集合的差集并存储在 destination 中

127.0.0.1:6379> SDIFFSTORE myset4 myset2 myset3
(integer) 1
127.0.0.1:6379> SMEMBERS myset4
1) "2"

返回给定所有集合的交集

127.0.0.1:6379> SINTER myset2 myset3
1) "1"
2) "3"
3) "4"

返回给定所有集合的交集并存储在 destination 中

127.0.0.1:6379> SINTERSTORE myset5 myset2 myset3
(integer) 3
127.0.0.1:6379> SMEMBERS myset5
1) "1"
2) "3"
3) "4"

返回所有给定集合的并集

127.0.0.1:6379> SUNION myset2 myset3
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

将 member 元素从 source 集合移动到 destination 集合

127.0.0.1:6379> SMOVE myset2 myset3 2
(integer) 1
127.0.0.1:6379> SMEMBERS myset2
1) "1"
2) "3"
3) "4"
127.0.0.1:6379> SMEMBERS myset3
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

移除并返回集合中的一个随机元素

127.0.0.1:6379> SPOP myset3 
"2"
127.0.0.1:6379> SMEMBERS myset3
1) "1"
2) "3"
3) "4"
4) "5"
127.0.0.1:6379> SPOP myset3 2
1) "3"
2) "5"
127.0.0.1:6379> SMEMBERS myset3
1) "1"
2) "4"

迭代集合中的元素 :SSCAN key cursor [MATCH pattern] [COUNT count]

127.0.0.1:6379> sadd myset6 'apple' 'banana' 'berry' 'blueberry' 'peach' 'grape' 'watermelon' 'strawberry' 'pear' 
(integer) 9
127.0.0.1:6379> SMEMBERS myset6
1) "apple"
2) "banana"
3) "berry"
4) "blueberry"
5) "peach"
6) "grape"
7) "watermelon"
8) "strawberry"
9) "pear"

127.0.0.1:6379> SSCAN myset6 5 count 3 match *a*
1) "0"
2) 1) "apple"
   2) "banana"
   3) "peach"
   4) "grape"
   5) "watermelon"
   6) "strawberry"
   7) "pear"
  • 注意:SCAN 是一个基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程。SCAN 以 0 作为游标,开始一次新的迭代,直到命令返回游标 0 完成一次遍历。
    此命令并不保证每次执行都返回某个给定数量的元素,甚至会返回 0 个元素,但只要游标不是 0,程序都不会认为 SCAN 命令结束,但是返回的元素数量大概率符合 Count 参数。另外,SCAN 支持模糊查询。
2.ZSet
  • Redis 有序集合和集合一样也是string类型元素的集合且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
  • Zset类型一般用于排行榜等。

向有序集合添加一个或多个成员,或者更新已存在成员的分数

127.0.0.1:6379> ZADD myzset 20 'zhangsan' 40 lisi 80 wangwu
(integer) 3

通过索引区间返回有序集合指定区间内的成员

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "zhangsan"
2) "20"
3) "lisi"
4) "40"
5) "wangwu"
6) "80"

获取有序集合的成员数

127.0.0.1:6379> ZCARD myzset
(integer) 3

计算在有序集合中指定区间分数的成员数

127.0.0.1:6379> ZCOUNT myzset 20 40
(integer) 2
127.0.0.1:6379> ZCOUNT myzset 10 100
(integer) 3

有序集合中对指定成员的分数加上增量 increment

127.0.0.1:6379> ZADD myzset incr 60 zhaoliu
"60"
127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "zhangsan"
2) "20"
3) "lisi"
4) "40"
5) "zhaoliu"
6) "60"
7) "wangwu"
8) "80"
127.0.0.1:6379> ZADD myzset incr 60 zhaoliu
"120"
127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "zhangsan"
2) "20"
3) "lisi"
4) "40"
5) "wangwu"
6) "80"
7) "zhaoliu"
8) "120"
127.0.0.1:6379> ZADD myzset2 70 a 70 b 70 c 70 d 70 e 70 f
(integer) 6

通过索引区间返回有序集合指定区间内的成员

127.0.0.1:6379> ZRANGE myzset2 0 -1 withscores
 1) "a"
 2) "70"
 3) "b"
 4) "70"
 5) "c"
 6) "70"
 7) "d"
 8) "70"
 9) "e"
10) "70"
11) "f"
12) "70"

通过字典区间返回有序集合的成员,前提是元素分数一样

127.0.0.1:6379> ZRANGEBYLEX myzset2 - +
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379> ZRANGEBYLEX myzset2 [a [d
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> ZRANGEBYLEX myzset2 [c [f
1) "c"
2) "d"
3) "e"
4) "f"

在有序集合中计算指定字典区间内成员数量

127.0.0.1:6379> ZLEXCOUNT myzset2 - +
(integer) 6
127.0.0.1:6379> ZLEXCOUNT myzset2 [b [f
(integer) 5

通过分数返回有序集合指定区间内的成员

127.0.0.1:6379> ZRANGEBYSCORE myzset 20 80
1) "zhangsan"
2) "lisi"
3) "tony"
4) "lily"
5) "wangwu"

返回有序集合中指定成员的索引

127.0.0.1:6379> ZRANK myzset tony
(integer) 2

通过索引区间返回有序集合指定区间内的成员

127.0.0.1:6379> ZRANGE myzset 0 -1
1) "zhangsan"
2) "lisi"
3) "tony"
4) "lily"
5) "wangwu"
6) "zhaoliu"

通过索引区间返回有序集合指定区间内的成员

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
 1) "zhangsan"
 2) "20"
 3) "lisi"
 4) "40"
 5) "tony"
 6) "40"
 7) "lily"
 8) "60"
 9) "wangwu"
10) "80"
11) "zhaoliu"
12) "120"

返回有序集中指定区间内的成员,通过索引,分数从高到低

127.0.0.1:6379> ZREVRANGE myzset 0 -1 withscores
 1) "zhaoliu"
 2) "120"
 3) "wangwu"
 4) "80"
 5) "lily"
 6) "60"
 7) "tony"
 8) "40"
 9) "lisi"
10) "40"
11) "zhangsan"
12) "20"

返回有序集合中指定成员的索引

127.0.0.1:6379> ZRANK myzset zhangsan
(integer) 0

返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序

127.0.0.1:6379> ZRevrANK myzset zhangsan
(integer) 5

返回有序集中,成员的分数值

127.0.0.1:6379> ZSCORE myzset zhangsan 
"20"
  • ZADD的语法里的相关内容
    LT: Only update existing elements if the new score is less than the current score. This flag doesn’t prevent adding new elements.
    less than: 只更新的分数小于当前分数的已存在的元素
    GT: Only update existing elements if the new score is greater than the current score. This flag doesn’t prevent adding new elements.
    greater than: 只更新分数大于当前分数的已存在元素,
    CH: 修改返回元素的数量:ZADD可以做更新的操作,可以不对我们未做更改的元素做统计,只返回新添加的和更新的元素数量
2.Hash
  • Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
  • Hash类型一般用于存储用户信息、用户主页访问量、组合查询等。

将哈希表 key 中的字段 field 的值设为 value

127.0.0.1:6379> hset myhash name zhangsan age 20 gender M 
(integer) 3
127.0.0.1:6379> hset myhash2 name zhangsan age 20 gender M name lisi
(integer) 3

获取存储在哈希表中指定字段的值

127.0.0.1:6379> HGET myhash name
"zhangsan"
127.0.0.1:6379> HGET myhash2 name
"lisi"

获取在哈希表中指定 key 的所有字段和值

127.0.0.1:6379> HGETALL myhash
1) "name"
2) "zhangsan"
3) "age"
4) "20"
5) "gender"
6) "M"
127.0.0.1:6379> HGETALL myhash2
1) "name"
2) "lisi"
3) "age"
4) "20"
5) "gender"
6) "M"

只有在字段 field 不存在时,设置哈希表字段的值

127.0.0.1:6379> HEXISTS myhash name 
(integer) 1
127.0.0.1:6379> HEXISTS myhash one
(integer) 0

获取哈希表中所有值

127.0.0.1:6379> HVALS myhash
1) "zhangsan"
2) "20"
3) "M"

获取所有哈希表中的字段

127.0.0.1:6379> HKEYS myhash
1) "name"
2) "age"
3) "gender"

获取哈希表中字段的数量

127.0.0.1:6379> HLEN myhash
(integer) 3

获取所有给定字段的值

127.0.0.1:6379> HMGET myhash name age gender
1) "zhangsan"
2) "20"
3) "M"

为哈希表 key 中的指定字段的整数值加上增量 increment

127.0.0.1:6379> HINCRBY myhash age 10
(integer) 30

为哈希表 key 中的指定字段的浮点数值加上增量 increment

127.0.0.1:6379> HINCRBYfloat myhash age 10.1
"40.1"

删除一个或多个哈希表字段

127.0.0.1:6379> HDEL myhash gender
(integer) 1
127.0.0.1:6379> HKEYS myhash
1) "name"
2) "age"
3.Bitmaps
  • 位图
  • Bitmaps本身不是一种数据类型,实际上它就是字符串(key-value),但是它可以对字符串的位进行操作。
  • Bitmaps单独提供了一套命令,所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。

下面示例是代表 2024-07-19 这天的独立访问用户的Bitmaps

127.0.0.1:6379> setbit unique:users:20240719 1 1 
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 7 1 
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 14 1 
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 21 1 
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 28 1 
(integer) 0

getbit用于获取Bitmaps中某个偏移量的值

127.0.0.1:6379> getbit unique:users:20240719 1
(integer) 1
127.0.0.1:6379> getbit unique:users:20240719 2
(integer) 0

BITCOUNT:这个命令用于统计字符串被设置为1的bit数。一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,start、end 是指bit组的字节的下标数,二者皆包含。

127.0.0.1:6379> BITCOUNT unique:user:20240719 
(integer) 0
127.0.0.1:6379> BITCOUNT unique:users:20240719 
(integer) 5

测试一周上班情况

127.0.0.1:6379> SETBIT weekwork 1 1
(integer) 0
127.0.0.1:6379> SETBIT weekwork 2 1
(integer) 0
127.0.0.1:6379> SETBIT weekwork 3 1
(integer) 0
127.0.0.1:6379> SETBIT weekwork 4 1
(integer) 0
127.0.0.1:6379> SETBIT weekwork 5 1
(integer) 0
127.0.0.1:6379> SETBIT weekwork 6 1
(integer) 0
127.0.0.1:6379> BITCOUNT weekwork 
(integer) 6
127.0.0.1:6379> BITCOUNT weekwork 1 5 bit
(integer) 5
127.0.0.1:6379> BITCOUNT weekwork 3 7 bit
(integer) 4

bitop:这个命令是一个复合操作, 它可以做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中。

127.0.0.1:6379> setbit eight 3 1
(integer) 0
127.0.0.1:6379> setbit ten 1 1
(integer) 0
127.0.0.1:6379> setbit ten 3 1
(integer) 0
127.0.0.1:6379> BITOP and ten eight
(integer) 1
127.0.0.1:6379> BITOP and result  ten eight
(integer) 1
127.0.0.1:6379> getbit result 3
(integer) 1
127.0.0.1:6379> getbit result 2
(integer) 0
127.0.0.1:6379> getbit result 1
(integer) 0
127.0.0.1:6379> BITOP or result2  ten eight
(integer) 1
127.0.0.1:6379> getbit result2 1
(integer) 0
127.0.0.1:6379> getbit ten 1
(integer) 0
127.0.0.1:6379> setbit ten 1 1
(integer) 0
127.0.0.1:6379> BITOP or result2  ten eight
(integer) 1
127.0.0.1:6379> getbit result2 1
(integer) 1
127.0.0.1:6379> getbit result2 3
(integer) 1
127.0.0.1:6379> getbit result2 4
(integer) 0
127.0.0.1:6379> getbit result2 2
(integer) 0
127.0.0.1:6379> BITOP not result3 eight
(integer) 1
127.0.0.1:6379> getbit result3 3
(integer) 0
127.0.0.1:6379> getbit result3 1
(integer) 1
127.0.0.1:6379> getbit result3 2
(integer) 1
127.0.0.1:6379> getbit result3 0
(integer) 1
127.0.0.1:6379> getbit result3 8
(integer) 0
127.0.0.1:6379> BITOP xor result4 eight ten
(integer) 1
127.0.0.1:6379> GETBIT result4 4
(integer) 0
127.0.0.1:6379> GETBIT result4 3
(integer) 0
127.0.0.1:6379> GETBIT result4 2
(integer) 0
127.0.0.1:6379> GETBIT result4 1
(integer) 1

测试这两天都访问过网站的用户的数量

127.0.0.1:6379> setbit unique:users:20240719 2 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 10 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 15 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 19 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240719 20 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 1 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 2 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 10 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 15 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 19 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20240718 20 1
(integer) 0
127.0.0.1:6379> BITCOUNT unique:users:20240718
(integer) 6
127.0.0.1:6379> BITCOUNT unique:users:20240719
(integer) 10

127.0.0.1:6379> BITOP and result5 unique:users:20240718 unique:users:20240719
(integer) 4
127.0.0.1:6379> BITCOUNT result5
(integer) 6
4.HyperLogLog
  • 解决基数问题(像UV(UniqueVisitor,独立访客)、独立IP数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题)
 什么是基数?
 比如数据集 {1, 3, 5, 7, 5, 7, 8},那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

解决基数问题有很多种方案:

1)数据存储在MySQL表中,使用distinct count计算不重复个数

2)使用Redis提供的hash、set、bitmaps等数据结构来处理

以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。

为了能够降低一定的精度来平衡存储空间,Redis推出了HyperLogLog。

相关命令
添加指定元素到 HyperLogLog 中
127.0.0.1:6379> PFADD myhyper 1 1 2 2 3 3 4 4 5 5 6 6 7 7
(integer) 1
127.0.0.1:6379> PFADD myhyper2 8 8 9 9 10 10 11 11 12 13 14
(integer) 1

返回给定 HyperLogLog 的基数估算值
127.0.0.1:6379> PFCOUNT myhyper
(integer) 7
127.0.0.1:6379> PFCOUNT myhyper2
(integer) 7

将多个 HyperLogLog 合并为一个 HyperLogLog
127.0.0.1:6379> PFMERGE myhyper3 myhyper myhyper2
OK
127.0.0.1:6379> PFCOUNT myhyper3
(integer) 14
5.Geospatial
  • Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。
添加数据
127.0.0.1:6379> GEOADD china:city 121.47 31.32 shanghai 108.94 34.26 xian
(integer) 2
127.0.0.1:6379> GEOADD china:city 113.62 34.74  zhengzhou 117.22 31.82 hefei
(integer) 2
127.0.0.1:6379> GEOADD china:city 118.79 32.06  nanjing 114.30 30.59 wuhan
(integer) 2
127.0.0.1:6379> GEOADD china:city 120.15 30.27  hangzhou 115.49 28.70 nanchang
(integer) 2
127.0.0.1:6379> GEOADD china:city 106.55 29.56 chongqing
(integer) 1

查看城市信息
127.0.0.1:6379> GEOPOS china:city shanghai
1) 1) "121.47000163793563843"
   2) "31.3199993839624824"
输出两城市之间直线距离
127.0.0.1:6379> GEODIST china:city shanghai xian km
"1215.4403"

以哈希值输出
127.0.0.1:6379> GEOHASH china:city shanghai
1) "wtw6hjeu0p0"
127.0.0.1:6379> GEOHASH china:city xian
1) "wqj6yuzdvy0"

输出某一经纬度范围内的城市
127.0.0.1:6379> GEORADIUS china:city 108.94 34.26 1000 km
1) "xian"
2) "chongqing"
3) "zhengzhou"
4) "nanjing"
5) "nanchang"
6) "wuhan"
7) "hefei"
;