首页 > 其他分享 >场景题:如何实现亿级用户在线状态统计?

场景题:如何实现亿级用户在线状态统计?

时间:2025-01-14 16:35:18浏览次数:1  
标签:场景 在线 实现 用户 级用户 key 统计

近两年不知道大家有没有发现,现在的面试中《场景题》问的越来越多了,一方面是就业市场竞争者较多所带来的必然结果;另一方面是随着时间的推移,公司对于应聘者的技术要求也越来越高了,这时候只会八股文就不够了,你还得会更难的场景题才行。

所以,今天我们就来盘 Java 中的常见面试题《如何实现亿级用户在线状态统计?》,这个时候有人就会说了:“亿级?你确定你们公司有亿级用户同时在线的场景?”“我会亿级系统的设计还会来你们公司应聘吗?可笑”。

哈哈哈,确实如此,这些质疑都是合理的。但是话说回来,面试的难度本来就比实际工作的难度大很多;其次,你来应聘是想拿到高薪的 Offer,而不是和面试官干仗来的,对吧?所以,搞明白这道题的答案才是我们关注的重点。

1.亿级用户在线场景分析

例如,QQ 在线状态的统计功能就是亿级的,它的特征是:数据量大、内存占用高、实时性要求高,因此我们使用常规的解决方案是不能实现的。例如,在数据库中给每个用户中添加一个在线状态,上线设为 1,下线设为 0,通过统计状态为 1 的数据,获取在线人数。该方案无法承受大规模用户频繁上、下线操作,会给数据库带来巨大 IO 压力,且实时统计需不断刷新查询,易拖垮数据库性能,因此不可取。

2.解决方案

此时,我们的统计实现可分为以下两类:

  1. 基于总数的统计方案:设置一个总在线人数,上线 +1、下线 -1,从而实现上线总人数的统计。
    1. 优点:实现简单、效率高、内存占用少。
    2. 缺点:不精准,没办法精确的查找某些用户某个时刻的在线状态;且在异常退出应用的情况下,后续基于在线监测机制的重复下线判断很难实现。
  2. 基于具体用户详情的统计方案:将用户的标识(如 QQ 号)和上线状态都存储在集合中。
    1. 优点:统计精准,可以查找某些用户某个时刻的在线状态;且在异常退出应用的情况下,后续基于在线监测机制可以精准的实现下线用户的去重功能。
    2. 缺点:内存占用大、效率较低。

3.具体实现

3.1 基于总数的统计方案

基于总数的统计,我们可以使用以下两种方式:

  1. 基于 Redis 的 incr(+1)和 decr(-1)操作实现,如下图所示:

  1. 基于 Redis 的 HyperLogLog 实现,HyperLogLog (下文简称为 HLL) 是 Redis 2.8.9 版本添加的数据结构,它用于高性能的基数 (去重) 统计功能,它的缺点就是存在极低的误差率(0.81%)。它只需要 12KB 空间就能统计 2^64(约 18 亿)的数据。

此实现方案不能移除元素、存在误差,但空间占用率非常低。

3.2 基于用户的统计实现

基于用户标识(QQ)我们可以采用 Redis 中提供的 Bitmap(位数组)来实现,位数组结构如下:

其中每个下标就可以表示一个具体的数字,例如以上图片标识 1、3 数字存在,如果值为 0 表示不存在,这样的话 **10 亿数字占用的位数组空间位 10 亿 bit,也就是 1000000000/1024/1024/1024/8=0.116GB,可以看出它的空间占用量是非常小的。

用户上线时使用 SetBit 命令将对应位置设为 1 表示在线,下线时设为 0 。判断用户是否在线用 GetBit 命令,统计在线用户数用 BigCount 命令,具体操作命令如下图所示:

在 Spring Boot 项目中,我们可以使用 RedisTemplate 实现用户的上、下线设置,以及在线个数统计,具体实现代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class BitmapService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 设置Bitmap中的位
     * @param key 键
     * @param offset 偏移量
     * @param value 值(0或1)
     */
    public void setBit(String key, long offset, boolean value) {
        redisTemplate.opsForValue().setBit(key, offset, value);
    }

    /**
     * 获取Bitmap中的位
     * @param key 键
     * @param offset 偏移量
     * @return 位的值(0或1)
     */
    public boolean getBit(String key, long offset) {
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    /**
     * 计算Bitmap中值为1的位的数量
     * @param key 键
     * @return 值为1的位的数量
     */
    public Long bitCount(String key) {
        return redisTemplate.opsForValue().bitCount(key);
    }
}

小结

类似这样的场景题我收录和整理的题解答案还有很多,我把它制作成了一个专栏:《Java 常见场景题》,每个场景题都有详细的图解+代码案例解析。学会它可以帮助您解决面试中的大部分场景题,从此不再害怕场景题。查看和解锁所有《Java 常见场景题》扫描以下二维码即可:

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:场景题、并发编程、MySQL、Redis、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、JVM、设计模式、消息队列等模块。

标签:场景,在线,实现,用户,级用户,key,统计
From: https://www.cnblogs.com/vipstone/p/18671081

相关文章

  • 用RK3576核心板做人形机器人(一):RK3576 可以重点开发的方向和应用场景
    SAIL-RK3576核心板具备高性能的多核CPU、AINPU、丰富的外设接口以及较高的能效比,因而非常适合在人形机器人中实现多种关键功能。以下是一些在人形机器人中基于SAIL-RK3576核心板可以重点开发的方向和应用场景:视觉和感知系统人脸识别与跟踪:利用SAIL-RK3576核心板内置......
  • 组件导航守卫 常见的使用场景
    组件导航守卫通常用于处理组件级别的特定逻辑。以下是一些常见的使用场景:1、表单数据保存提醒:<template><div><form@submit.prevent="handleSubmit"><inputv-model="formData.name"/><!--其他表单字段--></form></div>&......
  • Pinia 替代 localStorage 的常规使用场景
    在现代Vue工程化项目中,通常推荐使用Pinia(或Vuex)来管理状态,而不是直接使用localStorage。我来解释下具体原因和使用方式:1、为什么使用Pinia替代localStorage://使用Pinia的优势:-状态集中管理,更容易维护-支持响应式-支持开发工具调试-支持TypeScript-可以配......
  • 应用场景——教育培训类二、学习路径规划助手开发实战(根据学生画像生成学习规划)
    通过大模型实现个性化学习路径规划与自适应教育在现代教育中,个性化学习正在逐步成为一种趋势。每个学生都有不同的学习需求、兴趣偏好和学习节奏。传统的“一刀切”教学模式很难满足每个学生的个性化需求。因此,如何为学生提供个性化的学习路径规划,帮助他们以最合适的方式进......
  • cliproxy海外 IP 的应用场景
    在当今全球化与数字化深度交织的时代,海外IP扮演着愈发关键的角色,其应用场景广泛地渗透到诸多领域,为个人、企业乃至科研机构开辟了新的发展路径。一、跨境电商运营对于跨境电商从业者而言,海外IP堪称业务拓展的得力助手。一方面,在店铺注册环节,部分海外电商平台基于地域限制......
  • Python编程与在线医疗平台数据挖掘与数据应用交互性研究
    一、引言1.1研究背景与意义在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的发展阶......
  • uniapp精仿微信UI,基于SumerUI和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视频
    uniapp精仿微信UI,基于SumerUI和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视频商城小工具等,朋友圈视频号即时聊天用于视频,商城,直播,聊天,等等场景,源码分享sumer-weixin介绍uniapp精仿微信UI界面,基于SumerUI3.0和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,......
  • 在线翻译工具-免费离线且好用的OCR
    点击上方蓝字关注我前言CopyTranslator一个特别好用的在线翻译小帮手。你只需要把文字复制进去,它就能自动帮你翻译,而且它还很聪明,能自己认出是哪种语言。这个工具能一边翻译一边自动处理你复制的文字,比如去掉多余的格式、自动显示或隐藏翻译结果,用起来特别顺手。它翻译得又快又......
  • C++中线程同步与互斥的4种方式介绍、对比、场景举例
    在C++中,当两个或更多的线程需要访问共享数据时,就会出现线程安全问题。这是因为,如果没有适当的同步机制,一个线程可能在另一个线程还没有完成对数据的修改就开始访问数据,这将导致数据的不一致性和程序的不可预测性。为了解决这个问题,C++提供了多种线程同步和互斥的机制。1.......
  • margin和padding使用的场景有哪些?
    在前端开发中,margin和padding是两个非常重要的CSS属性,它们分别用于控制元素外部和内部的间距。以下是margin和padding使用的具体场景:margin的使用场景:元素间距调整:当需要调整不同元素之间的距离时,可以使用margin。例如,设置两个段落之间的间距,使得页面布局更加清晰和美观。外部......