首页 » 网站推广 » phpredis存储list技巧_深入浅出Redis运用List实现消息队列

phpredis存储list技巧_深入浅出Redis运用List实现消息队列

访客 2024-12-13 0

扫一扫用手机浏览

文章目录 [+]

Broker: 做事器,作为Server供应核心做事,一样平常会包含多个Q。
Producer: 生产者,业务的发起方,卖力生产传输给broker,Consumer: 消费者,业务的处理方,卖力从broker获取消息并进行业务逻辑处理2.2 它办理了我们哪些问题

1、解耦: 比如说系统A会交给系统B去处理一些事情,但是A不想直接跟B有关联,避免耦合太强,就可以通过在A,B中间加入行列步队,A将要任务的事情交给行列步队 ,B订阅行列步队来实行任务。

这种场景很常见,比如A是订单系统,B是库存系统,可以通过行列步队把减少库存的事情交予B系统去处理。
如果A系统同时想让B、C、D…多个别系处理问题的时候,这种上风就更加明显了。

phpredis存储list技巧_深入浅出Redis运用List实现消息队列

2、有序性: 前辈先出事理,先来先处理,比如一个别系处理某件事须要很长一段韶光,但是在处理这件事情时候,有其他人也发出了要求,可以把要求放在队里,一个一个来处理。

phpredis存储list技巧_深入浅出Redis运用List实现消息队列
(图片来自网络侵删)

对数据的顺序性和同等性有强需求的业务,比如同一张银行卡同时被多个入口利用,须要担保入账出账的顺序性,避免涌现数据不一致。

3、路由: 按照不同的规则,将行列步队中发送到不同的其他行列步队中

通过行列步队将不同染色的要求发送到不同的做事去操作。
这样达成了流量按照业务拆分的目的。

4、异步处理: 处理一项任务的时候,有3个步骤A、B、C,须要先完成A操作, 然后做B、C 操作。
任务实行成功与否强依赖A的结果,但不依赖B、C 的结果。
如果我们利用串行的实行办法,那边那里理任务的周期就会变长,系统的整体吞吐能力也会降落(在同一个别系中做异步实在也是比较大的开销),以是利用行列步队是比较好的办法。

登录操作便是范例的场景:A:实行登录并得到结果、B:记录登录日志、C:将用户信息和Token写入缓存。
实行完A就可以从登录页跳到首页了,B、C让做事逐步去消化,不壅塞当前操作。

5、削峰: 将峰值期间的操作减少,比如A同学的全体操作流程包含12个步骤,后续的11个步骤是不须要强关注结果的数据,可以放在行列步队中。

详细可参考笔者这篇《MQ系列1:中间件实行事理》。

2.3 行列步队知足的业务特性2.3.1 有序性

正如上面提到的有序性一样,他能够担保按照生产的顺序进行处理和消费,避免被无序处理的情形发生。

2.3.2 去重

同样的,生产和消费的须要担保幂等性事理。
避免涌现重复实行的情形,而行列步队的去重机制,也须要确保避免被重复消费的问题。

2.3.3 的可靠性传输

行列步队的数据可以实现重试、持久化存储、去世信行列步队记录等,以避免无法成功通报所产生的不一致征象。
当做事器或者消费者规复康健的时候,可以连续读取消息进行处理,防止遗漏。

3 利用Redis的List实现行列步队

轻微学过数据构造都知道。
我们常常说Queue(行列步队),他的存储和利用规则是【前辈先出】,栈的存储和利用规则是【前辈后出】。
以是List实质上是一个线性的有序构造,也便是Queue的存储关系,它能够担保消费的有序性,按照顺序进行处理。

3.1 入列操作 LPUSH

即进行生产,入列操作语法:

LPUSH key element[element...]

如果key存在,Producer 通过 LPUSH 将插入该行列步队的头部;如果 key 不存在,则是先创建一个空行列步队,然后在进行数据插入。
下面举个例子,往行列步队中插入几个,然后得到的返回值是插入的个数。

> LPUSH msg_queue msg1 msg2 msg3(integer) 3

这边往 key 为 msg_queue 的行列步队中插入了三个 msg1、msg2、msg3。

3.2 出列操作 RPOP

即进行消费,消费的顺序是前辈先出(师长西席产先消费),出列利用的语法如下:

> RPOP msg_queue"msg1"> RPOP msg_queue"msg2"> RPOP msg_queue"msg3"> RPOP msg_queue(nil)

都消费完成之后,便是nil了。

3.3 消费及时性问题

不同于常规的MQ,具备订阅模式,消费者可以感知到有新的生产出来了,再进行消费。
List的问题在于,生产者向行列步队插入数据的时候,List 并不会主动关照消费者,以是消费者做不到及时消费。
为了担保消费的及时,可能须要做一个心跳包(1秒实行一次),不断地实行 RPOP 指令,当探测到有新就会取出进行消费,没有的时候就返回nil。
但是这种也存在明显的短板,便是不断的调用 RPOP 指令,占用 I/O 资源和CPU资源。

比较好的办理办法便是在行列步队为空行列步队的时候,停息读取,等有入列的时候,规复取数和消费的事情,这样也避免了无效的资源摧残浪费蹂躏。
Redis 供应了 BLPOP、BRPOP ,无数据的时候自动壅塞读取的命令,有新进入的时候,规复取数,如下:

# BRPOP key timeout BRPOP msg_queue 0

命令末了一个参数 timeout 是超时时间,单位是秒,如果 timeout 大于0,则到达指定的秒数纵然没有弹出成功也会返回,如果 timeout 的值为0,则会一贯壅塞等待其他连接向列表中插入元素, timeout 参数不许可为负数。

3.4 的重复消费问题

目前 List 没有纯幂等的鉴别能力,但是可以通过以下两种方法来实现:

List为每一条天生一个 Glocal ID,重复的Glocal ID 不进行重复消费。
Producer在生产的时候在中创建一个Glocal ID,当消费的时候把Glocal ID Record一下,后续的消费先判断再消费,避免重复消费同一个。
这样就担保了对付同一条,消费者始终只处理一次,结果始终保持同等。
3.5 的可靠性传输问题

可靠性传输我们在MQ篇章用了一整节来先容持久化存储、ACK 、二次记录保障。
这边我们也来看看Redis List中的可靠性传输的保障。
Redis中短缺了一个确认(ACK)的机制,如果消费数据的时候运行崩溃了,没有确认机制,很可能这条就被错过了,无法担保数据的同等性。
办理方案:Redis 供应了 RPOPLPUSH 指令,当List读取消息的时候,会同步的把该复制到其余一个List以作备份。
全体操作过程是具备原子性的,避免读取消息了,但是同步备份不堪利。

如果涌现处理涌现故障的情形,在故障回答之后,可以从备份的List中复制连续消费。
操作如下:

# 生产 msg1 msg2> LPUSH list_queue msg1 msg2 (integer) 2# 消费并同步到备份> RPOPLPUSH list_queue list_queue_bak"msg1"# 当发生故障的时候去消费备份的数据,可以消费到> RPOP list_queue_bak"msg1"

如果消费成功则把 list_queue_bak 删除即可,如果发生故障,则可以连续从 list_queue_bak 再次读取消息处理。

4 利用 Redission 实现行列步队能力

这边以Java SpringBoot为例子进行解释,可以参考官方文档。

4.1 添加maven依赖 和 配置基本连接

# maven信息<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.16.8</version></dependency>

# 基本配置spring: application: name: redission_test redis: host: x.x.x.x port: 6379 ssl: false password: xxxx.xxxx4.2 Java程序实现

@Slf4j@Servicepublic class RedisQueueService { @Autowired private RedissonClient redissonClient; private static final String REDIS_QUEUE = "listQueue"; / 生产 @param msg / public void msgProduce(String msg) { RBlockingDeque<String> blockDeque = redissonClient.getBlockingDeque(REDIS_QUEUE); try { blockDeque.putFirst(msg); // 写入行列步队头部 } catch (InterruptedException e) { log.error(e.printStackTrace()); } } / 消费:壅塞 / public void msgConsume() { RBlockingDeque<String> blockDeque = redissonClient.getBlockingDeque(REDIS_QUEUE);Boolen isCheck = true; while (isCheck) { try { String msg = blockDeque.takeLast(); // 从行列步队中取出 } catch (InterruptedException e) { log.error(e.printStackTrace()); } } }5 总结Redis中利用List 数据构造实现行列步队,知足FIFO的处理机制,利用 RPOP 进行读取。
利用 BRPOP 指令处理消费及时性问题利用 BRPOPLPUSH 命令进行数据备份,办理可靠性传输问题。
相对付专业的MQ,如kafka和RocketMQ,处理能力会差很多。
以是在在量不大的场景中利用,可以作为一个比较不错的行列步队办理方案。
但是过于繁芜的场景随意马虎造成堆积。

为帮助开拓者们提升口试技能、有机会入职BATJ等大厂公司,特殊制作了这个专辑——这一次整体放出。

大致内容包括了: Java 凑集、JVM、多线程、并发编程、设计模式、Spring百口桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat等大厂口试题等、等技能栈!

欢迎大家关注"大众年夜众号【Java烂猪皮】,回答【666】,获取以上最新Java后端架构VIP学习资料以及视频学习教程,然后一起学习,一文在手,口试我有。

每一个专栏都是大家非常关心,和非常有代价的话题,如果我的文章对你有所帮助,还请帮忙点赞、好评、转发一下,你的支持会勉励我输出更高质量的文章,非常感谢!

标签:

相关文章

php多态若何懂得技巧_php多态性若何理解

多态性是指相同的操作或函数、过程可浸染于多种类型的工具上并得到不同的结果。不同的工具,收到同一将可以产生不同的结果,这种征象称为多...

网站推广 2024-12-15 阅读0 评论0