Redis各场景应用集合

应用场景

1、缓存(Cache),分布式缓存

在这里插入图片描述

有一些存储于数据库中的数据会被频繁访问,如果频繁的访问数据库,数据库负载会升高,同时由于数据库IO比较慢,应用程序的响应会比较差。此时,如果引入Redis来存储这些被频繁访问的数据,就可以有效的降低数据库的负载,同时提高应用程序的请求响应

2、会话存储(Session)

String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享

在这里插入图片描述

3、分布式锁(Distributed Lock)

在这里插入图片描述
这里主要是用Redis的原子操作命令:SETNX,该命令仅允许key不存在的时候才能设置key。

下图展示了一个简单用例。Client 1通过SETNX命令尝试创建lock 1234abcd。如果当前还没有这个key,那么将返回1。Client 1获得锁,就可以执行对共享资源的操作,操作完成之后,删除刚刚创建的lock(释放分布式锁)。如果Client 1在执行SETNX命令的时候,返回了0,说明有其他客户端占用了这key,那么等待一段时间(等其他节点释放)之后再尝试。

在这里插入图片描述
如今都是分布式的环境下java自带的单体锁已经不适用的。在 Redis 2.6.12 版本开始,string的set命令增加了一些参数:

EX:设置键的过期时间(单位为秒)

PX:设置键的过期时间(单位为毫秒)

NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value

XX :只在键已经存在时,才对键进行设置操作。

由于这个操作是原子性的,可以简单地以此实现一个分布式的锁,例如:

  set lock_key locked NX EX 1 

如果这个操作返回false,说明 key 的添加不成功,也就是当前有人在占用这把锁。而如果返回true,则说明得了锁,便可以继续进行操作,并且在操作后通过del命令释放掉锁。并且即使程序因为某些原因并没有释放锁,由于设置了过期时间,该锁也会在 1 秒后自动释放,不会影响到其他程序的运行。

5、计数器

int类型,incr方法

例如:文章的阅读量微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库

计数功能应该是最适合 Redis 的使用场景之一了,因为它高频率读写的特征可以完全发挥 Redis 作为内存数据库的高效。在 Redis 的数据结构中,stringhashsorted set都提供了incr方法用于原子性的自增操作,下面举例说明一下它们各自的使用场景:

1:如果应用需要显示每天的注册用户数,便可以使用string作为计数器,设定一个名为REGISTERED_COUNT_TODAY的 key,并在初始化时给它设置一个到凌晨 0 点的过期时间,每当用户注册成功后便使用incr命令使该 key 增长 1,同时当每天凌晨 0 点后,这个计数器都会因为 key 过期使值清零。

2: 每条微博都有点赞数、评论数、转发数和浏览数四条属性,这时用hash进行计数会更好,
将该计数器的 key 设为weibo:weibo_id,hash的 field 为like_number、comment_number、forward_number和view_number,在对应操作后通过hincrby使hash 中的 field 自增。

3: 如果应用有一个发帖排行榜的功能,便选择sorted set吧,将集合的 key 设为POST_RANK。当用户发帖后,使用zincrby将该用户 id 的 score 增长 1。sorted set会重新进行排序,用户所在排行榜的位置也就会得到实时的更新。

6、速率限制器(Rate Limiter)

也可以看作是 频率控制器,防止接口被刷导致服务器压力增大
由于Redis提供了计数器功能,所以我们可以通过该能力,配合超时时间,来实现速率限制器,最常见的场景就是服务端是用的请求限流。

在这里插入图片描述
根据用户id或者ip来作为key,使用INCR命令来记录用户的请求数量。然后将该请求数量与允许的请求上限数量做比较,只有低于限制的时候,才会执行请求处理。如果超过限制,就拒绝请求。

同时,请求数量的计数器需要设置一个时间窗口,比如:1分钟。也就是没过一分钟时间,计数器将被清零,重新计数。所以,当一个时间窗口中被限流之后,等到下一个时间窗口,就能恢复继续请求。以实现限制速率的效果。

在这里插入图片描述
除了时间窗算法之外,漏桶算法也能通过Redis来实现。

在这里插入图片描述

7、 位统计

String类型的bitcount(1.6.6的bitmap数据结构介绍)

set k1 a
setbit k1 6 1
setbit k1 7 0
get k1 
/* 6 7 代表的a的二进制位的修改
a 对应的ASCII码是97,转换为二进制数据是01100001
b 对应的ASCII码是98,转换为二进制数据是01100010因为bit非常节省空间(1 MB=8388608 bit),可以用来做大数据量的统计。
*/

8、 时间轴(Timeline)

list作为双向链表,不光可以作为队列使用。如果将它用作栈便可以成为一个公用的时间轴。当用户发完微博后,都通过lpush将它存放在一个 key 为LATEST_WEIBO的list中,之后便可以通过lrange取出当前最新的微博。

9、消息队列

Redis 中list的数据结构实现是双向链表,所以可以非常便捷的应用于消息队列(生产者 / 消费者模型)。消息的生产者只需要通过lpush将消息放入 list,消费者便可以通过rpop取出该消息,并且可以保证消息的有序性。

    如果需要实现带有优先级的消息队列也可以选择sorted set。而pub/sub功能也可以用作发布者 / 订阅者模型的消息。无论使用何种方式,由于 Redis 拥有持久化功能,也不需要担心由于服务器故障导致消息丢失的情况。

List提供了两个阻塞的弹出操作:blpop/brpop,可以设置超时时间

blpop:blpop key1 timeout 移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
brpop:brpop key1 timeout 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
上面的操作。其实就是java的阻塞队列。学习的东西越多。学习成本越低

队列:先进先除:rpush blpop,左头右尾,右边进入队列,左边出队列
栈:先进后出:rpush brpop

10、抽奖

利用set结构的无序性,通过 Spop( Redis Spop 命令用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。 ) 随机获得值

redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SPOP myset
"one"
redis> SMEMBERS myset
1) "three"
2) "two"
redis> SADD myset "four"
(integer) 1
redis> SADD myset "five"
(integer) 1
redis> SPOP myset 3
1) "five"
2) "four"
3) "two"
redis> SMEMBERS myset
1) "three"
redis> 
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);// 假设有一个奖品列表
$prizeListKey = 'prize_list';
$prizes = ['Prize1', 'Prize2', 'Prize3'];// 将奖品添加到列表中
foreach ($prizes as $prize) {$redis->rpush($prizeListKey, $prize);
}// 抽奖
$winner = $redis->lpop($prizeListKey);echo "Congratulations! The winner is: " . $winner;

实例2:
在ThinkPHP5.1中实现抽奖功能,可以通过Redis来管理奖池,以下是一个简单的示例:
首先,确保你的ThinkPHP5.1项目已经安装并配置了Redis扩展。
创建一个抽奖方法:

use think\facade\Redis;class LotteryService
{protected $redis;protected $key;public function __construct(){$this->redis = Redis::instance();$this->key = 'lottery_pool';}public function startLottery($participants, $probability){// 清空原有奖池$this->redis->delete($this->key);// 初始化奖池,参与者与其对应的概率foreach ($participants as $index => $participant) {$this->redis->zAdd($this->key, $probability[$index], $participant);}}public function lottery(){// 随机抽取一个参与者$participant = $this->redis->zRandMember($this->key, 1);return $participant ?: null;}
}

在你的控制器中调用抽奖方法:

public function draw()
{$lotteryService = new LotteryService();// 假设有一个参与者数组和对应概率数组//这里参与者也可以设置成奖品, 奖品1,奖品2,奖品3,下面是中奖概率$participants = ['user1', 'user2', 'user3'];$probability = [10, 20, 70]; // 概率需要加起来等于100// 初始化抽奖$lotteryService->startLottery($participants, $probability);// 进行抽奖$winner = $lotteryService->lottery();return json(['code' => 200, 'message' => 'Success', 'data' => $winner]);
}

这个示例中,我们使用了Redis的有序集合(ZSet)来存储参与者及其对应的概率,并且使用zRandMember命令来随机抽取参与者。这种方法可以简单快速地实现抽奖功能,并且可以通过Redis的持久化来保证抽奖的公平性和可靠性。

11、点赞、签到、打卡

假如上面的微博ID是t1001,用户ID是u3001

用 like:t1001 来维护 t1001 这条微博的所有点赞用户

点赞了这条微博:sadd like:t1001 u3001
取消点赞:srem like:t1001 u3001
是否点赞:sismember like:t1001 u3001
点赞的所有用户:smembers like:t1001
点赞数:scard like:t1001
是不是比数据库简单多了。

点赞

thinkphp5.1 redis 实现点赞
在ThinkPHP5.1中使用Redis实现点赞功能的基本步骤如下:

确保已经安装并配置好Redis服务器。

在ThinkPHP5.1项目中安装并配置Redis扩展,通常使用predis/predis包。

创建点赞的逻辑,比如用户A对帖子B点赞,可以在Redis中使用SET操作记录用户A对帖子B的点赞状态。

通过GET操作检查用户是否已点赞,以此来控制点赞按钮的显示状态。

实现取消点赞的逻辑,同样是通过DEL操作来删除用户A对帖子B的点赞记录。

以下是一个简单的示例代码:

// 引入Redis类
use Predis\Client as RedisClient;// 初始化Redis客户端
$redis = new RedisClient(['scheme' => 'tcp','host'   => '127.0.0.1','port'   => 6379,
]);// 用户A对帖子B点赞的操作
function addLike($userId, $postId) {global $redis;$key = "like:{$postId}:users";$redis->sAdd($key, $userId);
}// 检查用户A是否对帖子B点赞
function checkLike($userId, $postId) {global $redis;$key = "like:{$postId}:users";return $redis->sIsMember($key, $userId);
}// 用户A取消对帖子B的点赞
function removeLike($userId, $postId) {global $redis;$key = "like:{$postId}:users";$redis->sRem($key, $userId);
}// 示例:用户A点赞帖子B
addLike('userA', 'postB');// 示例:检查用户A是否点赞过帖子B
$isLiked = checkLike('userA', 'postB');// 示例:用户A取消点赞帖子B
if ($isLiked) {removeLike('userA', 'postB');
}

在这个例子中,我们使用了Redis的SET数据结构来记录每个帖子的点赞用户。sAdd方法用于添加用户到点赞集合,sIsMember检查用户是否在点赞集合中,而sRem则用于从点赞集合中移除用户。

请注意,这只是一个简单的示例,实际应用中你可能需要加入更多的安全检查和错误处理。同时,你还需要考虑如何存储点赞的数量等额外信息,以及如何处理并发点赞的情况。

签到实例

use think\Controller;
use think\Cache;class SignController extends Controller
{// 用户签到public function sign(){$userId = $this->request->param('user_id');$date = date('Ymd');$key = "sign:{$date}";// 使用bitmap记录签到用户$isSigned = Cache::bitmap('sign_users')->get($key, $userId);if ($isSigned) {return json(['code' => 1, 'msg' => '已签到']);} else {Cache::bitmap('sign_users')->set($key, $userId);return json(['code' => 0, 'msg' => '签到成功']);}}// 获取签到列表public function getSignList(){$date = date('Ymd');$key = "sign:{$date}";// 获取所有签到的用户列表$signList = Cache::bitmap('sign_users')->getAll($key);return json(['code' => 0, 'msg' => '成功', 'data' => $signList]);}
}

在这个示例中,我们定义了两个操作:sign用于用户签到,getSignList用于获取当日的签到列表。我们使用了Redis的bitmap数据结构来记录每个用户的签到状态。

确保你的config.php配置文件中已经配置了Redis,例如:

// redis配置文件
return ['default' => ['host'       => '127.0.0.1','port'       =>  6379,'password'   =>  '','select'     =>  0,'timeout'    =>  0,'expire'     =>  0,'persistent' => false,'prefix'     =>  '',],
];

这样,你就可以通过HTTP请求来实现用户的签到功能,并通过另一个请求获取签到列表。

12、商品标签

老规矩,用 tags:i5001 来维护商品所有的标签。

sadd tags:i5001 画面清晰细腻
sadd tags:i5001 真彩清晰显示屏
sadd tags:i5001 流程至极

13、好友关系、用户关注、推荐模型

对于一个用户 A,将它的关注和粉丝的用户 id 都存放在两个 set 中:

A:follow:存放 A 所有关注的用户 id

A:follower:存放 A 所有粉丝的用户 id

那么通过sinter命令便可以根据A:follow和A:follower的交集得到与 A 互相关注的用户。当 A 进入另一个用户 B 的主页后,A:follow和B:follow的交集便是 A 和 B 的共同专注,A:follow和B:follower的交集便是 A 关注的人也关注了 B。

好友关系,用户关注

// 假设已经有了Redis的实例 $redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);// 添加好友关系
function addFriend($redis, $user1, $user2) {// 使用集合(set)存储用户的好友$redis->sAdd("user:{$user1}:friends", $user2);$redis->sAdd("user:{$user2}:friends", $user1);
}// 获取好友列表
function getFriends($redis, $user) {// 获取用户的好友return $redis->sMembers("user:{$user}:friends");
}// 检查是否为好友
function isFriend($redis, $user1, $user2) {// 检查用户1是否是用户2的好友return $redis->sIsMember("user:{$user2}:friends", $user1);
}// 示例使用
addFriend($redis, 'user1', 'user2');
addFriend($redis, 'user2', 'user3');$friendsOfUser2 = getFriends($redis, 'user2');
print_r($friendsOfUser2); // 输出:Array ( [0] => user1 [1] => user3 )$isFriend = isFriend($redis, 'user1', 'user2');
echo $isFriend ? 'Yes' : 'No'; // 输出:Yes

14、排行榜(Rank/Leaderboard)

由于Redis提供了排序集合(Sorted Sets)的功能,所以很多游戏应用采用Redis来实现各种排行榜功能。

在这里插入图片描述
排序集合是唯一元素(比如:用户id)的集合,每个元素按分数排序,这样可以快速的按分数来检索元素
在这里插入图片描述

15 .倒排索引

倒排索引是构造搜索功能的最常见方式,在 Redis 中也可以通过set进行建立倒排索引,这里以简单的拼音 + 前缀搜索城市功能举例:

假设一个城市北京,通过拼音词库将北京转为beijing,再通过前缀分词将这两个词分为若干个前缀索引,有:北、北京、b、be…beijin和beijing。将这些索引分别作为set的 key(例如:index:北)并存储北京的 id,倒排索引便建立好了。接下来只需要在搜索时通过关键词取出对应的set并得到其中的 id 即可。

16 .显示最新的项目列表

比如说,我们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上我们有一个“显示全部”的链接,点击后就可以获得更多的评论。

每次新评论发表时,我们会将它的ID添加到一个Redis列表。可以限定列表的长度为5000

LPUSH latest.comments

在Redis中我们的最新ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在超出了这个范围的时候,才需要去访问数据库。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CTF题型 SSTI(2) Flask-SSTI典型题巩固

CTF题型 SSTI(2) Flask-SSTI典型题巩固 文章目录 CTF题型 SSTI(2) Flask-SSTI典型题巩固前记1.klf__sstiSSTI_Fuzz字典(网上收集自己补充) 2.klf_2数字问题如何解决了?|count |length都被禁? 3.klf_3 前记 从基础到自己构造paylo…

手机备忘录怎么导出到电脑,如何将手机备忘录导出到电脑

备忘录是我们日常生活和工作中常用的工具之一,我们可以在手机上轻松地记录重要的事务、想法和灵感。然而,在某些情况下,我们可能需要将手机备忘录导出到电脑进行更详细的整理和管理。那么,手机备忘录怎么导出到电脑,如…

【tls招新web部分题解】

emowebshell (php7.4.21版本漏洞) 非预期 题目提示webshell,就直接尝试一下常见的后门命名的规则 如 shell.php这里运气比较好,可以直接shell.php就出来 要是不想这样尝试的话,也可以直接dirsearch进行目录爆破 然后在phpinfo中直接搜素c…

企业信息安全怎么防护?迅软科技有方法!

一、企业信息防护策略 1、数据加密 使用迅软DSE加密系统,对敏感数据进行加密处理,确保数据在传输和存储过程中的安全性,防止数据泄露。 2、数据备份和恢复 定期备份重要数据,并确保可以在发生灾难性事件后迅速恢复业务运作。 …

力扣大厂热门面试算法题 43-45

43. 字符串相乘,44. 通配符匹配,45. 跳跃游戏 II,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.18 可通过leetcode所有测试用例。 目录 43. 字符串相乘 解题思路 完整代码 Python Java 44. 通配符…

计算机网络的分类

目录 <计算机网络的分类> 1.按网络覆盖范围分 1)个人区域网PAN 2)局域网 3)城域网 4)广域网 5)互联网 2.按传输介质分类 3.按网络传输技术分类 4.按网络的使用性质分类 <计算机网络的分类> 计算机网络分类的方法很多&#xff0c;可以从不同的角度观察网络…

如何使用IDE端通义灵码

如何使用IDE端通义灵码 第一步&#xff1a;安装IDE插件&#xff08; VS Code 和 JetBrains 二选一&#xff09; 如何下载安装VS Code &#xff1a;https://code.visualstudio.com 如何下载安装JetBrains&#xff1a;https://www.jetbrains.com/idea/download 第二步&#x…

Python 中异常处理介绍

异常处理是编程中一个非常重要的概念&#xff0c;它允许程序在出现错误时进行适当的处理&#xff0c;而不是直接崩溃。在 Python 中&#xff0c;异常处理是通过 try、except、finally 和 raise 语句来实现的。本文将详细介绍 Python 中的异常处理机制。 异常的基本概念 异常是在…

【人工智能】Gitee AI 天数智芯有奖体验开源AI模型,一定能有所收货,快来体验吧

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章。 这是《人工智能》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 目录 前言两大赛道天数智芯1.模型地址2.天数智芯专区3.选择模型4.模型详情页5.部署模型6.成功部署7.执行例子8.移除模型 千模盲…

PHP+MySQL开发组合:多端多商户DIY商城源码系统 带完整的搭建教程以及安装代码包

近年来&#xff0c;电商行业的迅猛发展&#xff0c;越来越多的商户开始寻求搭建自己的在线商城。然而&#xff0c;传统的商城系统往往功能单一&#xff0c;无法满足商户个性化、多样化的需求。同时&#xff0c;搭建一个功能完善的商城系统需要专业的技术团队和大量的时间成本&a…

JS精度计算的几种解决方法,1、转换成整数计算后再转换成小数,2、toFixed,3、math.js,4、bignumber.js,5、big.js

提示&#xff1a;学习express&#xff0c;搭建管理系统 文章目录 前言一、转换成整数计算后再转换成小数二、toFixed三、math.js四、bignumber.js五、big.js总结 前言 原始计算 let aNum 6.6 0.3;let bNum 6.6 - 0.2;let cNum 6.6 * 0.3;let dNum 6.6 / 0.2;console.log(…

【科普】气体检测仪使用时常见的几点误区,你占了几条?

气体检测仪的作用是检测环境中的气体浓度&#xff0c;及时发现并报警&#xff0c;以确保人员和设备的安全。气体检测仪在多个领域发挥着重要作用。 首先&#xff0c;它是对工业安全的重要保障。在生产现场&#xff0c;有毒、可燃或有爆炸性的气体泄漏可能导致严重的后果。气体检…

LabVIEW湍流等离子体束热效率优化

LabVIEW湍流等离子体束热效率优化 利用LabVIEW虚拟仪器技术&#xff0c;对湍流等离子体束的热效率进行了实时监测与优化&#xff0c;提高其在材料处理领域的应用效率和精度。通过双进气湍流等离子体发生器&#xff0c;实现了在不同工作参数下对热效率的实时在线监测&#xff0…

【Streamlit学习笔记】实现包含多个sheet的excel文件下载

1、什么是Streamlit Streamlit是一个免费的开源框架&#xff0c;用于快速构建和共享漂亮的机器学习和数据科学Web应用程序&#xff0c;官网链接 Streamlit Streamlit API链接 API reference 实际项目中遇到的问题&#xff1a;包含多个sheet的excel文件下载&#xff0c;下面将给…

【早鸟优惠|高录用|EI稳定检索】2024年虚拟现实、图像和信号处理国际学术会议(ICVISP 2024)诚邀投稿/参会!

【早鸟优惠|高录用|EI稳定检索】 2024年虚拟现实、图像和信号处理国际学术会议&#xff08;ICVISP 2024&#xff09;诚邀投稿/参会&#xff01; # 早鸟优惠 # 先投稿先送审 # #投稿免费参会、口头汇报及海报展示# 2024年虚拟现实、图像和信号处理国际学术会议&#xff08;I…

递推算法C++

所谓递推&#xff0c;是指从已知的初始条件出发&#xff0c;依据某种递推关系&#xff0c;逐次推出所要求的各中间结果及最后结果。其中初始条件或是问题本身已经给定&#xff0c;或是通过对问题的分析与化简后确定。从已知条件出发逐步推到问题结果&#xff0c;此种方法叫顺推…

【绘图案例-drawrect Objective-C语言】

一、接下来,我们来说drawrect:这个方法, 1.我们把之前的copy这个代码,复制粘贴一份,改个名字, 来个“05-drawrect”, 然后呢,关于这个drawrect: drawrect:啊,我们分几点来写, 1)首先:代码为什么要写在drawrect:当中, 2)rect参数的含义:也就是说,这个rect,…

Java毕业设计 基于springboot vue招聘网站 招聘系统

Java毕业设计 基于springboot vue招聘网站 招聘系统 springboot vue招聘网站 招聘系统 功能介绍 用户&#xff1a;登录 个人信息 简历信息 查看招聘信息 企业&#xff1a;登录 企业信息管理 发布招聘信息 职位招聘信息管理 简历信息管理 管理员&#xff1a;注册 登录 管理员…

第四百一十回

文章目录 1. 概念介绍2. 方法与细节2.1 获取方法2.2 使用细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取当前系统语言"相关的内容&#xff0c;本章回中将介绍如何获取时间戳.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

Windows Server 各版本搭建远程访问 / VPN 服务器实现 VPN 连接(03~19)

一、Windows Server 2003 开机后点击添加或删除角色 点击下一步 勾选自定义&#xff0c;点击下一步 点击 远程访问/VPN 服务器&#xff0c;点击下一步 点击下一步 点击下一步 勾选自定义&#xff0c;点击下一步 选择配置类型&#xff0c;点击下一步 点击完成 点击是 点击完成…