如何評估數據適不適合放入Redis中
當項目中引入了Redis做分布式緩存,那么就會面臨這樣的問題:
哪些數據應該放到緩存中?依據是什么?緩存數據是采用主動刷新還是過期自動失效?如果采用過期自動失效,那么失效時間如何制定?正好這兩周我們項目做了相關的評估,把過程記錄下來和大家分享分享;當然過程中用到了很多“笨辦法”,如果你有更好的辦法,也希望能分享給我。
01.項目背景我們的項目是一個純服務平臺,也就是只提供接口服務,并沒有操作頁面的,項目的接口日調用量大約在200萬次,高峰期也就1000萬出頭,因為大部分接口是面向內部系統的,所以大部分請求集中在工作日的9點到21點,高峰期的時候系統的QPS在300-400之間。
因為我們項目數據存儲使用的是MongoDB,理論上支撐這個量級的QPS應該是綽綽有余,但是我有這么幾點觀察和考慮:
MongoDB中雖然是整合好的數據,但是很多場景也不是單條查詢,夸張的時候一個接口可能會返回上百條數據,回參報文就有兩萬多行(不要問我能不能分頁返回......明確告訴你不能);
MongoDB中雖然是整合好的數據,但是很多場景也不是單條查詢,夸張的時候一個接口可能會返回上百條數據,回參報文就有兩萬多行(不要問我能不能分頁返回......明確告訴你不能);
目前項目99.95%的接口響應時間都在幾十到幾百毫秒,基本可以滿足業務的需要,但是還是有0.05%的請求會超過1s響應,偶爾甚至會達到5s、10s;
觀察這些響應時間長的請求,大部分時間消耗在查詢MongoDB上,但是當我將請求報文取出,再次手動調用接口的時候,依然是毫秒級返回;MongoDB的配置一般,時刻都有數據更新,而且我觀察過,響應時間長的這些接口,那個時間點請求量特別大;
MongoDB查詢偶爾會慢的原因我我還在確認,我現在能想到的原因比如:大量寫操作影響讀操作、鎖表、內存小于索引大小等等,暫時就認為是當時那一刻MongoDB有壓力;我觀察過,響應時間長的這些接口,那個時間點請求量特別大,這一點就不在這里具體分析了。
雖然一萬次的請求只有四五次響應時間異常,但是隨著項目接入的請求越來越大,保不齊以后量變產生質變,所以還是盡量將危機扼殺在搖籃里,所以果斷上了Redis做分布式緩存。
02.接口梳理下一步就是對生產環境現有接口進行統計和梳理,確定哪些接口是可以放到緩存中的,所以首先要對每一個接口的調用量有大概的統計,因為沒有接入日志平臺,所以我采用了最笨的辦法,一個一個接口的數嘛。
把工作日某一天全天的日志拉下來,我們四臺應用服務器,每天的日志大概1個G,還好還好;
通過EditPlus這個工具的【在文件中查找】的功能,查詢每個接口當天的調用量,已上線30個接口,有幾分鐘就統計出來了,反正是一次性的工作,索性就手動統計了;
一天也調不了幾次的接口,就直接忽略掉了,我基本上只把日調用量上萬的接口都留下來,進行下一步的分析。
03.字典表、配置類的數據這一類的數據是最適合放在緩存中的,因為更新頻率特別低,甚至有時候insert了之后就再也不做update,如果這類數據的調用量比較大,是一定要放到Redis中的;
至于緩存策略,可以在更新的時候雙寫數據庫和Redis,也可以采用自動失效的方式,當然這個失效時間可以放得比較長一些;針對我們項目,我采用的是半夜12點統一失效的策略,第一因為我們系統這類數據,是夜間通過ETL抽取過來的,每天同步一次,第二就是我們不怕緩存雪崩,沒有那么大的訪問量,夜間更沒有什么訪問量了。
04.明顯是熱點數據的數據有一類數據,很明顯就是熱點數據;
我們就有一個接口,雖然是業務數據,不過數據總量只有幾千條,但是每天的調用量大約在40萬,而且更新頻率不是很高,這類數據放入Redis中也就再適合不過了;至于緩存策略么,因為數據也是從其他系統同步過來的,根據數據同步的時間,我們最終采用一個小時的失效時間。
05.其余數據的評估
其實前兩種數據很容易就能評估出來,關鍵是這類數據的評估:
我們有一個接口日調用量20-30萬,量不大,但是查詢和處理邏輯比較復雜;
基礎數據量太大,無法把所有數據都放入Redis中;
無法把基礎數據直接放入Redis中,因為有多重查詢維度(條件);
無法確定每條數據的調用頻率是怎么樣的,最悲觀的結果,每條數據當天只調用一次,這樣就沒有緩存的必要了。
但是咱也不能一拍腦袋就說:“調用量挺大的,直接放到Redis中吧”,或者“不好評估,算了吧,別放緩存了”,做任何一個決定還是需要有依據的,于是我是這樣做的:
Step1.把該接口當天的所有日志都找出來
幾十個日志文件肯定不能一個一個翻,要么就自己寫個程序把需要的數據扒出來,但是考慮到這個工作可能只做一次,我還是盡量節省一些時間吧。
依然使用EditPlus這個工具的【在文件中查找】的功能,在查詢結果框中【復制所有內容】,花了兩分鐘,就把24萬條日志找出來了。
Step2.把數據導入到數據庫中進行下一步分析每一條日志大概是這樣的:
XXXX.log"(64190,95):2020-3-1716:44:10.092http-nio-8080-exec-5INFO包名.類名:請求參數:args1={"字段1":"XXX","字段2":"YYY"}日志里面我只需要三個內容:請求報文中的字段1和字段2,以及調用時間;怎么摘出來?寫個程序?當然沒問題,但是我懶呀,幾分鐘能做好的事情為什么話花幾十分鐘呢?而且這工作是一次性的,于是:
全文替換:[2020-3-17]替換成[/t2020-3-17],也就是在時間戳前面加一個tab;
全文替換:[{"字段1":"]替換成[/t];
全文替換:[","字段2":"]替換成[/t];
全文替換:["}]替換成[],也就是替換成空;
全選復制,粘貼到excel中,excel自動按照tab換列;
刪除不需要的列,只留字段1和字段2的內容,以及時間戳;
這幾步操作用不了一分鐘。
Step3.調用頻率分析
當把數據進入到數據庫中,就根據我們的需要進行分析了;我們主要想知道,相同的入參會不會重復調用?每次調用間隔的時間是多少?一個SQL搞定:
當然調用間隔時間的統計,這里統計的不精確,具體我不解釋了,你們細品...
總之吧,全天24萬的調用量,其中10萬只調用了一次,14萬的數據會在短時間內重復調用,有一些數據甚至會在幾分鐘之內重復查詢幾十次,所以這個接口還是比較適合放入到Redis中的。
Step4.數據怎么存?
再說說我們的數據用什么格式保存到Redis中,一圖勝千言:
至于緩存更新策略嘛,我們依然使用設置失效時間的方式,根據數據同步的時間和調用統計結果,這個時間設置成15分鐘比較合適。
可以看到在這個評估過程中,我所有操作都保持了“能偷懶就偷懶”這個好習慣,保持高效,善用工具,節約不必要的時間,全部過程花了兩個小時,其中大部分時間是在數據導入,幾乎用了一個半小時,還好在這個過程中我還能做其他的工作。
我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。游戲不支持中文路徑怎么回事
答:
游戲不支持中文路徑是因為游戲的程序代碼中沒有對中文路徑進行編碼處理,導致無法識別中文路徑。
這是因為中文路徑包含了中文字符,而計算機只能識別英文字符和數字,無法直接識別中文字符。
如果想要解決這個問題,可以按照以下步驟進行操作:
1.將游戲安裝路徑更改為英文路徑,例如C:\Games\,這樣游戲就可以正常運行了。
2.如果不想更改路徑,可以使用一些第三方軟件進行中文路徑轉換,將中文路徑轉換為英文路徑,例如LongPathTool等。
這樣就可以在中文路徑下運行游戲了。
需要注意的是,使用第三方軟件可能會存在一定的風險,需要謹慎使用。