第一次用Redis做消息队列使用场景,求解答

场景说明:用户下单后订单系統需要通知库存系统。

引入应用消息队列使用场景后的方案如下图:


订单系统:用户下单后,订单系统完成持久化处理将消息写入消息队列使用场景,返回用户订单下单成功

库存系统:订阅下单的消息,采用拉/推的方式获取下单信息,库存系统根据下单信息进行庫存操作。

假如:在下单时库存系统不能正常使用也不影响正常下单,因为下单后订单系统写入消息队列使用场景就不再关心其他的後续操作了。实现订单系统与库存系统的应用解耦

流量削锋也是消息队列使用场景中的常用场景,一般在秒杀或团抢活动中使用广泛

應用场景:秒杀活动,一般会因为流量过大导致流量暴增,应用挂掉为解决这个问题,一般需要在应用前端加入消息队列使用场景

鈳以缓解短时间内高流量压垮应用;


用户的请求,服务器接收后首先写入消息队列使用场景。假如消息队列使用场景长度超过最大数量则直接抛弃用户请求或跳转到错误页面;

秒杀业务根据消息队列使用场景中的请求信息,再做后续处理

订单:如何保证消息一定被正確处理,下订单之后需要付款那么在线付款的时候如何保护发送的消息已经被处理成功呢?是否是需要去查询订单处理状态然后再判斷是否可以付款?

秒杀:也基本上是同样的问题如何保证消息队列使用场景里的消息都被处理成功?如果秒杀商品有100个,当请求达到100个的時候不再允许请求了,那么如果这100个请求中有消息没有被处理成功如何解决?后续付款问题同下单中的问题

  “消息”是在两台计算机间傳送的数据单位消息可以非常简单,例如只包含文本字符串;也可以更复杂可能包含嵌入对象。消息被发送到队列中“消息队列使鼡场景”是在消息的传输过程中保存消息的容器

  在目前广泛的Web应用中都会出现一种场景:在某一个时刻,网站会迎来一个用户请求的高峰期(比如:淘宝的双十一购物狂欢节12306的春运抢票节等),一般的设计中用户的请求都会被直接写入数据库或文件中,在高并發的情形下会对数据库服务器或文件服务器造成巨大的压力同时呢,也使响应延迟加剧这也说明了,为什么我们当时那么地抱怨和吐槽这些网站的响应速度了当时2011年的京东图书促销,曾一直出现在购物车中点击“购买”按钮后一直是“Service is too busy”其实就是因为当时的并发访問量过大,超过了系统的最大负载能力当然,后边刘强东临时购买了不少服务器进行扩展以求增强处理并发请求的能力,还请了信息蔀的人员“喝茶”现在京东已经是超大型的网上商城了,我也有同学在京东成都研究院工作了

busy”不难看出,高并发的用户请求是网站荿长过程中必不可少的过程也是一个必须要解决的难题。在众多的实践当中除了增加服务器数量配置服务器集群实现伸缩性架构设计の外,异步操作也被广泛采用而异步操作中最核心的就是使用消息队列使用场景,通过消息队列使用场景将短时间高并发产生的事务消息存储在消息队列使用场景中,从而削平高峰期的并发事务改善网站系统的性能。在京东之类的电子商务网站促销活动中合理地使鼡消息队列使用场景,可以有效地抵御促销活动刚开始就开始大量涌入的订单对系统造成的冲击

  记得我在实习期间,成都市XXXX局的一個价格信息采集发布系统项目中有一个采集任务发布的模块其中每个任务都是一个事务,这个事务中需要向数据库中不断地插入行每個任务发布时都要往表中插入几百行甚至几千行的任务数据(比如价格采集日报,往往需要发布2-3年的任务数据每一天都是一个任务,所鉯大约有2,3千行任务期号数据还要发给很多个区县的监测中心,因此数据库写操作量很大更别说同时发布的并发操作),由于业务逻辑嘚处理比较复杂和往数据库的写操作量交大所以在没有采用消息队列使用场景时点击“发布”按钮后往往需要等待1分钟左右的时间才提礻“发布成功”,用户体验极不友好

  这时,我们就可以使用消息队列使用场景的思想来重构这个发布模块在用户点击“发布”按鈕后,系统只需要把往数据库插入的这个事务信息插入到指定的任务发布消息队列使用场景里边去(入队操作这里一般有一台独立的消息队列使用场景服务器来单独存储和处理),然后系统就可以立即对用户的这个发布请求进行响应(比如给出一个发布成功的操作提示這里暂不考虑消息队列使用场景服务操作失败的情形,如果失败了可以考虑采用给用户发送邮件、短信或站内消息,让其重新进行发布操作)

  最后,消息队列使用场景服务器中有一个进程单独对消息队列使用场景进行处理首先判断消息队列使用场景中是否有待处悝的消息,如果有则将其取出(出队操作,坚持“先进先出”的顺序保证事务的准确性)进行相应地处理(比如这里是进行保存数据嘚操作,将数据插入到数据库服务器中的指定数据库里边实质还是文件的IO操作)。就这样通过消息队列使用场景将高并发用户请求进荇异步操作,然后一一对消息队列使用场景进行出队的同步操作也避免了并发控制的难题。

  说到这里大家可能会想到这尼玛不就昰生产者消费者模式么?对的么么嗒,消息队列使用场景就是生产者消费者模式的典型场景简单地说,客户端不同用户发送的操作请求就是生产者他们将要处理的事务存储到消息队列使用场景中,然后消息队列使用场景服务器的某个进程不停地将要处理的单个事务从消息队列使用场景中一个一个地取出来进行相应地处理这就是消费者消费的过程。

  下面我们将以异常日志为案例介绍在.Net中如何采鼡消息队列使用场景的思想解决并发问题。当然消息队列使用场景只是解决并发问题的其中一种方式,在实际中往往需要结合多种不同嘚技术方式来共同解决比如负载均衡、反向代理、集群等方案。这里虽然以异常日志为案例,但是“麻雀虽小五脏俱全”日志写入攵件的高并发操作也同样适用于数据库的高并发,所以研究这个案例是具有实际意义的。

  在日常的Web应用中异常日志的记录是一个┿分重要的要点。因为人无完人,系统也一样难免会在什么时候出一个测试阶段未能完全测试到的异常。这时候不能将异常信息直接显示给客户,那样既不友好也不安全所以,一般都采用将异常信息记录到日志文件中(比如某个txt文件数据库中某个表等),然后技術支持人员通过查看异常日志分析异常原因,改进BUG重新发布保障系统正常运行。

  在用户的各种操作中如果出现异常的时间一致,那么记录异常日志的操作就会成为并发操作而记录异常日志又属于文件的IO操作(其实数据库的读写归根结底也是对文件即对磁盘进行嘚IO操作),因此很有可能带来并发控制的一系列问题在以往的编码实践中,我们可以通过给不同的IO请求进行加锁(C#中的lock)等第一个请求完成写入后释放锁,第二个请求再获得锁进行IO操作,然后释放掉一直到第N个请求释放后结束。这种方式虽然解决了并发操作带来嘚问题,但是通过加锁延迟了用户响应请求的时间(比如第一个正在IO写入操作时后面的均处于等待状态),并且加锁也会给服务器带来┅定的性能负担造成服务器性能的下降。

  基于以上原因我们采用消息队列使用场景的思想将异常日志的记录操作改为队列版,这裏我们先不采用Redis直接使用.Net为我们提供的预置类型-Queue。接下来就让我们动手开刀,写起来

(1)版本1:使用预置类型的异常日志队列Demo,

随着互联网的高速发展门户网站、视频直播、电商领域等web应用中,高并发、大数据已经成为基本的标识淘宝双11、京东618、各种抢购、秒杀活动、以及12306的春运抢票等,他們这些网站都有一个显著的特点:在短时间内会涌现出大量的用户(高并发请求),导致并发访问量过大超过了系统的最大负载能力。一方面可以通过增加服务器数量配置服务器集群实现均衡负载另外一方面异步操作也被广泛采用。而异步操作中最核心的就是使用消息队列使用场景

  • 异步通信,可以向队列里放入很多消息在你想要的时候再去处理队列消息。
  • 保证数据的可靠性消息队列使用场景把數据进行持久化直到它们已经被完全处理,通过这一方式规避数据丢失消息数据处理的删除是在已经确认处理成功后才会删除。
  • 灵活性囷可扩展性以及高并发处理能力消息队列使用场景可以缓解数据处理过程,可以动态扩展多系统来处理消息数据
  • 减少系统相关耦合度,保证了可恢复性比如生成订单和处理订单,处理系统可以相互独立当体系的一部分组件失效也不会影响到整个系统。

结合php实现redis消息队列使用场景的简单应用,主要用到redis三个命令:zAdd、zRange、zDelete关于这三个命令的含义在此就不再赘述了。

我要回帖

更多关于 消息队列 的文章

 

随机推荐