天天看點

eureka和nacos注冊中心緩存高并發讀寫比較

eureka和nacos ap模式下為了高并發讀寫,都在記憶體中修改,但是分别采用了不同的政策。nacos 使用的是CopyOnWrite思想防止并發沖突。eureka使用的是3級緩存。

注冊中心支援大量provider和consumer,是以有高并發的讀寫。

eureka和nacos注冊中心緩存高并發讀寫比較

引用一個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)實際系統資料庫

eureka和nacos注冊中心緩存高并發讀寫比較

拉取系統資料庫的時候:

  • 首先從ReadOnlyCacheMap裡面查詢緩存的系統資料庫。
  • 若沒有,就找ReadWriteCacheMap裡面緩存的系統資料庫。
  • 如果還是沒有,就從記憶體中擷取實際的系統資料庫資料。

在系統資料庫發生變更的時候:

  • 會在記憶體中更新變更的系統資料庫資料,同時過期掉 ReadWriteCacheMap
  • 此過程不會影響ReadOnlyCacheMap提供人家的查詢系統資料庫
  • 預設每30s Eureka Server會将ReadWriteCacheMap更新到ReadOnlyCacheMap裡面
  • 預設每180s Eureka Server将ReadWriteCacheMap裡面資料失效
  • 下次有服務拉取系統資料庫,又會從記憶體中擷取最新的資料了,同時填充各級緩存。