Redis限流实践:实现用户消息推送每天最多通知2次的功能

2023-08-28 14:11:35

在这里插入图片描述

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。
🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。
🏆本文已收录于PHP专栏:PHP进阶实战教程
🏆另有专栏PHP入门基础教程,希望各位大佬多多支持❤️。
🎉欢迎 👍点赞✍评论⭐收藏


🚀一、背景

在开发应用程序中,经常需要向用户推送消息通知,但是为了避免过多的打扰用户,我们希望限制每天最多通知2次。本篇博文将介绍如何使用 PHP 和 Redis 实现这一功能。

在这里插入图片描述

🚀二、准备工作

首先,我们需要准备好数据库和 Redis 服务。在 MySQL 数据库中创建一个 user_notifications 表, 包含以下字段:

  • id:主键自增长ID
  • user_id:用户ID
  • content:通知内容
  • created_at:记录创建时间

此外,还需要安装 Redis 扩展,在 PHP 中可以通过以下命令安装:

$ pecl install redis

常见的推送消息场景如下图。

在这里插入图片描述

🚀三、实现逻辑

🔎3.1 查询用户的已发送通知数量

在用户登录或接收新通知时,我们需要查询用户今天已发送的通知数量。我们可以利用 Redis 的 Sorted Set 数据结构来存储每个用户的通知记录。将用户ID作为 Sorted Set 的 key,通知的发送时间戳作为 score 值,这样就可以按照时间顺序存储用户的通知记录。

使用以下代码实现查询用户已发送通知数量的函数:

function getNotificationCount($userId) {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    $todayStart = strtotime('today'); // 当天开始的时间戳
    $todayEnd = strtotime('tomorrow') - 1; // 当天结束的时间戳

    $count = $redis->zcount('user_notifications:' . $userId, $todayStart, $todayEnd);

    return $count;
}

🔎3.2 发送通知

在发送通知之前,先检查用户已发送通知数量是否达到限制。如果已发送通知数量大于等于2,则不再发送新通知;否则,保存通知记录到数据库,并将通知记录的发送时间戳添加到 Redis Sorted Set 中。

使用以下代码实现发送通知的函数:

function sendNotification($userId, $content) {
    // 检查用户已发送通知数量
    $count = getNotificationCount($userId);
    if ($count >= 2) {
        return false;
    }

    // 保存通知记录到数据库
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
    $stmt = $pdo->prepare("INSERT INTO user_notifications (user_id, content, created_at) VALUES (?, ?, NOW())");
    $stmt->execute([$userId, $content]);

    // 将通知记录的发送时间戳添加到 Redis Sorted Set
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $redis->zadd('user_notifications:' . $userId, time(), $content);

    return true;
}

🔎3.3 获取用户通知列表

用户可以通过接口或页面查看自己的通知列表。我们可以从数据库中查询用户的通知记录,并按照发送时间倒序排列。

使用以下代码实现获取用户通知列表的函数:

function getNotificationList($userId) {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
    $stmt = $pdo->prepare("SELECT * FROM user_notifications WHERE user_id = ? ORDER BY created_at DESC");
    $stmt->execute([$userId]);

    $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);

    return $notifications;
}

🔎3.4 清理过期通知记录

为了避免 Redis Sorted Set 中存储的用户通知记录过多,我们可以定时清理过期的通知记录。通过设置 Redis 的过期时间来实现自动清理。例如,我们可以设置 Sorted Set 的过期时间为2天,在用户查询通知列表时,先删除过期的通知记录,再返回有效的通知列表。

function cleanExpiredNotifications($userId) {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    // 设置 Sorted Set 的过期时间为2天
    $expireTime = strtotime('2 days ago');
    $redis->expireAt('user_notifications:' . $userId, $expireTime);
}

🔎3.5 定时任务

为了每天凌晨清理用户的通知记录,我们可以使用 Linux 的 crontab 来定时执行清理任务。编辑 crontab 文件,添加如下代码:

0 0 * * * php /path/to/clean_expired_notifications.php

并创建 clean_expired_notifications.php 文件,内容如下:

<?php

require_once 'redis.php';

$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $pdo->prepare("SELECT DISTINCT user_id FROM user_notifications");
$stmt->execute();

$userIds = $stmt->fetchAll(PDO::FETCH_COLUMN);

foreach ($userIds as $userId) {
    cleanExpiredNotifications($userId);
}

🚀四、结语

通过 PHP 和 Redis 实现用户消息推送每天最多通知2次的功能,并结合定时任务清理过期通知记录,可以有效地避免过多地打扰用户。以上是基本实现逻辑和代码示例,你可以根据自己的实际需求进行修改和扩展,例如根据不同用户设置不同的通知限制次数等。

在这里插入图片描述

推荐您阅读本专栏其他内容,PHP进阶实战教程,相信不会让您失望。如果你对上面的功能有疑问,随时欢迎与我交流。

更多推荐

Qt+GDAL开发笔记(一):在windows系统mingw32编译GDAL库、搭建开发环境和基础Demo

若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/131931309红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…Qt开发

R语言绘制染色体变异位置分布图,RIdeogram包

变异位点染色体分布图今天分享的内容是通过RIdeogram包绘制染色体位点分布图,并介绍一种展示差异位点的方法。在遗传学研究中,通过测序等方式获得了基因组上某些位置的基因型信息。如下表,第一列是变异位点的ID,第二列是染色体,第三列是物理位置,最后两列是两个样品的基因型。这个文件通常有好几万行,要想快速从中获得有效信息

数字孪生行业相关政策梳理--智慧水利领域相关政策(可下载)

&nbsp;&nbsp;&nbsp;&nbsp;自2021年国家“十四五”规划纲要提出“探索建设数字孪生城市”以来,国家发展和改革委员会、工业和信息化部、住房和城乡建设部、水利部、农业农村部等部门纷纷出台政策,大力推动数字孪生在千行百业的落地发展。这些政策不仅为数字孪生的应用提供了广阔的舞台,也为相关产业的发展提供了坚

数据结构----链式栈

目录前言链式栈操作方式1.存储结构2.初始化3.创建节点4.判断是否满栈5.判断是否空栈6.入栈7.出栈8.获取栈顶元素9.遍历栈10.清空栈完整代码前言前面我们学习过了数组栈的相关方法,(链接:线性表-----栈(栈的初始化、建立、入栈、出栈、遍历、清空等操作)_灰勒塔德的博客-CSDN博客)那么今天我们就开始学习新

初识Java 9-1 内部类

目录创建内部类到外部类的链接使用.this和.new内部类和向上转型在方法和作用域中的内部类匿名内部类嵌套类接口中的类从多嵌套的内部类中访问外部人员本笔记参考自:《OnJava中文版》定义在另一个类中的类称为内部类。利用内部类,将逻辑上存在关联的类组织在一起,并且可以控制一个类在另一个类中的可见性。创建内部类创建内部类

企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理工程项目各模块及其功能点清单一、系统管理1、数据字典:实现对数据字典标签的增删改查操作2、编码管理:实现对系统编码的增删改查操作3、用户管理:管理和查看用户角

2023/9/14 -- C++/QT

作业:仿照Vector实现MyVector,最主要实现二倍扩容#include<iostream>usingnamespacestd;template<typenameT>classMyVector{private:T*data;size_tsize;size_tV_capacity;public://无参构造MyVe

想了解RPA看这篇就够了(全面又清晰)

想了解RPA看这篇就够了(全面又清晰)本文目录如下:(1)什么是RPA(2)RPA技术发展路线(3)RPA应用场景(4)RPA对比人工的优势(5)RPA的核心能力(1)什么是RPARPA(RoboticProcessAutomation,机器人流程自动化)是一种通过软件机器人模拟和执行规则化、重复性的任务来提高工作效率

大模型重构行业,百度网盘再度抢跑?

随着ChatGPT爆火出圈,AI大模型逐渐渗透到各个行业和领域,诸多大厂也纷纷发布了自己的大模型产品。而在国内AI大模型的市场上,百度的文心大模型无疑是其中较为有名的一个。于是,在国内大厂都在探索如何在大模型时代取得更多优势时,百度大模型也不再局限于某个特定领域,而是将目光放在了网盘应用上。自百度网盘经历“百盘大战”进

Vue3中watch用法

在Vue3中的组合式API中,watch的作用和Vue2中的watch作用是一样的,他们都是用来监听响应式状态发生变化的,当响应式状态发生变化时,都会触发一个回调函数。当需要在数据变化时执行异步或开销较大的操作时,computed是无法操作异步数据的,所以需要使用watch进行侦听。侦听器watch作用是侦听一个或多个

斗地主案例及一些实现规则

4.斗地主发牌4.1案例介绍按照斗地主的规则,完成洗牌发牌的动作。具体规则:使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。4.2案例分析准备牌:牌可以设计为一个ArrayList<String>,每个字符串为一张牌。每张牌由花色数字两部分组成,我们可以使用花色集合与数字集合嵌套迭

热文推荐