注册中心 Eureka 源码解析 —— Eureka源码解析 —— 应用实例注册发现 (九)之岁月是把萌萌的读写锁

栏目: Java · 发布时间: 6年前

内容简介:注册中心 Eureka 源码解析 —— Eureka源码解析 —— 应用实例注册发现 (九)之岁月是把萌萌的读写锁

摘要: 原创出处 http://www.iocoder.cn/Eureka/instance-registry-read-write-lock/ 「芋道源码」欢迎转载,保留摘要,谢谢!

注册中心 Eureka 源码解析 —— Eureka源码解析 —— 应用实例注册发现 (九)之岁月是把萌萌的读写锁

关注 微信公众号:【芋道源码】 有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有 源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言 将得到 认真 回复。 甚至不知道如何读源码也可以请教噢
  4. 新的 源码解析文章 实时 收到通知。 每周更新一篇左右
  5. 认真的 源码交流微信群。

1. 概述

本文主要分享 Eureka 注册中心的那把读写锁 ,让我瘙痒难耐,却不得其解。在某次意外的抠脚的一刻( 笔者不抽烟,如果抽烟的话,此处应该就不是抠脚了 ),突然顿悟,爽,这好比… 比喻有点猥琐,笔者就省略 100 字。

不瞎比比,上代码:

public abstract class AbstractInstanceRegistry implements InstanceRegistry{

 private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 private final Lock read = readWriteLock.readLock();
 private final Lock write = readWriteLock.writeLock();

 // ... 省略其他代码

}

推荐 Spring Cloud 书籍:

2. 读写锁

我们把设计到读写锁的方法整理如下:

方法 读锁 写锁 不使用
#register(...)
#cancel(...)
#evict(...)
#renew(...)
#statusUpdate(...)
#deleteStatusOverride(...)
#getApplicationDeltasFromMultipleRegions(...)
#getApplicationsFromMultipleRegions(...)

是否看到这读写感到几丝诡异的味道?OK,我们把问题梳理如下:

  • A. 为什么 #register(...) / #cancel(...) / #evict(...) / #statusUpdate(...) / #deleteStatusOverride(...)写操作 使用 读锁
  • B. 为什么 #renew(...) 写操作 不使用
  • C. 为什么 #getApplicationDeltasFromMultipleRegions(...) 读操作 使用 写锁
  • D. 为什么 getApplicationsFromMultipleRegions(...) 读操作 不使用

先解释 A + C :

我们来回想下,在 Eureka 应用集合一致性哈希码的公式: appsHashCode = ${status}_${count}_ 。( 不了解的同学可以加载下 《Eureka 源码解析 —— 应用实例注册发现(七)之增量获取》「 2. 应用集合一致性哈希码 」 )

应用实例的数量和状态都会影响 哈希码 的计算结果。也就是说,上述 前六个 ( 包括不使用锁的 #renew(...) 方法 )方法的调用都会影响哈希码。

我们把目光移向唯一使用 写锁#getApplicationDeltasFromMultipleRegions(...) 方法,该方法执行过程中,需要保证 recentlyChangedQueueregistry 共享变量的 应用实例的状态一致 ,不然返回的增量应用实例集合的状态是不准确的。此时能够达到该效果,必须让 #getApplicationDeltasFromMultipleRegions(...) 和前六个方法 互斥 。方案如下:

  • a. 全部 synchronized
  • b. #getApplicationDeltasFromMultipleRegions(...) 使用 读锁 ,前六个方法使用 写锁
  • c. #getApplicationDeltasFromMultipleRegions(...) 使用 写锁 ,前六个方法使用 读锁

Eureka 选择了 方案c ,原因如下:

再解释 D

#getApplicationsFromMultipleRegions(...) 方法的逻辑,只依赖 registry 共享变量,不存在应用实例的状态一致的困扰,所以不使用锁。

最后解释 B

#renew(...) 方法的逻辑,虽然会影响应用实例的状态,但是是极小概率,考虑到它调用的比较频繁,比起因为锁给这个方法带来的性能降低,不如返回的结果暂时不够准确。( 想了解极小概率发生原因的同学可以加载 《Eureka 源码解析 —— 应用实例注册发现(八)之覆盖状态》「 4.3 续租场景 」 )

TODO [0029] 读写锁

笔者路上突然又想了问题,可能不是上述原因,可能和 ResponseCache 有关系,参见 #invalidateCache(...) 方法的每次调用。也就是说,这个读写锁是针对 ResponseCache 的读写锁。

666. 彩蛋

开森 !

本来以为需要跟 Eureka 官方提交 issue 提问,并且做好了获得不到答案的准备,结果无意中的抠脚( 请允许我热爱抠脚给我带来的灵感 )解答了自己的疑惑。

岁月是把纠结而又萌萌哒的锁,你不知道你的困扰,哪天不经意的被打开。

愿大喜大悲,不枉仅知的这一生。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言进阶

C语言进阶

牟海军 / 机械工业出版社 / 2012-7 / 59.00元

C语言是编程语言中的一朵奇葩,虽已垂垂老矣,但却屹立不倒,诞生了数十年,仍然是最流行的编程语言之一。C语言看似简单,却不易吃透,想要运用好,更是需要积淀。本书是一本修炼C程序设计能力的进阶之作,它没有系统地去讲解C语言的语法和编程方法,而是只对C语言中不容易被初学者理解的重点、难点和疑点进行了细致而深入的解读,揭露了C语言中那些鲜为普通开发者所知的秘密,旨在让读者真正掌握C语言,从而编写出更高质量......一起来看看 《C语言进阶》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具