有赞一面:亿级用户DAU日活统计,有几种方案?

说在前面

在40岁老架构师 尼恩的读者社区(50+)中,最近有小伙伴拿到了一线互联网企业如极兔、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的面试题:

(1) 亿级用户场景,如何高性能统计日活?

(2) 如何实现亿级数据统计?

(3) 亿级用户日活统计,有几种方案?

等等等等…

高并发Redis的使用,是面试的重点和高频点。

尼恩作为技术中台、数据中台的架构师,致力于为大家研究出一个 3高架构知识宇宙, 所以,这里,带大家完成一个 亿级用户场景,如何高性能统计日活的架构分析和实操。

当然,作为一篇文章,仅仅是抛砖引玉,后面有机会,带大家做一下这个高质量的实操,并且指导大家写入简历。

让面试官爱到 “不能自已、口水直流”

也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典》V65版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从文末公号 【技术自由圈】取

文章目录

    • 说在前面
    • 业务场景分析
    • 亿级用户日活统计的存储架构
      • 方式1:通过 Redis 的 Set 集合来实现
      • 方式2:利用 Hash 类型实现
      • 方式3:利用 bitmap 实现
      • 方式4:利用 HyperLogLog 实现
    • 存储方案的问题分析
      • bigkey问题
      • 准确性问题
      • 方案选择
    • 回顾:什么是 Big Key?
      • Big Key的危害?
        • 1、阻塞请求
        • 2、内存增大
        • 3、阻塞网络
        • 4、影响主从同步、主从切换
    • HyperLogLog 原理和实操
      • 什么是 HyperLogLog?
      • HyperLogLog 与 bitmap 对比
        • 1、bitmap
        • 2、HyperLogLog
      • HyperLogLog 的使用场景
        • 大数据去重:
        • 用户活跃度统计:
        • 网站UV统计:
        • 社交网络推荐:
    • HyperLogLog 的相关命令
    • SpringBoot 实操:利用 HyperLogLog 实现网站UV统计
    • 超高并发异步架构
      • 队列缓存+批量写入的架构
    • 本文的版本计划和基础学习资料
    • 技术自由的实现路径 PDF:
        • 实现你的 架构自由:
        • 实现你的 响应式 自由:
        • 实现你的 spring cloud 自由:
        • 实现你的 linux 自由:
        • 实现你的 网络 自由:
        • 实现你的 分布式锁 自由:
        • 实现你的 王者组件 自由:
        • 实现你的 面试题 自由:

业务场景分析

什么是日活?

日活跃用户数量(Daily Active User,DAU)是用于反映网站、互联网应用或网络游戏的运营情况的统计指标。

日活跃用户数量通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户)。

受统计方式限制,互联网行业使用的日均活跃用户数指在统计周期(周/月)内,该App的每日活跃用户数的平均值。

亿级用户日活统计的存储架构

一个用户一天内多次访问一个网站只能算作一次,

怎么做存储架构呢?

大概有四种方案,可供技术选型:

  • 方式1:通过 Redis 的 Set 集合来实现。
  • 方式2:利用 Hash 类型实现
  • 方式3:利用 bitmap 实现
  • 方式4:利用 HyperLogLog 实现

方式1:通过 Redis 的 Set 集合来实现

将用户id 放到 Set 中,Set 的去重功能能保证不会重复记录同一个用户 ID。

一个ZSET类型的Key,它的成员数量为10000个

一般来说,这个ZSET就是bigkey

方式2:利用 Hash 类型实现

将用户 ID 作为 Hash 集合的 key,访问页面则执行 HSET 命令将 value 设置成 1。

即使用户重复访问,重复执行命令,也只会把这个 userId 的值设置成 “1"。

利用 HLEN 命令,统计 Hash 集合中的元素个数就是 UV。

一个Hash类型的Key,它的成员数量虽然只有1000个但这些成员的Value值总大小为100MB,

一般来说,这个 Hash 就是bigkey

方式3:利用 bitmap 实现

使用bitmap,记录用户id的访问,则把指定key的用户id对应的bit位标记为1,

统计 日活,就是就是指定key中1的个数。

显然这里是操作位,相比2中,一个字节为8位,估算一下占用空间:96M/8=12M,

1千万用户只要 1M多的空间,但是 1亿的用户需要12M的大小即可记录。

一个String类型的Key,它的值为5MB, 就是bigkey

bitmap 底层结构,和String类型是类似的。

方式4:利用 HyperLogLog 实现

在输入用户数量非常大时,计算基数所需要的空间总是固定的,并且是很小的,

每个hyperloglog键需要12kb内存可以计算2^64个不同元素的基数,

这和元素基数元素越多,耗费内存越多的集合形成鲜明对比,

但是hyperloglog只会根据元素来计算基数,不会存储元素本身,所以不能像其它类型一样返回各个元素

hyperloglog是概率算法,是牺牲准确率换区空间的,

对于对精度要求不高的情况下可以使用,因为概率算法本身不直接存储数据本身,能保证误差在一定范围内,又不占用空间,误差在0.81%左右

存储方案的问题分析

bigkey问题

方案1、方案2、方案3

准确性问题

方案4

方案选择

如果允许 存在 准确性问题,就使用 hyperloglog 存储架构

如果允许 存在 bigkey 问题,或者解决 bigkey 问题,就使用 方案3 存储架构

这里优先使用 hyperloglog 存储架构

回顾:什么是 Big Key?

通俗易懂的讲,Big Key就是某个key对应的value很大,占用的redis空间很大,本质上是大value问题。

key往往是程序可以自行设置的,value往往不受程序控制,因此可能导致value很大。

redis中这些Big Key对应的value值很大,在序列化/反序列化过程中花费的时间很大,因此当我们操作Big Key时,通常比较耗时,这就可能导致redis发生阻塞,从而降低redis性能。

BigKey指以Key的大小和Key中成员的数量来综合判定,用几个实际的例子对大Key的特征进行描述:

  • Key本身的数据量过大:一个String类型的Key,它的值为5MB
  • Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10000个
  • Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有1000个但这些成员的Value值总大小为100MB

Big Key的危害?

1、阻塞请求

Big Key对应的value较大,我们对其进行读写的时候,需要耗费较长的时间,这样就可能阻塞后续的请求处理。Redis的核心线程是单线程,单线程中请求任务的处理是串行的,前面的任务完不成,后面的任务就处理不了。

2、内存增大

读取Big Key耗费的内存比正常Key会有所增大,如果不断变大,可能会引发 OOM(内存溢出),或达到redis的最大内存maxmemory设置值引发写阻塞或重要Key被逐出。

3、阻塞网络

读取单value较大时会占用服务器网卡较多带宽,自身变慢的同时可能会影响该服务器上的其他Redis实例或者应用。

4、影响主从同步、主从切换

删除一个大Key造成主库较长时间的阻塞并引发同步中断或主从切换。

HyperLogLog 原理和实操

HyperLogLog 是大数据基数统计中的常见方法,无论是 Redis,Spark 还是 Flink 都提供了这个功能,其目的就是在一定的误差范围内,用最小的空间复杂度来估算一个数据流的基数。

这个最小的空间,小到什么程度呢?在 Redis 中实现的 HyperLogLog,只需要12K内存就能统计2^64个数据。不过有得必有失,HyperLogLog计数存在一定的误差,误差率整体较低。标准误差为 0.81% ,不到1%。当然,误差可以被设置辅助计算因子进行降低。

什么是 HyperLogLog?

HyperLogLog 是一种概率性数据结构,它是 LogLog 算法的升级版,作用是能够提供不精确的去重计数。HyperLogLog 下面简称为HLL,

Redis中的HLL是基于string结构实现的,单个HLL的内存永远小于16kb内存占用低的令人发指!作为代价,其测量结果是概率性的,有小于0.81%的误差

HLL是一种用于基数统计的算法,可以用来估计一个集合中不同元素的数量,而不需要存储这些元素本身。它可以高效地处理大规模的数据集,且占用的空间非常小,通常只需要几千个字节的存储空间就可以处理数十亿个元素。HLL算法的实现非常简单,可以使用位图和随机哈希函数来实现。

HLL算法的基本思想是利用随机哈希函数将元素映射到一个二进制字符串中,并根据哈希函数的结果将字符串分为若干个桶。在每个桶中,记录哈希值的最大前导零的数量。

对于一个大的数据集,可以对每个元素进行哈希并记录其对应桶的最大前导零的数量,然后计算所有桶的平均值,得到一个近似的基数估计值。

HLL算法的误差率可以控制在0.81/sqrt(m)以内,其中m是桶的数量。

因此,随着桶的数量增加,误差率将变得越来越小。

HLL算法的优点在于它具有极低的内存消耗和高效的计算速度,并且可以处理极大的数据集。

HyperLogLog 与 bitmap 对比

1、bitmap

优势是:非常均衡的特性,精准统计,可以得到每个统计对象的状态,秒出。

缺点是:当你的统计对象数量十分十分巨大时,可能会占用到一点存储空间,但也可在接受范围内。也可以通过分片,或者压缩的额外手段去解决。

注意:bitmap是精确的

2、HyperLogLog

优势是:

可以统计夸张到无法想象的数量,并且占用小的夸张的内存。

缺点是:

建立在牺牲准确率的基础上,而且无法得到每个统计对象的状态。

注意:HyperLogLog 不是精确的,误差在 1%左右

HyperLogLog 的使用场景

HyperLogLog算法主要用于基数统计场景,即需要快速统计一个数据集中不同元素的数量的场合。在实际应用中,HyperLogLog算法通常应用于以下场景:

大数据去重:

在大数据场景下,需要去重的数据量非常大,如果使用传统的去重算法,需要对每个元素进行存储和比对,时间和空间消耗非常高。HyperLogLog算法可以在占用极小的空间的情况下,高效地对大规模数据进行去重,提高去重效率。

用户活跃度统计:

在Web应用和移动应用中,需要对用户的活跃度进行统计。如果每个用户的活跃度都进行存储,需要消耗大量的存储空间。HyperLogLog算法可以在占用极小的空间的情况下,高效地统计活跃用户数量,提高统计效率。

网站UV统计:

在Web应用中,需要统计网站每日独立访客数量(即UV),但是由于数据量非常大,不能简单地直接计数,因为会导致内存不足。HyperLogLog算法可以在占用极小的空间的情况下,高效地对大规模的访问日志进行去重和统计,提高统计效率。

社交网络推荐:

在社交网络中,需要对用户的兴趣爱好进行统计,以便向用户推荐相关内容。HyperLogLog算法可以在占用极小的空间的情况下,高效地对用户行为进行去重和统计,提高推荐效率。

总之,HyperLogLog算法可以在需要高效处理大规模数据集的场景下发挥作用,适用于各种基数统计场合,可以提高数据处理效率,减少存储空间的消耗。

HyperLogLog 的相关命令

Redis提供了多个HyperLogLog相关的指令,包括以下几个:

  • PFADD:将一个或多个元素添加到指定的HyperLogLog数据结构中。
    语法:PFADD key element [element ...]
PFADD hll_key a b c
  • PFCOUNT:统计指定的HyperLogLog数据结构中不同元素的数量。
    语法:PFCOUNT key [key ...]
PFCOUNT hll_key
  • PFMERGE:将多个HyperLogLog数据结构合并为一个。
    语法:PFMERGE destkey sourcekey [sourcekey ...]
PFMERGE hll_key1 hll_key2 hll_key3

这些指令可以方便地对HyperLogLog数据结构进行添加、统计和合并操作,以满足各种基数统计场景的需求。

需要注意的是,HyperLogLog数据结构虽然占用空间非常小,但是在添加元素时需要进行哈希计算,因此添加元素的效率可能会受到影响。

因此,在java代码中,可以使用 队列缓存+ 批量写入的架构,进行批量添加, 尽量减少io时间。

在使用HyperLogLog数据结构时,需要根据实际情况评估其效率和误差率,以确定是否适合使用HyperLogLog算法。

SpringBoot 实操:利用 HyperLogLog 实现网站UV统计

利用HyperLogLog实现网站UV统计 ,代码如下:

测试如下:

误差计算:

1百万,减去 99 6723 ,大概在 4000左右,不到1%

超高并发异步架构

通过阻塞队列,使用队列缓存+批量写入的架构

队列缓存+批量写入的架构

这里用了阻塞队列,这个非常常用

具体的架构图如下:

所以阻塞队列的结构,以及底层原理,大家好好掌握

BlockingDeque<String> dauList = new LinkedBlockingDeque<>();

访问记录,直接进入到 阻塞队列,参考代码如下

异步写入的参考代码如下:

本文的版本计划和基础学习资料

尼恩作为技术中台、数据中台的架构师, 高并发是尼恩架构的重点, 所以,后面会大家从 架构到实操, 多个维度、多种场景的高并发实操。

而且尼恩指导简历的过程中,也指导过小伙伴写过 10Wqps 超高并发 网关、超高并发秒杀、超高并发物联网等等简历,里边涉及到大量的设计模式,

经过尼恩的指导之后,很多 小伙伴的简历,里边立马金光闪闪,并且顺利走上了架构师之路。

后面有机会,带大家做一下这个高质量的实操,并且指导大家写入简历。

所以,这个材料后面也会进行持续迭代,大家可以在文末找尼恩获取最新版本和技术交流。

尼恩编著的400页PDF电子书 《SpringCloud Alibaba 技术圣经》

尼恩编著的500页 PDF电子书 《Java高并发核心编程 卷2 加强版》,清华大学出版社出版

技术自由的实现路径 PDF:

实现你的 架构自由:

《吃透8图1模板,人人可以做架构》

《10Wqps评论中台,如何架构?B站是这么做的!!!》

《阿里二面:千万级、亿级数据,如何性能优化? 教科书级 答案来了》

《峰值21WQps、亿级DAU,小游戏《羊了个羊》是怎么架构的?》

《100亿级订单怎么调度,来一个大厂的极品方案》

《2个大厂 100亿级 超大流量 红包 架构方案》

… 更多架构文章,正在添加中

实现你的 响应式 自由:

《响应式圣经:10W字,实现Spring响应式编程自由》

这是老版本 《Flux、Mono、Reactor 实战(史上最全)》

实现你的 spring cloud 自由:

《Spring cloud Alibaba 学习圣经》

《分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)》

《一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)》

实现你的 linux 自由:

《Linux命令大全:2W多字,一次实现Linux自由》

实现你的 网络 自由:

《TCP协议详解 (史上最全)》

《网络三张表:ARP表, MAC表, 路由表,实现你的网络自由!!》

实现你的 分布式锁 自由:

《Redis分布式锁(图解 - 秒懂 - 史上最全)》

《Zookeeper 分布式锁 - 图解 - 秒懂》

实现你的 王者组件 自由:

《队列之王: Disruptor 原理、架构、源码 一文穿透》

《缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)》

《缓存之王:Caffeine 的使用(史上最全)》

《Java Agent 探针、字节码增强 ByteBuddy(史上最全)》

实现你的 面试题 自由:

4000页《尼恩Java面试宝典 》 40个专题

以上尼恩 架构笔记、面试题 的PDF文件更新,请到《技术自由圈》公号取↓↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/20044.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智见|中国能建中电工程罗必雄:数能融合为数字中国夯实底座

出品|网易科技《智见访谈》 作者&#xff5c;赵芙瑶 编辑&#xff5c;丁广胜 数字化浪潮的风&#xff0c;吹到了能源结构转型领域。 中国作为全球最大的能源生产国和消费国&#xff0c;正积极推动能源行业的数字化和智能化建设。数字化智能化升级在能源产业中被视为一项重要的战…

lambda处理异常四种方式

最近对接第三方呼叫系统&#xff0c;第三方SDK的所有方法里都有异常抛出&#xff0c;因为用到了lambda&#xff0c;所以异常处理还是很必要的。 本文主要用到了四种解决方案&#xff1a; 直接代码块处理自定义函数式接口&#xff0c;warp静态方法通过Either 类型包装通过Pair 类…

【Android】Exam5 ListView组件简单应用

Exam5 ListView组件简单应用 ListView组件简单应用 Exam5 ListView组件简单应用目的实验内容及实验步骤采用SimpleAdapter自定义Adapter运行及结果&#xff1a;实验总结 目的 掌握常用的UI布局及组件&#xff1b; 掌握使用Intent启动Activity的方法 掌握ListView组件的简单应用…

[离散数学] 函数

文章目录 函数判断函数的条件复合函数复合函数的性质 逆函数 函数 判断函数的条件 dom F A ⇔ \Leftrightarrow ⇔所有x 都有 F&#xff08;x&#xff09;与之对应 有唯一的与其对应 < x , y > ∈ f ∧ < y , z > ∈ f ⇒ y z <x,y>\in f \land <y,z…

无需繁琐手工操作,如何利用Web自动化测试元素定位做到快速高效的测试?

1、什么是Web自动化测试元素定位&#xff1f; 在Web自动化测试中&#xff0c;元素定位是非常重要的环节。因为我们需要找到需要进行操作的页面元素&#xff0c;例如按钮、输入框、下拉菜单等等。元素定位可以帮助我们在自动化测试中对这些元素进行操作&#xff0c;如点击、输入…

生物识别技术能否成为应对安全挑战的绝佳选择?

生物识别技术能否成为应对安全挑战的绝佳选择&#xff1f; 生物识别技术是利用人体固有的生理特征或行为特征来进行身份鉴别的一种技术&#xff0c;如指纹、人脸、声纹、虹膜等。1 生物识别技术具有不可撤销性、高度便利性和较低错误率等优势&#xff0c;在安全领域中也备受瞩目…

React动态路由配置

目录 项目初始化 模块创建 统一导出 全局模块配置选项 核心代码 使用及效果展示 博文适用于react-router v6及以上&#xff0c;其中还有很多值得改进的地方 最近学习react的过程中&#xff0c;思考怎样实现动态路由的配置(最终实现从页面配置最终动态从数据库加载上线模…

Stable Diffusion webui安装使用

参考&#xff1a; https://stability.ai/blog/stable-diffusion-public-release https://github.com/AUTOMATIC1111/stable-diffusion-webui 1、安装&#xff08;6g显存&#xff09; 1、conda创建python 3.10.6环境 conda create -n stable-diffusion pythonpython 3.10.6 也安…

中国南方Oracle用户组沙龙活动:大环境下的Oracle数据库的机遇与挑战

2023年03月12日(周日)在杭州索菲特西湖大酒店 (浙江省杭州市上城区西湖大道333 号)&#xff0c;中国南方Oracle用户组创始人之一&#xff1a;周亮&#xff08;zhou liang&#xff09;组织举办了主题为《大环境下的Oracle数据库的机遇与挑战》活动&#xff0c;大约有50名左右的人…

刷完这个笔记,17K不能再少了....

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;得准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿到理想…

马赛克处理

去取马赛克的网址&#xff1a; Redact • Photo - Free And Private Image Redaction In The Browser https://redact.photo/ REDACT.PHOTO &#xff08;照片马赛克处理在线工具&#xff09;简介 REDACT.PHOTO是一个照片马赛克处理在线工具&#xff0c;能够帮助我们非常方便…

ChatGPT使用体验

ChatGPT使用体验 前言 介绍ChatGPT 体验ChatGPT 菜谱 编程学习 出行导航 导游攻略 中英翻译 电影推荐 文章总结 总结 前言 最近关于ChatGPT的话题已经火爆了&#xff0c;我也观察和体验了一段时间。平心而论&#xff0c;这东西真的黑科技&#xff0c;大多行业都能通…

Windows10安装二进制Mysql-5.7.41和汉化

1.创建my.ini [mysqld] ##skip-grant-tables1 port 3306 basedirD:/webStudy/mysql-5.7.41 datadirE:/adata/mysqlData max_connections200 character-set-serverutf8 default-storage-engineINNODB sql_modeNO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [mysql] default-char…

论文解读|MetaAI图像分割基础模型SAM——解锁数字大脑“视觉区”

原创 | 文 BFT机器人 内容提要 事件背景: 2023年4月5日&#xff0c;MetaAI研究团队发布论文“分割一切”一《Segment Anything》并在官网发布了图像分割基础模型一Segment Anything Model(SAM)以及图像注释数据集Segment-Anything 1-Billion(SA-1B)。 论文核心观点 : 目…

Simulink 和 Gazebo联合仿真控制机械臂【Matlab R2022a】

逛 B 站&#xff0c;偶然发现一个 up 主上传的视频&#xff0c;可以实现 Simulink 中搭建机器人的控制器设计&#xff0c;对运行在虚拟机中 Gazebo 中的机械臂进行控制&#xff0c;链接&#xff1a;三关节机械臂Gazebo-Simulink联合仿真&#xff0c;这让我很感兴趣&#xff0c;…

60岁的机器视觉工程师,你还在敲代码?不想做机器视觉工程师,还可以做什么?机器视觉工程师职业生命线有多长​?

如果按程序员参加工作时间为22岁计算,平均退役年龄为35岁计算的话,程序员的职业寿命大概为14年。为什么程序员的职业生命线如此短暂呢?大致有以下几点—— 1、编程技术层出不穷,迭代速度非常快,这时候就需要我们不断的学习,不断地保持学习能力,当随着年龄的增长我们的学…

K8S系列之污点和容忍度详细分析

架构图 本篇文档主要介绍污点和容忍度的关系。 污点和容忍度 污点顾名思义就是脏的东西&#xff0c;给节点添加污点来限制pod调度到该节点上&#xff0c;如果pod可以容忍这种污点就可以被调度到有污点的节点上&#xff0c;如果不能容忍就不能被调度到该节点上。 污点作用于节…

Java版本企业电子招采系统源码——信息数智化招采系统

信息数智化招采系统 服务框架&#xff1a;Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构&#xff1a;VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术&#xff1a;Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、Stre…

Nginx实现负载均衡

张三开发了一个分享文学作品的网站&#xff0c;刚开始入驻的作者不多&#xff0c;可谓是人烟稀少。但入驻的作者们信念坚定&#xff0c;孜孜不倦地更新着自己的作品&#xff0c;功夫不负有心人&#xff0c;作品迎来了爆发式的阅读增长量&#xff0c;终于&#xff0c;大访问量使…

YooAsset | Unity资源管理方案

跳转官方仓库地址 一、说明 可空包、可首包DLC、可满足限制包体的需求、可玩家自己制作MOD上传到服务器、可分工程构建&#xff1b;支持内置渲染管线、可编程渲染管线&#xff1b;支持完整路径、可寻址资源定位&#xff1b;基于标签打包&#xff0c;自动分析冗余&#xff0c;基…