1. 读写锁
1.1 位置
public abstract class AbstractInstanceRegistry implements InstanceRegistry {
private ConcurrentLinkedQueue<RecentlyChangedItem> recentlyChangedQueue = new ConcurrentLinkedQueue<RecentlyChangedItem>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
}
1.2 锁机制
- 读锁之间不互斥,写锁之间互斥,读写锁之间互斥
- 当一个线程获取读锁时,另一个线程能获取读锁但是不能获取写锁;当一个线程获取写锁,另一个线程读锁或写锁都不能获取。这个和 InnoDB 的读写锁是一样的
1.3 调用方
- read:处理客户端注册、下架、状态变更、删除状态
- write:处理客户端拉取增量注册表
1.4 分析
- 在上述处理的相关代码中,可以发现共同点就是操作了 recentlyChangedQueue 最近变更队列,读写锁就是服务于这个队列
- 对于 recentlyChangedQueue 队列,写的场景很多,读的场景只有拉取增量注册表。当多个场景多线程对于 recentlyChangedQueue 进行写操作时,recentlyChangedQueue 的数据结构是线程安全的,所以不用加写锁,但是加读锁和为了配合拉取增量注册表的读场景,保证对 recentlyChangedQueue 写操作时无法读操作,读操作时不能写操作,保证拉取增量注册表时获取的 recentlyChangedQueue 没变更,recentlyChangedQueue 变更时不给拉取增量注册表
2. invalidateCache()
2.1 源码解析
private void invalidateCache(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {
responseCache.invalidate(appName, vipAddress, secureVipAddress);
}
public void invalidate(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {
for (Key.KeyType type : Key.KeyType.values()) {
for (Version v : Version.values()) {
invalidate(
new Key(Key.EntityType.Application, appName, type, v, EurekaAccept.full),
new Key(Key.EntityType.Application, appName, type, v, EurekaAccept.compact),
new Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.full),
new Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.compact),
new Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.full),
new Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.compact)
);
if (null != vipAddress) {
invalidate(new Key(Key.EntityType.VIP, vipAddress, type, v, EurekaAccept.full));
}
if (null != secureVipAddress) {
invalidate(new Key(Key.EntityType.SVIP, secureVipAddress, type, v, EurekaAccept.full));
}
}
}
}
public void invalidate(Key... keys) {
for (Key key : keys) {
logger.debug("Invalidating the response cache key : {} {} {} {}, {}",
key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());
readWriteCacheMap.invalidate(key);
Collection<Key> keysWithRegions = regionSpecificKeys.get(key);
if (null != keysWithRegions && !keysWithRegions.isEmpty()) {
for (Key keysWithRegion : keysWithRegions) {
logger.debug("Invalidating the response cache key : {} {} {} {} {}",
key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());
readWriteCacheMap.invalidate(keysWithRegion);
}
}
}
}