当前位置:   article > 正文

Redis和消息队列_消息队列与readis关系

消息队列与readis关系

Redis

一、Redis数据类型、Redis数据结构、Redis使用场景
  1. Redis数据类型

    键的类型只能是字符串

    值支持5种数据类型:

    • 字符串String,可以存储字符串、整数、浮点数

    • 列表list

    • 集合set

    • 散列表hash,包含键值对的无序散列表

    • 有序集合zset

  2. Redis具体数据结构

    • 字典:是集合的一种,集合中每个元素都是key-value键值对

    • 跳跃表:是有序集合的底层实现之一,是基于多指针有序链表实现的,可以看成多个有序链表

      对于一个单链表来说,即使链表中存储的数据有序,查找数据也只能从头到尾遍历

      想要提高效率,考虑在链表上建立索引,每两个节点提取一个节点到上一级

      查找时,从上层指针开始查找,找到对应区间之后再到下一层查找。

  3. Redis的使用场景

    • 缓存

    • 会话缓存:存储多个应用服务器的会话信息,应用服务器无状态

    • 消息队列:写入和读出消息

    • 计数器

    • 查找表:和缓存类似,如存储DNS记录;查找表内容不允许失效,缓存允许失效

    • 分布式锁:分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步

二、Redis和Memcashed

都是非关系型内存键值数据库

  • Redis支持5种不同的数据类型;Mencashed只支持字符串类型
  • Redis支持两种持久化策略:RDB快照和AOF日志;而Memcashed不能持久化
  • Redis支持分布式,Memcashed不支持分布式
  • Redis中并不是所有数据都一直在内存中,可以将很久没用的value交换到磁盘;而Memcashed的所有数据都一直在内存中
三、Redis键的过期时间、数据淘汰策略、持久化、(事务、事件)
  1. 键的过期时间

  2. 数据淘汰策略(算法)

    可以设置内存最大使用量,当内存使用量超出时就会淘汰;

    • 从以设置过期时间的数据中选择:volatile-lru、volatile-ttl(将要过期)、volatile-random

    • 从全部数据中选择:allkeys-lru、allkeys-random

    禁止驱逐数据:noeviction

    一般使用allkeys-lru算法

  3. 数据持久化:将数据从内存中持久化到磁盘上

    • ROB快照:将某个时间点的所有数据,以快照形式存放到硬盘上
    • AOF日志:以独立日志的方式记录“每一次的写命令”,在Redis重启时,重新执行AOF中的命令,以达到恢复数据的目的。
  4. (事务)

    一个事务包含多个命令,服务器执行事务期间,不会执行其他命令。

  5. (事件)

    Redis服务器是一个事件驱动程序

    • 文本事件:服务器通过套接字与客户端或其他服务器通信,文本事件就是对套接字操作的抽象
    • 时间事件:服务器有一些操作,需要在给定的事件点执行,时间事件是对这类定时操作的抽象
四、(Redis复制、sentinel、分片)
  1. Redis主从复制

    Redis主服务器,从服务器

    可以设置主从链

  2. Redis的Sentinel

    哨兵,可以监听集群中的服务器,可以在主服务器下线时,自从从 从服务器中选举出新的主服务器

  3. Redis的分片

    将数据划分为多个部分,可以将数据存储到多台机器里面

缓存问题
  • 缓存雪崩

    如果缓存在某个时刻出现大规模的key失效,就会导致大量的请求直接打在数据库上,使得数据库压力巨大;如果在高并发的情况下,可能瞬间导致数据库宕机。

  • 缓存击穿

    某个热点key失效,大量并发请求集中访问,在缓存找不到;

    就会引起高并发访问数据库,使得数据库压力剧增,可能导致数据库宕机;

  • 缓存穿透

    用户请求的数据在缓存中不存在,同时也在数据库中不存在;

    导致用户每次请求该数据,都要去数据库中查询;

    如果有恶意攻击者短时间内不断请求系统中不存在的数据,会导致短时间内有大量请求落在数据库上,从而使数据库宕机。

消息队列

消息队列介绍

消息队列是分布式系统中重要的组件;

主要解决“应用解耦”、“异步消息”,“流量削峰”等问题;实现高性能,高可用,高伸缩和最终一致性架构。

目前使用较多的消息队列有ActiveMQ、RabbitMQ、kafka、RocketMQ等。

概念:

  • Topic:

    从逻辑上讲一个Topic就是一个队列Queue

    从存储上讲一个Topic存储了一类相关的消息,是消息的集合

    Partition:

    分是存在于服务端,且内部保持顺序,顺序不可变更的一个队列,用户存储消息。

    在使用消息队列时用户感觉不到分区

    image-20210831161727619

    一个Topic存储消息时会分为多个Partition,每个Partition内部消息是有顺序的。

    类似于快递网点内有多家快递公司

  • Productor:

    生产消息,生产完决定将消息发送到哪个Topic的哪个Partition

    一个MQ中可以有多个种类的Topic种类消息,Patition先理解成一个Queue的内部存储

    Consumer:

    订阅Topic,消费内部的消息

    Group:

    用来标记Consumer的身份,拥有相同Group名称的Consumer是一个类Consumer,一般消费同一类消息。

    Consumer之间是需要协同工作的,Productor之间一般是不相关的,不需要Group标记身份。

    协同工作:两个consumer消费Topic消息,订单消息只能消费一次;如果行为相同的consumer只存在一个,就不存在协同工作了,但是存在单点问题和性能问题,因为大多数情况下是分布式系统。

  • 集群消费:

    一个消息只被消费一次,同一个Group内有多个Consumer,共同完成对一个Topic的消费。

    上面说的Consumer协同工作就默认是集群消费了。

    image-20210831163054239

    图中Consumer0和Consumer1属于同一个Group,假设Topic中有0到5共6条消息,Consumer0消费0-2,Consumer1消费3-5,他们共同完成了Topic中消息的消费。

    这存在于大量的无状态的后台系统,就如上面说的消费订单消息进行发货的例子。(一个消息只被一个Consumer消费一次)

    广播消费:

    Topic中的每个消息会被同一个Group里的每个Consumer都消费一次;

    image-20210831163456392

    如图Topic有0-5共6条消息,Consumer0会消费到0-5完整的6条消息,Consumer1也会消费0-5的6条消息。

    这种消费往往应用在有状态的后台系统,比如多个缓存服务器,都要去消费消息,更新自己的缓存数据。

消息模型
  • 点对点模型

    生产者向消息队列Topic中发送一个消息后,只能被一个消费者消费一次

    image-20210831164254877

  • 发布订阅模型

    生产者向Topic中发布了一个消息之后,所有订阅了该Topic的消费者都可以进行消费该消息,一个消息可以被消费多次。

    image-20210831164444759

    (扩展:设计模式中“发送订阅模式”和“观察者模式”区别)

    • 观察者模式中,Topic和观察者都知道对方的存在;而在发布订阅者模式中,生产者和消费者不知道对方的存在,它们通过Topic进行通信。

    • 观察者模式是同步的,当事件触发,Topic会调用观察者的方法,然后等待方法的返回;

      发布订阅模式是异步的,生产者向Topic发送一条消息,会立即返回,不关心消费者什么时候来消费这个消息。

      image-20210831164906893

使用场景
  1. 异步处理

    productor将消息发送给消息队列Topic之后,不需要等待consumer的处理,而是立即返回,可以进行其他操作。consumer从Topic中接收消息后进行异步处理。

    例如在注册流程中,系统需要发送邮件验证用户合法性,可以使用消息队列使得 发送邮件的操作异步处理;用户注册完后就可以完成注册,而将“发送邮件”这一消息发送给消息队列。

    但只有业务流程允许异步处理的情况下才能这么做。

  2. 流量削峰

    高并发场景下,如果短时间内有大量请求到达,可能会压垮服务器和数据库;

    可以将请求转发到消息队列中,业务处理服务器再根据其处理能力,从消息队列中订阅消息进行处理。

    因为用户请求被放入消息队列中之后,请求就立即返回了。但是在后续的业务操作和数据库操作可能失败,因此使用消息队列进行异步处理之后,需要适当修改业务流程进行配合。例如在用户提交订单之后,订单数据写入MQ,不能立即返回给用户订单结果,需要在MQ中的消息被真正处理之后,再通过email或者短信通知用户订单结果,如手机订车票。

  3. 系统解耦

    传统情况下系统模块之间进行直接调用,修改或新增一个模块会直接对其他模块产生影响。

    通过使用MQ,一个模块只需要向MQ中发送消息,其他模块可以选择性的从MQ中订阅消息,从而完成调用,这样降低了系统耦合性。

    利用发布订阅模式;消息发送者(生产者)发布消息,一个或多个消费者订阅消息,消息发送者和消息接收者并没有直接耦合,对新增业务而言,只要对某类消息感兴趣,就可以订阅该消息,对原有的系统和业务没有任何的影响。从而实现网站业务的可拓展性设计。

消息队列的问题
  • 可用性降低:引入MQ之后,需要考虑MQ服务器宕机的情况。
  • 复杂性提高:需要保证消息没有被‘’重复消费“,处理”消息丢失“的情况,保证“消息传递的顺序性”
  • 数据一致性:MQ异步处理可以提高系统的响应速度,但是消费者消费失败了,就会导致数据不一致的问题。

解决方案:

  • 可用性问题:

    MQ服务器使用集群,每次访问的是集群中的主服务器,当主服务器挂掉以后,备用服务器顶上。

  • 复杂性问题

    • 如何保证消息不被重复消费

      消息被重复消费的原因大多是因为网络不通,确认消息没有传送到消息队列,导致MQ不知道自己已经消费过该消息了,再次将消息分发给其他消费者。三种解决思路:

      1. 如果消息是做数据库插入操作,给这个消息做一个唯一的主键,这样就算重复消费也会到导致主键冲突;不可取,数据库记录的主键一般是与业务无关的自增主键。

      2. 如果这个消息是做redis的set操作,那么不用解决,因为无论set几次结果都是一样的。

      3. 如果以上两种情况都不行,那么准备一个第三方来做消息记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以键值对的形式写入redis。那么消费者开始消费前,先去redis中查看有没有消费记录即可。

      4. 选择一个支持消息持久化的方案:如RabiitMQ,给消息一个处理状态

    • 如何保证消息的可靠传输

      保证消息的可靠传输就是防止Productor弄丢数据,MQ弄丢数据,Consumer弄丢数据。

      • Productor弄丢数据:事务机制,生产者发送数据之前开启RabbitMQ事务,然后发送消息,如果消息没有被MQ接收到,生产者就会报错,此时就可以进行回滚,重新发送消息。

        ack机制和超时重传:当MQ收到消息以后返回ack给Productor确认,如果在超时时间内Productor没有收到MQ的确认就重发该消息;

      • MQ丢失数据:开启MQ的持久化,即使MQ挂了重启以后还能恢复之前的数据

      • Consumer丢失数据:主要是消费时刚消费到,还没处理,进程就挂了;

        关闭MQ的自动ack机制,只有消息真正处理完才手动返回给MQ一个ack;

    • 如何保证从消息队列里拿到的数据按顺序执行

      将需要保持顺序的消息放到同一个Topic里面,然后只用一个消费者去消费该Topic

    • 数据是通过push还是通过pull方式给到Consumer比较好

      • push实时性好,但是consumer消费速度不一致,同时MQ也难以知道consumer消费的情况,push也会加重Consumer的负载压垮Cnosumer
      • pull实现相对简单,但实时性取决于轮询的频率,在对实时性要求不高的场景可以使用

其他问题:

  • 大量消息在MQ中积压了几个小时还没解决?

    临时紧急扩容:临时将Queue资源和consumer资源扩大10倍,以正常的10倍数据来消费数据。

  • 消息队列过期失效:批量重新导入

  • 消息队列满了:

常见消息队列

消息队列详解_hc_ttxs的博客-CSDN博客_消息队列详解

ActiveMQ

  • 单机吞吐量:万级,吞吐量比RocketMQ和Kafka低一个数量级
  • Topic数量对吞吐量的影响:
  • 时效性:ms级别
  • 可用性:高,基于主从架构实现高可用性
  • 消息可靠性:有较低的概率丢失数据
  • 功能支持:MQ领域的功能极其完备
  • 优劣势总结:
    • 非常成熟,功能强大,在业内大量公司用
    • 偶尔会有较低概率丢失消息
    • 社区和国内应用越来越少,官方维护越来越少
    • 主要基于异步和解耦使用,较少在大规模吞吐的场景中使用

RabbitMQ

  • 单机吞吐量:万级,吞吐量比RocketMQ和Kafka低一个数量级
  • Topic数量对吞吐量的影响:
  • 时效性:us级别,延迟是最低的,这是RabbitMQ的一大特点
  • 可用性:高,基于主从架构实现高可用性
  • 消息可靠性:
  • 功能支持:基于erlang开发,所以并发能力很强,性能极好,延时很低
  • 优劣势总结:
    • 基于erlang语言开发,性能好,延时很低
    • 吞吐量到万级,MQ功能比较完备
    • 开源而且提供的管理界面很好
    • 社区相对活跃,几乎几个月都发布几个版本
    • 国内互联网公司近几年用的相对想多
    • 问题也显而易见,吞吐量确实会低一些
    • erlang语言很难读懂源码以及很难定制

RocketMQ

  • 单机吞吐量:10万级别,可以支撑高吞吐量
  • Topic数量对吞吐量的影响:==Topic可以达到几百,几千个的级别,这是Rocket的优势。==吞吐量会有较小幅度的下降
  • 时效性:ms级别
  • 可用性:非常高,采用分布式架构
  • 消息可靠性:经过参数优化配置,可以做到0丢失
  • 功能支持:MQ功能较为完善,分布式,扩展性好
  • 优劣势总结:
    • 接口简单引用,阿里大规模应用过,有阿里品牌保证
    • 日处理消息上百亿之多,可以做到大规模吞吐;性能也非常好,分布式扩展也方便;社区维护、可用性OK;支持大规模Topic复杂MQ业务场景
    • 采用java系的,可以自己阅读源码,定制自己公司的MQ,可以掌控
    • 社区活跃度相对一般,但也还可以

Kafaka——高吞吐量的分布式发布订阅MQ

  • 单机吞吐量:10万级别,这是kafka最大的特点,吞吐量高,一般配合大数据系统来进行实时数据计算、日志采集等场景

  • Topic数量对吞吐量的影响:Topic从几十个到几百个的时候,吞吐量会大幅度下降;

    所以在同等机器中,kafka尽量保证topic数量不要过多;如果需要大规模topic,需要增加更多机器资源

  • 时效性:ms级别

  • 可用性:非常高,kafka是分布式的,一个数据多个副本,少数机器宕机不会导致数据不可用

  • 消息可靠性:经过参数优化配置,可以做到0丢失

  • 功能支持:功能较为简单,主要支持简单的MQ功能;在大数据领域的实时计算和日志采集被大规模使用,是事实上的标准。

  • 优劣势总结:

    • kafka特点明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量;ms级的延时,极高的可用性,分布式可以任意扩展
    • kafka为了保证其超高的吞吐量,支持尽量较少的topic
    • 唯一缺点:消息有可能重复消费,那么对数据的准确性会造成轻微的影响;在大数据领域实时计算和数据采集中,这点轻微影响可以忽略。

20180723203239485

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/908181
推荐阅读
相关标签
  

闽ICP备14008679号