当前位置: 首页 > article >正文

统计在线人数,百万数据表,查询很慢,如何统计,用php如何实现

        统计在线人数时,如果数据表有百万级别的数据,直接查询数据库会导致性能瓶颈,查询速度非常慢。对于这种大数据量的实时统计,使用数据库查询并不是最好的方案。相反,可以借助缓存或类似 Redis 的内存数据库来实现高效的在线人数统计。

常见的解决方案

1. 使用 Redis 实现在线人数统计

        Redis 是一个高性能的内存数据库,适合处理高并发请求和实时数据处理。通过 Redis 可以避免直接查询数据库的开销,下面是 Redis 实现在线人数统计的思路。

Redis 方案步骤
  • 每次用户登录时,将用户的 ID 或其他唯一标识保存到 Redis 的集合(SET 数据结构)中。
  • 用户离线时,从集合中移除该用户的 ID。
  • 使用 SCARD 命令统计集合中元素的个数,即为当前在线用户数。
具体实现
// Redis 连接配置
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 用户登录时
function userLogin($userId) {
    global $redis;
    // 使用集合保存在线用户,集合自动去重
    $redis->sAdd('online_users', $userId);
}

// 用户离线时
function userLogout($userId) {
    global $redis;
    // 从集合中移除用户
    $redis->sRem('online_users', $userId);
}

// 统计在线人数
function getOnlineUsersCount() {
    global $redis;
    // 获取集合的元素个数,即为在线人数
    return $redis->sCard('online_users');
}

// 示例调用
userLogin(1001); // 用户1001登录
userLogin(1002); // 用户1002登录
userLogout(1001); // 用户1001下线

// 获取在线人数
echo '当前在线人数: ' . getOnlineUsersCount();
Redis 的优点
  • 高性能:Redis 将数据保存在内存中,读写速度非常快。
  • 去重功能:Redis 的集合 SET 数据结构会自动去重,确保在线用户不会重复统计。
  • 并发处理:可以处理高并发场景,支持百万级别的在线用户管理。
2. 设置过期时间

        为了确保统计在线人数的准确性,你可以在 Redis 中为每个用户的会话设置一个过期时间。当用户长时间未活动时,会自动将其从在线用户集合中移除,避免统计冗余数据。

function userLoginWithExpiry($userId) {
    global $redis;
    // 设置每个用户的登录状态,并给它一个过期时间,比如 15 分钟
    $redis->setex('online_user_' . $userId, 900, time());  // 900 秒即 15 分钟
}

// 更新在线用户(每次有活动)
function updateUserActivity($userId) {
    global $redis;
    // 刷新过期时间
    $redis->expire('online_user_' . $userId, 900);  // 900 秒即 15 分钟
}

// 统计在线人数
function getOnlineUsersCountWithExpiry() {
    global $redis;
    // 获取所有键以 'online_user_' 开头的用户数据
    $keys = $redis->keys('online_user_*');
    return count($keys);
}
3. 使用 MySQL 配合缓存策略

如果你必须使用数据库来记录在线用户信息,可以采取以下优化方案:

  • 记录用户的最后活动时间:在用户表或一个专门的在线用户表中,记录用户的 user_idlast_active_time。然后只统计那些 last_active_time 在过去 15 分钟内的用户。
  • 查询优化:使用合适的索引和查询语句,避免全表扫描。
  • 缓存在线用户数:将统计结果缓存到 Redis 中,并定时从数据库中同步更新。

实现 MySQL + Redis 缓存

  1. 在用户表或在线用户表中记录最后活动时间。
  2. 定期从数据库中查询在线用户数,并将结果缓存到 Redis 中,设定缓存过期时间。
  3. 每次请求只查询 Redis,定期同步更新 Redis 的数据。
MySQL + Redis 代码示例
// 用户登录或有活动时,更新数据库中的最后活动时间
function updateLastActivity($userId) {
    $db = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
    $stmt = $db->prepare("UPDATE users SET last_active_time = NOW() WHERE id = :userId");
    $stmt->execute(['userId' => $userId]);
}

// 从数据库查询在线人数并缓存到 Redis
function updateOnlineUsersCountCache() {
    global $redis;
    $db = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
    
    // 查询过去 15 分钟内活动的用户数量
    $stmt = $db->query("SELECT COUNT(*) FROM users WHERE last_active_time > NOW() - INTERVAL 15 MINUTE");
    $onlineCount = $stmt->fetchColumn();
    
    // 将结果缓存到 Redis 中,缓存有效期为 60 秒
    $redis->setex('online_users_count', 60, $onlineCount);
    
    return $onlineCount;
}

// 获取在线人数
function getOnlineUsersCount() {
    global $redis;
    
    // 先从 Redis 获取缓存的在线人数
    $onlineCount = $redis->get('online_users_count');
    
    // 如果缓存不存在或过期,重新计算并更新缓存
    if ($onlineCount === false) {
        $onlineCount = updateOnlineUsersCountCache();
    }
    
    return $onlineCount;
}

总结

  • Redis 实现在线人数统计 是最常用的方案,适合高并发和大规模数据场景,能大大提高性能。
  • 结合数据库与缓存 的策略可以提供更准确的统计数据,但性能会受到一定影响。

http://www.kler.cn/news/302975.html

相关文章:

  • 产品经理如何转型为AI产品经理,如何理解AI产品工程化
  • 工厂安灯系统在优化生产流程上的优势
  • redis底层—数据结构
  • 动态规划问题
  • day48
  • 【hot100-java】【接雨水】
  • NCBI-get-spesis-ref-IDs_fast.py
  • AI与艺术的碰撞:当机器开始创作,创造力何在?
  • HarmonyOS4升级到Harmonyos Next(Api 11)系列教程
  • 音视频开发之旅(93)-图像超分增强之Real-ESRGAN
  • Vue 3 组合式 API
  • C++ | Leetcode C++题解之第393题UTF-8编码验证
  • RabbitMQ SDK 支持发布、消费,连接恢复,死信队列,多种使用场景
  • db.fsyncLock() 和 db.fsyncUnlock()
  • 前后端分离项目实现SSE
  • Redis Sentinel(哨兵)详解
  • 从JVM角度看对象创建过程和内存布局
  • 基于微信小程序+Java+SSM+Vue+MySQL的宿舍管理系统
  • F1C100S/F1C200S的资料来源说明
  • 快速切换淘宝最新镜像源npm
  • js 时间戳转日期格式
  • 【STM32笔记】STM32CubeIDE介绍
  • 漫谈设计模式 [18]:策略模式
  • ISO 21434与网络安全管理系统(CSMS)的协同作用
  • Java 入门指南:Java 并发编程 —— 同步工具类 Exchanger(交换器)
  • 学生请假管理系统
  • pytest钩子函数
  • Ubuntu22.04安装nginx
  • SpringBoot项目用Aspose-Words将Word转换为PDF文件正常显示中文的正确姿势
  • RP2040 C SDK clocks时钟源配置使用