前言

不知你大规模的用过Redis吗?还是仅仅作为缓存的工具了?在Redis中使用最多的就是集合了,举个例子,如下场景:

  1. 签到系统中,一天对应一系列的用户签到记录。

  2. 电商系统中,一个商品对应一系列的评论。

  3. 交友系统中,某个用户的一系列的好友。

Redis中集合的特点无非是一个Key对应一系列的数据, 但是数据的作用往往是为了统计的,比如:

  1. 交友系统中,需要统计每天的新增好友,以及双方的共同好友。

  2. 电商系统中,需要统计评论列表中的最新评论。

  3. 签到系统中,需要统计连续一个月的签到的用户数量。

大型互联网应用中,数据量是巨大的,少说百万,千万,甚至是一个亿,比如电商巨头淘宝,交友巨头微信、微博;办公巨头钉钉等,哪一个的用户不是上亿?

只有针对不同场景,选择合适的集合,统计才能更方便。

聚合统计

聚合统计指的是多个元素聚合的结果,比如统计多个集合的交集、并集、差集

在你需要对多个集合做聚合统计的时候,Set集合是个不错的选择,除了其中无重复的数据外,Redis还提供了对应的API

交集

在上述的例子中交友系统中统计双方的共同好友正是聚合统计中的交集

Redis中可以userid作为key,好友的userid作为value,如下图:

统计两个用户的共同好友只需要两个Set集合的交集,命令如下;

SINTERSTORE userid:new userid:20002 userid:20003

上述命令运行完成后,userid:new这个key中存储的将是userid:20002userid:20003两个集合的交集。

差集

举个例子:假设交友系统中需要统计每日新增的好友,此时就需要对临近两天的好友集合取差集了,比如2020/11/1日的好友是set12020/11/2日的好友是set2,此时只需要对set1set2做差集。

此时的结构应该如何设计呢?如下图:

userid:20201101这个key记录了userid用户的2020/11/1日的好友集合。

差集很简单,只需要执行SDIFFSTORE命令,如下:

SDIFFSTORE  user:new  userid:20201102 userid:20201101

执行完毕,此时的user:new这集合将是2020/11/2日新增的好友。

这里还有一个更贴切的例子,微博上有个可能认识的人功能,可以使用差集,即是你朋友的好友减去你们共同的好友即是可能认识的人。

并集

还是差集的那个例子,假设需要统计2020/11/012020/11/2总共新增的好友,此时只需要对这两日新增好友的集合做一个并集。命令如下:

SUNIONSTORE  userid:new userid:20201102 userid:20201101

此时新的集合userid:new则是两日新增的好友。

总结

Set集合的交差并的计算复杂度很高,如果数据量很大的情况下,可能会造成Redis的阻塞。

那么如何规避阻塞呢?建议如下:

  1. Redis集群中选一个从库专门负责聚合统计,这样就不会阻塞主库和其他的从库了

  2. 将数据交给客户端,由客户端进行聚合统计。

排序统计

在一些电商网站中可以看到商品的评论总是最新的在上面,这个是怎么做的呢?

最新评论列表包含了所有的评论,这就要集合对元素进行保序存储了。也就是说集合中的元素必须按序存储,称之为有序集合。

Redis中的四种集合中ListSorted Set属于有序集合。

但是ListSorted Set有何区别呢?到底使用哪一种呢?

List是按照元素进入顺序进行排序,而Sorted Set可以根据元素权重来排序。 比如可以根据元素插入集合的时间确定权值,先插入的元素权重小,后插入的元素权重大。

针对这一例子中,显然这两种都是能够满足要求的,List中分页查询命令LRANGESorted Set分页查询命令ZRANGEBYSCORE

但是就灵活性来说,List肯定不适合,List只能根据先后插入的顺序排序,但是大多数的场景中可能并不只是按照时间先后排序,可能还会按照一些特定的条件,此时Sorted Set就很合适了,只需要根据独有的算法生成相应的权重即可。

二值状态统计

二值状态指的是取值0或者1两种;在签到打卡的场景中,只需要记录签到(1)和未签到(0)两种状态,这就是典型的二值状态统计。

二值状态的统计可以使用Redis的扩展数据类型Bitmap,底层使用String类型实现,可以把它看成是一个bit数组。关于详细内容后续介绍.........

在签到统计中,01只占了一个bit,即使一年的签到数据才365个bit位。大大减少了存储空间。

Bitmap 提供了GETBIT/SETBIT 操作,使用一个偏移值 offset 对 bit 数组的某一个 bit 位进行读和写。不过,需要注意的是,Bitmap 的偏移量是从 0 开始算的,也就是说 offset 的最小值是 0。当使用 SETBIT 对一个 bit 位进行写操作时,这个 bit 位会被设置为 1。Bitmap 还提供了 BITCOUNT 操作,用来统计这个 bit 数组中所有1的个数。

键值如何设计呢?key可以是userid:yyyyMM,即是唯一id加上月份。假设员工id为10001,需要统计2020/11月份的签到打卡记录。

第一步,执行命令设置值,假设11月2号打卡了,命令如下:

SETBIT userid:10001:202011 1 1

BitMap是从下标0开始,因此2号则是下标为1,值设置为1则表示成功打卡了。

第二步,检查该用户11月2号是否打卡了,命令如下:

GETBIT userid:10001:202011 1

第三步,统计11月的打卡次数,命令如下:

BITCOUNT userid:10001:202011

那么问题来了,需要统计你这个签到系统中连续20天的签到打卡的用户的总数,如何处理呢?假设用户一个亿。

比如需要统计2020/11/012020/11/20天中连续打卡的人数,如何统计呢?

Bitmap中还支持同时对多个BitMap按位做异或操作,命令如下图:

思路来了,我们可以将每天的日期作为一个key,对应的BitMap存储一亿个用户当天的打卡情况。如下图:

此时我们只需要对2020/11/12020/11/20号的Bitmap做按位操作,最终得到的一个Bitmap中每个bit位置对应的值则代表连续20天打卡的情况,只有连续20天全部打卡,所在的bit位的值才为1。如下图:

最终可以使用BITCOUNT命令进行统计。

可以尝试计算下内存开销,每天使用 1 个 1 亿位的 Bitmap,大约占 12MB 的内存(10^8/8/1024/1024),20 天的 Bitmap 的内存开销约为 240MB,内存压力不算太大。不过,在实际应用时,最好对 Bitmap 设置过期时间,让 Redis 自动删除不再需要的签到记录,以节省内存开销。

如果涉及到二值状态,比如用户是否存在,签到打卡,商品是否存在等情况可以使用Bitmap,可以有效的节省内存空间。

基数统计

基数统计指统计一个集合中不重复元素的个数。

举个栗子:电商网站中通常需要统计每个网页的UV来确定权重,网页的UV肯定是需要去重的,在Redis类型中Set支持去重,第一时间肯定想到的是Set。

但是这里有一个问题,Set底层使用的是哈希表和整数数组,如果一个网页的UV达到千万级别的话(一个电商网站中何止一个页面),那么对于内存的消耗极大。

Redis提供了一个扩展类型HyperLogLog用于基数统计,计算2^64个元素大概只需要12KB的内存空间

是不是很心动?但是HyperLogLog是存在误差的,大概是在0.81%,如果需要精准的统计,还是需要使用Set。对于这种网页的UV来说,足够了。

在统计网页UV的时候,只需要将用户的唯一id存入HyperLogLog中,如下:

PFADD p1:uv 10001 10002 10003 10004

如果存在重复的元素,将会自动去重。

统计也很简单,使用PFCOUNT命令,如下:

PFCOUNT p1:uv

总结

本文介绍了统计的几种类型以及应该用什么集合存储,为了方便理解,作者将支持情况和优缺点汇总了一张表格,如下图:

SetSorted Set支持交集、并集的聚合运算,但是Sorted Set不支差集运算。

Bitmap也能对多个Bitmap做与、异或、或的聚合运算。

ListSortedSet都支持排序统计,但是List是根据元素先后插入顺序排序,Sorted Set支持权重,相对于List排序来说更加灵活。

对于二值状态统计,判断某个元素是否存在等场景,建议使用Bitmap,节省的内存空间。

对于基数统计,在大数据量、不要求精准的情况建议使用HyperLogLog,节省内存空间;对于精准的基数统计,最好还是使用Set集合。

给你一个亿的keys,Redis如何统计?相关推荐

  1. 价值一个亿的 AI 核心代码!开源了~

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~ 中文详细注释的开源项目 ...

  2. 个人okr_我如何通过个人OKR完成了一个亿的小目标

    Tita OKR软件 OKR工作法,不仅仅适用在企业管理或团队管理,对于个人的目标管理,也一样适用.更需要强调的,如果个人能通过OKR将自己的生活.职业目标管理起来,那么他的人生,将会变得无比强大! ...

  3. python抢红包脚本实例-这个Python脚本牛逼了,秒抢红包,再不怕错过一个亿了!...

    原标题:这个Python脚本牛逼了,秒抢红包,再不怕错过一个亿了! 曾经有一份"份额很足"的大红包,摆在我面前,我没有好好珍惜,如果上天再给我一次机会,我会对发红包的人说三个字:再 ...

  4. 一个亿的融资在一家芯片初创公司可以烧多久?

    01  前言 这个问题我分别问了几个芯片公司的创始人. 有说2年的(某中等规模电路,成熟制程的MCU芯片公司): 有说1年的(某AI算力芯片公司): 有说半年的(通讯SoC芯片,需要搭建百人团队的): ...

  5. 如果给你一个亿,你想去干嘛?各专业的科研狗是这样回答的……

    全世界只有3.14 % 的人关注了 爆炸吧知识 "如果现在给你一个亿, 你想去做什么?" 每天都被穷醒的小天一看到, 立马展开了丰富的想象力: 首先,当然少不了买买买, 将一切之前 ...

  6. 405 not allowed什么意思_二驴质问散打:为什么不救天道!面临一个亿赔款?次惑小仙女宣布与可乐分手!...

    次惑小仙女发作品表示:对不起让你们失望了,慢慢也学着长大了,懂得了很多,以前每天就知道天真傻笑的玩,后来懂得了努力和加油,但是很多东西并不是大家看到的那样背后的事情谁又能知道.都认为他对我很好,只有自 ...

  7. MaxCompute存储力持续升级,每年节省不止一个亿

    数据是开启全新洞察和机器智能创新的基础,拥有高性能.稳定.可扩展性强的存储能力和充沛的计算力,才能全面释放数据价值. 阿里巴巴大数据计算平台MaxCompute,作为阿里巴巴统一的计算平台,支持了整个 ...

  8. 装载鸿蒙系统,华为3-4月份将正式推送鸿蒙系统 第三方装载量也将达到一个亿...

    描述 作为华为消费者业务软件部总裁的王成录表示,鸿蒙系统不是安卓系统的拷贝,也不是苹果系统的拷贝,而是面向的整个物联网.预计在2021年,华为持有设备装机量将达到两个亿,或者是超过两个亿.还有很重要的 ...

  9. 天使轮融资一个亿的AI公司创新奇智,与徐工信息达成战略合作

    郭一璞 发自 凹非寺 量子位 出品 | 公众号 QbitAI 还记得那家天使轮就融了一个亿的AI公司创新奇智么? 继与永辉超市.原麦山丘达成合作后,今天,创新奇智与江苏徐工集团旗下的徐工信息在北京宣布 ...

最新文章

  1. 【 MATLAB 】impz函数介绍(数字滤波器的脉冲响应)
  2. linux c 文件指针 句柄(FILE*) 文件描述符(fd) 文件路径(filepath) 互相转换
  3. AlertDialog中的EditText不能输入
  4. u盘魔术师装linux,使用U盘魔术师安装Win7系统教程
  5. java spi技术,Java SPI机制
  6. Spotlights
  7. asp编程实例:通过表单创建word的一个例子
  8. 小米 MIUI 12 Magisk root教程(无需刷REC)
  9. HDU 6184 Counting Stars(分块)
  10. Python大作业-爬取成都链家租房信息(大作业)源码
  11. Class6 基于ECS和NAS搭建个人网盘
  12. STM32项目分享---MQTT智能门禁系统(含APP控制)
  13. Facebook APP 注册 登录
  14. 【Latex】如何用 latex 分双栏(分两列)
  15. Linux——SAMBA文件共享
  16. C语言编程编程思维培养的重要性,谈编程思维的培养
  17. VMware虚拟网络编辑器用法
  18. 【SQL】SQL语句积累
  19. ASO | APP推广之ASO优化中的九大奥义。
  20. python页面转图片_网页转图片_技术分享 - SegmentFault 思否

热门文章

  1. 如何快速清空 Linux 中的大文件
  2. 企业IT运维的“安全终结者”-堡垒机指南
  3. Python会消亡吗?
  4. mysql/mariadb命令如何获取帮助
  5. maple linux,Linux下面如何安装maple,mathematica,matlab这类软件?
  6. 种子文件多服务器,使用bitcomet制作torrent文件 [BitComet]
  7. python max()_Python Decimal max()用法及代码示例
  8. 我在兰亭这三年之跳出率升高门
  9. 为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器
  10. windows编辑好的python代码在linux的vim编辑,缩进问题