黑马点评—redis消息队列

为什么要是用redis消息队列?

1.之前使用JDK的阻塞队列完成异步下单,阻塞队列使用的时JDK内存,为队列长度设置了上限,若出现高并发的情况,无数的数据存入JDK内存,可能会导致内存溢出,就引发了内存限制问题

2.因为数据都存在与内存中,若内存宕机,则所有内存都会受到影响,用户已经完成了抢单操作,但内存中没有相关的订单信息。还有当从队列中取出数据,要完成相应的下单任务,出现了严重事故,导致任务丢失,队列中没有记录,就引发了数据安全问题。

消息队列(Message Queue)

字面上就是存放消息的队列,包含三个角色,最直白的理解:就是菜鸟驿站,决出了耦合,提升了消息传递、工作的效率

那么就有一个疑问,消息队列和阻塞队列有什么不一样吗,都是起到临时存放的作用:

1.消息队列不受JVM内存的限制 

2.消息队列不仅仅起到消息临时存储的作用,还未数据提供了安全性保障,提供持久化管理,不用担心出现重大事故时,数据丢失的问题。同时,在传递给消费者数据时,还会提供确认机制,确保消费者接收到消息,否则数据仍存在于队列中,直至至少一次的确定。

redis中的消息队列

list:模仿链表的阻塞队列

pubsub:发布订阅模式

stream: 更加完善

基于list结构模仿消息队列

基本结构:是一个双向链表,容易模拟出队列效果,链表的特点先进先出

队列时入口出口不再同一侧的,因此利用LPUSH和RPOP等来实现

注意的是,若队列中没有消息时,POP操作会返回null,而我们希望的是可以是阻塞式的,在有消息的时候再返回消息,因此可以使用B(block)RPOP和B(block)LPOP实现阻塞效果

创建两个redis连接,一个生产者,一个消费者

生产者:再l1中存入两个数据e1,e2

消费者:监听l1,先后拿到e1,e2,在输入BRPOP输出数据时,就处于阻塞状态直至有新的消息输入

总结

1.无法避免消息丢失:因为采取POP操作是直接移除remove消息

2.一对一:因为一个消费者拿走消息后,其他消费者就无法或者该消息

基于PubSub的消息队列

消费者订阅一或多个channel,生产者相对应channel发布消息后,所有订阅者都能收到消息,即一对多

相关语法

PubSub消息队列实现敏捷,虽然有多个消费者同时订阅一个生产者,但彼此订阅的队列不同。如,A订阅order.queue,B订阅一个order.*,那么生产者发送,publish order.q1 meg1,那就只有B能收到

总结

1.因为List队列本身就是数据结构,具有存储功能,所以可以做到数据持久化,而PubSub本身就只是一个发送消息模型,无法做到数据持久化

2.无法做到持久化,就无法避免数据的丢失

3.消息发送时需要生产者和消费者都同时在线,否则一方不再就无法传递消息,

4.安全问题较大

基于Stream的消息队列

stream是redis5.0新引入数据类型,注意是数据类型,所以本身就可以做到数据持久化,保障数据的安全,所以是功能非常完善的消息队列

发送消息命令;XADD,格式如下,发送成功后,返回的信息格式是”时间戳-递增数字“

读取消息之一:XREAD

可以发现,在不同的消费者上读取消息,消息并不会读一次就消失,证明了持久化管理

XREAD COUNT 1 BLOCK 10 STREAM s1 $:这代表了永久阻塞的阻塞模式,读取消息最大数量为1,s1队列的最新消息,可以看到下图进入了阻塞模式,等待新消息的出现

XADD s1 * k2 v2:表示创建名为s1的队列,冰箱其中发送消息内容为{k2=v2},并且使用redis自动生成id

这时,上面这个消费者在等待了14.53s之后收到了{k2=v2}的消息

Stream类型消息队列的XREAD命令特点

1.因为持久化管理,消息永久保存在队列中,所以消息可以回溯查询

2.可以设置BLOCK 0,表示永久阻塞进行阻塞读取,等待新消息的传递

3.因为$表示从最新消息开始,但只局限于最后一个的消息,如果一次发送了三条新消息,技能拿到最后一个消息,存在消息漏读的风险

基于Stream的消息队列-消费者组

消费者组:将多个消费者划分到一个组中,监听一个队列,有以下四个特点

1.消息分流:队列中的消息会分流给组内不同的消费者,即不同的消费者要去抢队列中大哥消息,而不是重复消费,从而加快处理消息的速度,避免了消息堆积

2.消息表示:消费者组会为维护一个表示,记录最后一个被处理的消息,即使发生了宕机等情况,还可以从标识之后读取消息,避免了消息漏读的情况

3.消息确认:消费者收到消息后,消息会维持pending(待处理)状态,并且存入pending-list,等待消费者处理完消息后,通过XACK来确认,标记消息已处理,才会从pending-list中移除,避免了消息丢失的情况

命令方法如下:

创建消费者组

下述命令表示:创建了队列名为s1,消费者组名称为g1,并且从队列中第一个消息开始读取

XGROUP CREATE s1 g1 0

从消费者组中读取消息下面这个命令表示:指定消费者组g1中消费者c1(若c1不存在,则自动创建)从队列s1中读取开始于下一个未消费,最大数量为1的消息,并且阻塞时间设置为2s,即监听2s以内最新的消息,没有退出监听

XREADGROUP GROUP g1 c1 COUNT 1 BLOCK 2000 STREAMS s1 >

可以看见,组g1中的消费者c1从队列s1中读取了{k1 = v1}的消息,并且将其标记成已消费,同样当组g1中的消费者c1再次从队列s1中读取消息是,只能读取下一个标识为未消费的消息,即{k2 = v2},并设置为已消费

{k3 = v3}与{k4 = v4}同理

但上述消息只是被标记为已消费,还没有用XACK确认消费,所以这5个消息仍存在在pending-list中 ,所以当用XACK确认队列s1中被g1消费者组消费的5个消息的ID,才能将5个消息从pending-list中移除

当读取完消息{k6 = v6}时,可以在pending-list中查看,下面命令表示查看pending-list中由消费者组g1消费的队列s1中的消息从最小到最大的10条消息,但结果只显示了消息{k6 = v6}的ID,因为前五条消息都被XACK确认移除了

XPENDING s1 g1 - + 10

最后,当队列s1中的消息都被XACK确认移除了,再去读取消息,会返回empty

java代码实现

 

STREAM类型消息队列的XREADGROUP命令特点

三种方法的对比总结

### 关于Redis黑马点评中的使用情况 Redis作为一种高性能的键值存储系统,在实际项目开发中被广泛应用于缓存消息队列以及分布式会话管理等领域。以下是基于提供的引用内容和专业知识,总结关于Redis黑马点评或其他类似场景下的具体应用。 #### 1. Redis调用方法 在Redis的实际操作过程中,可以通过`redis.call()`函数来执行各种命令。例如,可以利用该函数实现对数据的操作,其基本语法如下: ```lua local result = redis.call('GET', 'myKey') return result ``` 上述代码展示了如何通过Lua脚本调用Redis命令获取某个键对应的值[^1]。 #### 2. 数据库配置 当使用Spring框架集成Redis时,通常需要设置具体的数据库编号。根据引用说明,默认情况下Redis提供16个独立的数据库实例(编号范围为0至15)。开发者可以在配置文件中定义使用的数据库索引号,比如: ```yaml spring: redis: database: 1 # 使用第1号数据库 ``` 此配置项允许应用程序切换不同的命名空间以隔离不同业务的数据[^2]。 #### 3. 集群模式下Slot迁移过程验证 对于大规模生产环境而言,采用集群架构能够显著提升系统的可用性和扩展能力。如果发生slot转移,则需确认新旧节点间的数据分布状态是否正常更新完成。例如,假设部分槽位已成功迁移到目标节点上,那么可通过以下方式检验结果准确性: ```bash $ redis-cli -c -p 7001 > cluster nodes ``` 运行以上指令后应观察到预期的变化记录显示源节点上的相应slot已被清除而目的端新增加了这些条目[^3]。 #### 4. Session共享解决方案设计思路 考虑到多台Web服务器共存的情况下仍要保持用户的登录态一致性问题,此时可借助Redis统一保存各客户端关联的信息而非单纯依赖本地内存机制。“Code”字段可能因重复冲突风险而不适合作为主键标识符;因此建议结合唯一ID生成算法构建复合型结构体形式作为最终映射关系依据[^4]。 #### 5. 缓冲击穿防护措施探讨 为了避免突发流量冲击造成后台资源耗尽现象的发生,应当提前规划好应对策略。其中一种常见做法就是引入随机时间窗口偏移量或者渐进式淘汰比例控制手段延缓批量删除动作触发时机从而平滑负载曲线变化趋势[^5]。 ```python import time from random import randint def safe_delete(key, min_delay=1, max_delay=5): delay_time = randint(min_delay * 1000, max_delay * 1000)/1000 time.sleep(delay_time) # Simulate actual deletion logic here... print(f'Deleted {key} after waiting for {delay_time:.2f}s.') safe_delete('example_key') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值