redis从零开始(2)----基本类型set/zset/bitmap

接上文

Set
简介
  • redis集合(set)类型和list列表类型类似,都可以用来存储多个字符串元素的集合。
  • 但是和list不同的是set集合当中不允许重复的元素。而且set集合当中元素是没有顺序的,不存在元素下标。
  • redis的set类型是使用哈希表构造的,因此复杂度是O(1),它支持集合内的增删改查,并且支持多个集合间的交集、并集、差集操作。可以利用这些集合操作,解决程序开发过程当中很多数据集合间的问题。
  • set的底层结构相对复杂,使用了intset和hashtable两种数据结构存储,intset可以理解为数组。
底层实现
  • 如果set中的元素个数小于512,redis使用整数集合来存储set
  • 如果set中的元素个数大于512,redis使用哈希表存储set
使用
// 向集合中添加成员
127.0.0.1:6379> sadd me qian male 23
(integer) 3
// 展示集合中的所有成员
127.0.0.1:6379> smembers me
1) "male"
2) "23"
3) "qian"
// 获取集合成员个数
127.0.0.1:6379> scard me
(integer) 3
// 查询某元素是不是集合的成员
127.0.0.1:6379> sismember me female
(integer) 0
// 移除一个随机元素
127.0.0.1:6379> spop me
"qian"
// 返回随机的几个元素
127.0.0.1:6379> srandmember me 2
1) "male"
2) "23"
127.0.0.1:6379> srandmember me 2
1) "23"
2) "qian"
// 移除集合中的若干个成员
127.0.0.1:6379> srem me 23
(integer) 1
127.0.0.1:6379> smembers me
1) "male"
2) "qian"
使用场景

set的特点是无序、不可重复、支持交集并集差集等操作。
但是要注意,set的交并差的计算复杂度较高,数据量大的情况下,如果直接计算,会导致redis阻塞。通常情况下为避免redis主库因执行该类计算而阻塞,会将数据返回客户端,由客户端来进行统计;或者让从库完成计算
1、点赞
set类型可以实现让用户只能为一篇文章点一次赞。

# uid:1 用户对文章 article:1 点赞
> SADD article:1 uid:1
(integer) 1
# uid:2 用户对文章 article:1 点赞
> SADD article:1 uid:2
(integer) 1
# uid:3 用户对文章 article:1 点赞
> SADD article:1 uid:3
(integer) 1
# uid:1 用户取消点赞
> SREM article:1 uid:1
(integer) 1
# 获取 article:1 文章所有点赞用户 :
> SMEMBERS article:1
1) "uid:3"
2) "uid:2"
# 获取 article:1 文章的点赞用户数量:
> SCARD article:1
(integer) 2
# 判断用户 uid:1 是否对文章 article:1 点赞了:
> SISMEMBER article:1 uid:1
(integer) 0  # 返回0说明没点赞,返回1则说明点赞了

2、共同关注
set支持交集运算,所以可以用来计算共同关注的好友

# uid:1 用户关注公众号 id 为 5、6、7、8、9
> SADD uid:1 5 6 7 8 9
(integer) 5
# uid:2  用户关注公众号 id 为 7、8、9、10、11
> SADD uid:2 7 8 9 10 11
(integer) 5
# 获取 uid:1 和 uid:2 共同关注的公众号:
> SINTER uid:1 uid:2
1) "7"
2) "8"
3) "9"
# 给 uid:2 推荐 uid:1 关注的公众号:
> SDIFF uid:1 uid:2
1) "5"
2) "6"
# 验证某个公众号是否同时被 uid:1 或 uid:2 关注:
> SISMEMBER uid:1 5
(integer) 1 # 返回0,说明关注了
> SISMEMBER uid:2 5
(integer) 0 # 返回0,说明没关注

3、抽奖
set可以保证一个用户只能中一次奖

# 将所有成员加入set
>SADD lucky Tom Jerry John Sean Marry Lindy Sary Mark
(integer) 5

如果允许重复中奖,可以使用srandmember
如果不允许重复中奖,可以使用spop

zset
简介
  • redis有序集合也是集合类型的一部分,所以它保留了集合中元素不能重复的特性,但是不同的是,有序集合给每个元素多设置了一个分数,利用该分数作为排序的依据
底层实现
  • 如果zset中元素个数小于128个,并且每个元素都小于64byte,redis使用listpack实现
  • 否则,使用跳表来实现
使用
// 向有序集合中添加成员
127.0.0.1:6379> zadd me 1 qian 11 male 21 "23"
(integer) 3
// 获取该key集合的成员数
127.0.0.1:6379> zcard me
(integer) 3
// 计算有序集合中指定区间分数的成员数量
127.0.0.1:6379> zcount me 5 15
(integer) 1
// 查看指定区间内成员并可查看其权重
127.0.0.1:6379> zrange me 0 30 withscores
1) "qian"
2) "1"
3) "male"
4) "11"
5) "23"
6) "21"
// 返回集合中指定成员的索引
127.0.0.1:6379> zrank me qian
(integer) 0
// 返回指定成员的分数值
127.0.0.1:6379> zscore me 23
"21"
// 按分数排序返回
127.0.0.1:6379> zrangebyscore me 0 100
1) "qian"
2) "male"
3) "23"
127.0.0.1:6379> zrangebyscore me 0 100 withscores
1) "qian"
2) "1"
3) "male"
4) "11"
5) "23"
6) "21"
// 删除某个元素
127.0.0.1:6379> zrem me 23
(integer) 1
// 返回成员的分数值
127.0.0.1:6379> zscore me qian
"1"
// 返回该元素的排名,按从大到小排序
127.0.0.1:6379> zrevrank me qian
(integer) 1
127.0.0.1:6379> zrevrank me male
(integer) 0
使用场景

面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Sorted Set。
1、排行榜

# arcticle:1 文章获得了200个赞
> ZADD user:qian:ranking 200 arcticle:1
(integer) 1
# arcticle:2 文章获得了40个赞
> ZADD user:qian:ranking 40 arcticle:2
(integer) 1
# arcticle:3 文章获得了100个赞
> ZADD user:qian:ranking 100 arcticle:3
(integer) 1
# 文章 arcticle:4 新增一个赞
> ZINCRBY user:qian:ranking 1 arcticle:3
"101"
# 查看某文章的赞数
> ZSCORE user:qian:ranking arcticle:3
"101"
# 获取点赞数最多的2篇文章
# WITHSCORES 表示把 score 也显示出来
> ZREVRANGE user:qian:ranking 0 2 WITHSCORES
1) "arcticle:1"
2) "200"
3) "arcticle:3"
4) "101"
# 返回150-250赞的文章
> ZRANGEBYSCORE user:xiaolin:ranking 150 250 WITHSCORES
1) "arcticle:1"
2) "200"

2、电话、姓名排序
zrangebylex和zrevrangebylex只能用在分数一致的集合中

# 将电话号码存储到zset中
> ZADD phone 0 13100111100 0 13110114300 0 13132110901 
(integer) 3
> ZADD phone 0 13200111100 0 13210414300 0 13252110901 
(integer) 3
> ZADD phone 0 13300111100 0 13310414300 0 13352110901 
(integer) 3
# 获取所有号码:
> ZRANGEBYLEX phone - +
1) "13100111100"
2) "13110114300"
3) "13132110901"
4) "13200111100"
5) "13210414300"
6) "13252110901"
7) "13300111100"
8) "13310414300"
9) "13352110901"
# 获取 132 号段的号码:
> ZRANGEBYLEX phone [132 (133
1) "13200111100"
2) "13210414300"
3) "13252110901"
# 获取132、133号段的号码:
> ZRANGEBYLEX phone [132 (134
1) "13200111100"
2) "13210414300"
3) "13252110901"
4) "13300111100"
5) "13310414300"
6) "13352110901"
# 将联系人名字加到zset中
> zadd names 0 Toumas 0 Jake 0 Bluetuo 0 Gaodeng 0 Aimini 0 Aidehua 
(integer) 6
# 获取所有人的名字:
> ZRANGEBYLEX names - +
1) "Aidehua"
2) "Aimini"
3) "Bluetuo"
4) "Gaodeng"
5) "Jake"
6) "Toumas"
# 获取名字中大写字母A开头的所有人:
> ZRANGEBYLEX names [A (B
1) "Aidehua"
2) "Aimini"
# 获取名字中大写字母 C 到 Z 的所有人:
> ZRANGEBYLEX names [C [Z
1) "Gaodeng"
2) "Jake"
3) "Toumas"
bitmap
简介
  • bitmap即位图,存储一连串的0/1,可以以O(1)的时间复杂度访问和更改,特别适合一些数据量很大的二值统计的场景,节省很大空间
  • bitmap可以进行与、或、异或、去反的运算操作
底层实现

使用string保存

使用
# SETBIT key offset value
# 设置值,value = 0/1
127.0.0.1:6379> setbit me 1 1
(integer) 0
# 获取值
127.0.0.1:6379> getbit me 1
(integer) 1
# 获取从start到end之间的1的个数
127.0.0.1:6379> bitcount me 0 10
(integer) 2
# BITPOS KEY VALUE START END
# 获取key中从start到END第一次出现0或1的位置
# 序号是从0开始的
127.0.0.1:6379> setbit me 1 0
(integer) 1
127.0.0.1:6379> bitpos me 1 0 10
(integer) 2
# 运算操作:and/or/xor/not
# 如果字符串长度不相等,短的那个会被看成0,返回的字符串长度和最长的一致
# BITOP OP destkey key1 key2
# 除了not操作以外,其他操作都可以接受多于一个key运算
127.0.0.1:6379> setbit you 1 1
(integer) 0
127.0.0.1:6379> getbit you 1
(integer) 1
127.0.0.1:6379> bitop and you me
(integer) 1
127.0.0.1:6379> getbit you 1
(integer) 0
使用场景

1、签到统计
统计每个月的签到信息,只需要31bit就可以实现:

# 记录该用户 6 月 3 号已签到。
SETBIT uid:sign:100:202206 2 1
# 检查该用户 6 月 3 日是否签到。
GETBIT uid:sign:100:202206 2 
# 统计该用户在 6 月份的签到次数。
BITCOUNT uid:sign:100:202206
# 查询6月首次打卡时间,返回值从0开始,所以需要+1
BITPOS uid:sign:100:202206 1

2、判断用户登录态

# 用户已登录。
SETBIT login_status 10086 1
# 检查该用户是否登陆,返回值1表示已登录。
GETBIT login_status 10086
# 用户登出,将offset对应的value设置成 0。
SETBIT login_status 10086 0

3、连续打卡的用户数量
每天日期作为一个key,存储不同用户的打卡记录,对所有的日期做一个与运算,就可以知道这一段时间内都有打卡的用户数量。即使每天产生一个亿的数据,也只是占用11MB的内存。

# 与操作
BITOP AND destmap bitmap:01 bitmap:02 bitmap:03
# 统计 bit 位 =  1 的个数
BITCOUNT destmap

还可以给bitmap设置过期时间,删除过期数据,节省内存。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值