微服務化后緩存怎么做


摘要

最近接手的代碼中遇到幾個緩存的問題,存在一些設計原則的問題,這里總結一下,希望可以對你有幫助

問題

問題1: 店鋪數據的獲取,將用戶關注的數據放在店鋪信息一起返回

對外提供的接口

List<Shop> getPageShop(final Query query,final Boolean cache);

返回的店鋪信息

public class Shop {

    public static final long DEFAULT_PRIORITY = 10L;

    /**
     * 唯一標識
     */
    private Long id;
   //省略了店鋪其他信息
    /**
     * 用戶關注
     */
    private ShopAttention attention;
}

當調用方設置cache為true時,因為有緩存的存在,獲取不到用戶是否關注的數據。

問題2: 統計店鋪的被關注數導致的慢SQL,導致數據庫cpu飆高,影響到了整個應用

SQL

SELECT shop_id, count(user_Id) as attentionNumber
FROM shop_attention
WHERE shop_id IN
<foreach collection="shopIds" item="shopId" separator="," open="(" close=")">
    #{shopId}
</foreach>
GROUP BY shopId

這兩種代碼的寫法都是基於一個基准

不同的地方的緩存策略不一樣,比如我更新的地方,查找數據時不能緩存,頁面展示的查找的地方需要緩存。 既然服務提供方不知道該不該緩存,那就不管了,交給調用方去管理

這種假設本身沒什么問題,但是忽略了另外一個原則,服務的內聚性。不應該被外部知道的就沒必要暴露給外部

無論是面向過程的C,還是面向對象的語言,都強調內聚性,也就是高內聚,低耦合。單體應用中應當遵循這個原則,微服務同樣遵循這個原則。但是在實際過程中,我們發現做到高內聚並不簡單。我們必須要時時刻刻審視方法/服務的邊界,只有確定好職責邊界,才能寫出高內聚的代碼

問題分析

第一個問題,從緩存的角度來看,是忽略了數據的更新頻繁性以及數據獲取的不同場景。

對於店鋪這樣一個大的聚合根,本身包含的信息很多,有些數據可能會被頻繁更改的,有些則會很少更新的。那么不同的修改頻率,是否緩存/緩存策略自然不同,使用同一個參數Boolean cache來控制顯然不妥

第二個問題,這種統計類的需求使用SQL統計是一種在數據量比較小的情況下的權宜之計,當數據規模增大后,必須要使用離線計算或者流式計算來解決。它本身是一個慢SQL,所以必須要控制號調用量,這種統計的數據量的時效性應該由服務方控制,不需要暴露給調用方。否則就會出現上述的問題,調用方並不清楚其中的邏輯,不走緩存的話就會使得調用次數增加,QPS的增加會導致慢SQL打垮數據庫

解法

緩存更新本身就是一個難解的問題,在微服務化后,多個服務就更加復雜了。涉及到跨服務的多級緩存一致性的問題。

所以對大部分的業務,我們可以遵循這樣的原則來簡單有效處理。

  • 對數據的有效性比較敏感的調用都收斂到服務內部(領域內部應該更合適),不要暴露給調用方,
    領域內部做數據的緩存失效控制
  • 緩存預計算(有些頁面的地方不希望首次打開慢)的邏輯也應該放在領域內控制,不要暴露給調用方。
    在領域內部控制在不同的地方使用不同的緩存策略,比如更新數據的地方需要獲取及時的數據。比如商品的價格,和商品的所屬類目更新頻次不同,需要有不同的過期時間。
  • 跨服務調用為了減少rpc調用,可以再進行一層緩存。因為這些調用可以接受過期的數據,再進行一層緩存沒問題,expired time疊加也沒多大影響(expire time在這邊主要是影響緩存的命中數)

以上述店鋪查詢問題改造為例

在這里插入圖片描述
擴展:如果后續有case在跨服務的調用時,對數據的過期比較敏感,並且在調用方也做了緩存,那就是跨服務的多級緩存一致性的問題。那就需要服務方告知調用方緩存何時失效,使用消息隊列or其他方式來實現。

關注【方丈的寺院】,與方丈一起開始技術修行之路
在這里插入圖片描述

參考

https://martin.kleppmann.com/2012/10/01/rethinking-caching-in-web-apps.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM