• redis、rocketmq 高级面试考点


    redis

    redis如何保证原子性?

    1 incr是原子操作的, 直接用redis的incr实现read和write的打包原子操作,就不会出现读了一半,然后被别人篡改了。 像批量设置多个值的场景可以用mset,批量获取多个值的mget,与incr相对应的decr,这些都是原子的。
    2 即使redis支持很多原子命令,但是还是无法满足所有场景,于是redis在2.6之后开始支持开发者编写lua脚本传到redis中,使用lua脚本的好处就是:

    减少网络开销,通过lua脚本可以一次性的将多个请求合并成一个请求。
    原子操作,redis将lua脚本作为一个整体,执行过程中,不会被其他命令打断,不会出现竞态问题。
    复用,客户端发送的lua脚本会永远存在redis服务中。

    redis部署的方式有哪些?

    单机模式
    主从模式
    哨兵模式
    集群模式

    redis以上的部署方式有哪些优势、弊端?

    单机模式:

    • 优点
      部署简单
    • 缺点
      可支持的并发量少

    主从模式:

    • 优点:
      1 能够为后续的高可用机制打下基础
      2 在持久化的基础上能够将数据同步到其他机器,在极端情况下做到灾备的效果
      3 能够通过主写从读的形式实现读写分离提升Redis整体吞吐,并且读的性能可以通过对从节点进行线性扩容无限提升
    • 缺点:
      1 全量数据同步时如果数据量比较大,在之前会导致线上短暂性的卡顿。
      2 一旦主节点宕机,需要人工干预从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。
      3 写入的QPS性能受到主节点限制,虽然主从复制能够通过读写分离来提升整体性能,但是只有从节点能够做到线性扩容升吞吐,写入的性能还是受到主节点限制木桶效应,整个Redis节点群能够存储的数据容量受到所有节点中内存最小的那台限制,比如一主两从架构:master=32GB、slave1=32GB、slave2=16GB,那么整个Redis节点群能够存储的最大容量为16GB 。

    哨兵模式:数据的分布都是去中心化,可支持的读并发有限

    • 优点:
      1 解决了之前主从切换需要人工干预问题,保证了一定意义上的高可用
    • 缺点:
      1 全量数据同步仍然会导致线上出现短暂卡顿
      2 写入QPS仍然受到主节点单机限制,对于写入并发较高的项目无法满足需求
      3 仍然存在主从复制时的木桶效应问题,存储容量受到节点群中最小内存机器限制

    集群模式:

    redis分布式锁的底层原理

    setnx,如果

    redis使用过程中遇到的一些问题

    缓存雪崩:短时间redis的key失效,所有的请求直接到数据库。
    解决办法:设置key随机消失的时间。

    缓存击穿:热key失效
    解决办法:1 设置永不过期;

    缓存穿透:使用不存在的key查询
    解决办法:1、设置ip白名单,防止黑客攻击;2、对空值进行缓存

    rocketMQ

    如何保证消息的可靠性(不丢失)

    保证消息的不丢失,主要从三个方面:生产端、broker端、消费端处理。

    • 生产端
      在生产阶段,主要通过请求确认机制,来保证消息的可靠传递。
      1、同步发送的时候,要注意处理响应结果和异常。如果返回响应OK,表示消息成功发送到了Broker,如果响应失败,或者发生其它异常,都应该重试。
      2、异步发送的时候,应该在回调方法里检查,如果发送失败或者异常,都应该进行重试。
      3、如果发生超时的情况,也可以通过查询日志的API,来检查是否在Broker存储成功。
    • broker端
      存储阶段,可以通过配置可靠性优先的 Broker 参数来避免因为宕机丢消息,简单说就是可靠性优先的场景都应该使用同步。
      1、消息只要持久化到CommitLog(日志文件)中,即使Broker宕机,未消费的消息也能重新恢复再消费。
      2、Broker的刷盘机制:同步刷盘和异步刷盘,不管哪种刷盘都可以保证消息一定存储在pagecache中(内存中),但是同步刷盘更可靠,它是Producer发送消息后等数据持久化到磁盘之后再返回响应给Producer。
      3、Broker通过主从模式来保证高可用,Broker支持Master和Slave同步复制、Master和Slave异步复制模式,生产者的消息都是发送给Master,但是消费既可以从Master消费,也可以从Slave消费。同步复制模式可以保证即使Master宕机,消息肯定在Slave中有备份,保证了消息不会丢失。
    • 消费端
      Consumer保证消息成功消费的关键在于确认的时机,不要在收到消息后就立即发送消费确认,而是应该在执行完所有消费业务逻辑之后,再发送消费确认。因为消息队列维护了消费的位置,逻辑执行失败了,没有确认,再去队列拉取消息,就还是之前的一条。

    消息积压如何处理

    发生了消息积压,这时候就得想办法赶紧把积压的消息消费完,就得考虑提高消费能力,一般有两种办法:

    • 消费者扩容:如果当前Topic的Message Queue的数量大于消费者数量,就可以对消费者进行扩容,增加消费者,来提高消费能力,尽快把积压的消息消费玩。

    • 消息迁移Queue扩容:如果当前Topic的Message Queue的数量小于或者等于消费者数量,这种情况,再扩容消费者就没什么用,就得考虑扩容Message Queue。可以新建一个临时的Topic,临时的Topic多设置一些Message Queue,然后先用一些消费者把消费的数据丢到临时的Topic,因为不用业务处理,只是转发一下消息,还是很快的。接下来用扩容的消费者去消费新的Topic里的数据,消费完了之后,恢复原状。

    如何保证不重复消费

    对分布式消息队列来说,同时做到确保一定投递和不重复投递是很难的,就是所谓的“有且仅有一次” 。 RocketMQ择了确保一定投递,保证消息不丢失,但有可能造成消息重复。
    处理消息重复问题,主要有业务端自己保证,主要的方式有两种:业务幂等和消息去重。

    • 业务幂等:第一种是保证消费逻辑的幂等性,也就是多次调用和一次调用的效果是一样的。这样一来,不管消息消费多少次,对业务都没有影响。

    • 消息去重:第二种是业务端,对重复的消息就不再消费了。这种方法,需要保证每条消息都有一个惟一的编号,通常是业务相关的,比如订单号,消费的记录需要落库,而且需要保证和消息确认这一步的原子性。
      具体做法是可以建立一个消费记录表,拿到这个消息做数据库的insert操作。给这个消息做一个唯一主键(primary key)或者唯一约束,那么就算出现重复消费的情况,就会导致主键冲突,那么就不再处理这条消息。

    如何实现顺序消息

    顺序消息是指消息的消费顺序和产生顺序相同,在有些业务逻辑下,必须保证顺序,比如订单的生成、付款、发货,这个消息必须按顺序处理才行。

    顺序消息分为全局顺序消息和部分顺序消息,全局顺序消息指某个 Topic 下的所有消息都要保证顺序;

    部分顺序消息只要保证每一组消息被顺序消费即可,比如订单消息,只要保证同一个订单 ID 个消息能按顺序消费即可。

  • 相关阅读:
    十、2023.10.4.计算机网络(one).10
    UnityAPI学习之碰撞检测与触发检测
    前端培训丁鹿学堂:js中箭头函数的面试相关总结
    剑指 Offer 18. 删除链表的节点
    后端面试话术集锦第 十七 篇:MySQL面试话术
    【数据结构】——链表面试题详解
    linux实用技巧:在虚拟机vmware16软件上安装CentOs8.2虚拟机,重置可用源和安装输入法
    [机缘参悟-110] :一个IT人对面具的理解:职业面具戴久了,就会忘记原本真实的自己,一个人是忠于职位,还是忠于内心?
    【性能测试】数据库优化
    R语言ggplot2可视化:使用ggpubr包的ggscatter函数可视化分组散点图(scatter plot)、设置add参数为每个分组添加回归线
  • 原文地址:https://blog.csdn.net/Nick_zcy/article/details/126410933