eureka和nacos ap模式下為了高并發讀寫,都在記憶體中修改,但是分别采用了不同的政策。nacos 使用的是CopyOnWrite思想防止并發沖突。eureka使用的是3級緩存。
注冊中心支援大量provider和consumer,是以有高并發的讀寫。
引用一個dubbo的圖,大體上nacos和eureka也是大緻的邏輯。
nacos
provider向注冊中心注冊,将伺服器相關資訊寫入記憶體。
consumer拉取,讀取注冊中心服務資訊。
eureka為了增加讀寫并發,在記憶體中運用讀寫分離的思想。
讀寫分離的弊端就是consumer擷取示例資料會慢一些,因為可能有延遲。
但是提高了并發。
nacos中注冊的時候,會調用更新list清單:
/**
* Update instance list.
*
* @param ips instance list
* @param ephemeral whether these instances are ephemeral
*/
public void updateIps(List<Instance> ips, boolean ephemeral) {
//系統資料庫執行個體資訊
//注冊的時候,會更新執行個體資訊
//先複制一下 是否是ephemeral 這個判斷是否是臨時還是持久,臨時是AP,持久是存儲到資料庫cp模式。
//指派了一下 這個一般方法操作記憶體都是先複制一下,或者複制變量。
//我感覺c++的寫法習慣,害怕指針改了
Set<Instance> toUpdateInstances = ephemeral ? ephemeralInstances : persistentInstances;
//複制了一份oldmap 系統資料庫執行個體資訊,下面的所有操作都是更新oldmap
HashMap<String, Instance> oldIpMap = new HashMap<>(toUpdateInstances.size());
for (Instance ip : toUpdateInstances) {
oldIpMap.put(ip.getDatumKey(), ip);
}
//他的更新都是oldmap
....
//注冊有很多種情況,
//如果之前注冊了,改了一下配置檔案,需要修改執行個體資料,做一些比對,更新資料。
toUpdateInstances = new HashSet<>(ips);
//最後再指派回來,這樣更新就和讀取分離出來了。
//copy on write思想
if (ephemeral) {
ephemeralInstances = toUpdateInstances;
} else {
persistentInstances = toUpdateInstances;
}
}
eureka server注冊使用多緩存設計:
Eureka Server 系統資料庫多級緩存設計
1)隻讀緩存
2)讀寫緩存
3)實際系統資料庫
拉取系統資料庫的時候:
- 首先從ReadOnlyCacheMap裡面查詢緩存的系統資料庫。
- 若沒有,就找ReadWriteCacheMap裡面緩存的系統資料庫。
- 如果還是沒有,就從記憶體中擷取實際的系統資料庫資料。
在系統資料庫發生變更的時候:
- 會在記憶體中更新變更的系統資料庫資料,同時過期掉 ReadWriteCacheMap
- 此過程不會影響ReadOnlyCacheMap提供人家的查詢系統資料庫
- 預設每30s Eureka Server會将ReadWriteCacheMap更新到ReadOnlyCacheMap裡面
- 預設每180s Eureka Server将ReadWriteCacheMap裡面資料失效
- 下次有服務拉取系統資料庫,又會從記憶體中擷取最新的資料了,同時填充各級緩存。