分布式系统内部RetryCache机制

前言


在分布式系统的运行过程中,出现网络不稳定(例如网络超时)导致的client请求回复超时是时有发生的事。在这种低概率发生的情况下时,client端其实是无法感知它的请求是不是真正的被处理了,它只能是基于坏的情况(即请求没被server处理的情况),然后执行重试操作。问题就出现在这里,对于某些非幂的操作而言,操作重试是会返回不同的结果的。这个时候,其实server端不应该执行client端发起的第二次请求的,假设server已经成功处理了client的第一次请求。本文我们就来聊聊针对非幂等操作处理的RetryCache,通过RetryCache我们可以避免重复请求被处理。

非幂等操作重复处理的问题


这里重新回过头来说说非幂等操作被重复处理可能会导致的问题。

简单概括下来,会有以下几点潜在问题:

1)Application端因为接收到server返回的异常结果信息而导致application失败。因为非幂等类型重复请求第二次被server端时,可能会导致返回错误结果。比如重复执行创建文件请求时,第二次系统就会返回FileAlreadyExistException之类的错误。

2)Server端metadata信息的破坏。假设我们执行完create文件操作后,然后这个文件被相关任务read完随后被正常清理了,但是client的重试导致这个文件又被创建了一次,这就有可能引发metadata信息的损坏了。

3)Server HA failover切换时的metadata一致性问题。当服务在做HA failover切换和时候,服务主备切换是一个比较重的操作,failover切换期间是会出现client端请求无响应超时的情况的。这个时候可能部分请求被处理,部分实质上没有被处理,在服务主备切换后,为了保证server状态的完全一致性,我们需要利用RetryCache,来帮助server做重复的请求处理。当然,这里面需要新的active server做内部RetryCache的重建操作。

鉴于上述的问题,因此我们需要引入一个内部Cache来存放已执行过的请求调用结果,来防止非幂等操作的重复处理。在这里,我们称之为上述Cache为RetryCache。

RetryCache的实现细节


如果我们想实现一套完整的RetryCache,有哪些点需要重点去考虑的呢?

这里主要列出了以下几点:

  • Client请求call的独立标识区分。目前RPC server内部一般会带有类似callId的概念来区分请求,但是单一callId还是无法区分出请求是否来自于同一个机器的client还是多个机器的client。在这里我们需要额外引入clientId的字段,以此组成<callId+clientId>的联合Id方式。
  • 标记区分操作方法是否是幂等类型的还是非幂等类型的,我们只对后者类型请求结果进行RetryCache的存放。
  • RetryCache内部每个Cache Entry不可能保证永久的存放,需要有过期时间的限制。
  • RetryCache的信息持久化和重建过程的考虑,这个主要发生在HA服务做主从切换的时候。

RetryCache的实现样例


针对上面的实现细节,我们通过一个具体样例来进行更具化地了解,此样例取自于Hadoop 所使用的RetryCache类。

首先是Cache Entry的定义:

  /**
   * CacheEntry is tracked using unique client ID and callId of the RPC request
   */
  public static class CacheEntry implements LightWeightCache.Entry {
   
    /**
     * Processing state of the requests
     */
    private static byte INPROGRESS = 0;
    private static byte SUCCESS = 1;
    private static byte FAILED = 2;

    /** 此entry代表的请求目前的状态,正在被处理,或者已经处理成功或失败*/
    private byte state = INPROGRESS;
    
    ...
    
    private final int callId;
    private final long expirationTime;
    private LightWeightGSet.LinkedElement next;

    /**
     * 一个全新的cache entry,它需要有clientId,callId以及过期时间.
     */
    CacheEntry(byte[
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值