程序员过关斩将--从每秒6000写请求谈起
點擊上方“藍字”關注我們
菜菜哥,緊急求助呀
怎么回事?產(chǎn)品經(jīng)理砍你了?
沒有,只是寫了個新項目,上線就被壓垮了
什么功能,這么強悍?
一個記錄用戶觀看視頻進度信息的功能
那如果用戶基數(shù)大,確實是需要注意的,那我給你分析一下哈
背景
每一個片子的幕后,都保留了你的觀看記錄,詳細的記著你觀看了幾次,跳過了那些時長 ,據(jù)說根據(jù)這些數(shù)據(jù)可以分析出你喜歡哪個日本明星,以此來做定向推送......
雖然看起來很簡單的一個功能,其實涉及到的數(shù)據(jù)量非常大,極限情況下為你的用戶數(shù)*視頻數(shù)的乘積。
那么在只有兩個網(wǎng)站服務器,一臺sqlserver的情況下,該如何面對這樣不算大數(shù)據(jù)量的寫請求呢?為什么說是寫請求呢?因為用戶觀看視頻的每一秒你都需要記錄下來,例如:視頻的第十秒用戶觀看了。要想把這個功能搞定,首先需要定義幾個事情:
1. 記錄用戶觀看視頻情況的數(shù)據(jù)定義
2. 和客戶端交互的數(shù)據(jù)協(xié)議
3. 數(shù)據(jù)庫中記錄的數(shù)據(jù)格式
4. 如何解決服務器寫的壓力(畢竟單臺服務器請求數(shù)還是比較大)
解決方案
用戶觀看視頻進度定義
對于一個視頻來說,假如有1個小時的時長,這3600秒對應著3600個是否已經(jīng)觀看的狀態(tài),對于觀看狀態(tài)來說,只有觀看和未觀看兩種狀態(tài),所以一個bit足以,一個字節(jié)(byte)有8個bit,所以一個byte可以表示8秒的觀看狀態(tài),以此為基礎,進制越高,同樣數(shù)量的字符表示的狀態(tài)就越多。
客戶端每次上傳新的數(shù)據(jù),需要和服務端已經(jīng)存在的數(shù)據(jù)做位運算,例如:01000? 表示第二秒觀看了 ,客戶端新上傳:00011 表示第4,5秒都觀看了,對于用戶而言這個視頻第2,4,5 秒都看過,雖然只是一個簡單的運算,但是量大的時候,對cpu的消耗不容小覷。
第一字節(jié)????第二字節(jié)0?1?2?3?4?5?6?7??0?1?2?3?4?5?6?7? bit:? 1 0?0?0 1 0?0?0??0 1 0?0?0?0?0?0 二進制:??0x88 ???0x40 字符串:? 8840和客戶端交互協(xié)議
用戶觀看視頻的進度實時信息,只有客戶端知道,客戶端需要上傳用戶的觀看進度數(shù)據(jù),和服務端交互的進制可以選擇通用性比較強的16進制,當然你選擇100進制也無所謂,只要雙方能同時支持,并且能正常解析即可
數(shù)據(jù)庫數(shù)據(jù)格式
每種數(shù)據(jù)庫支持的數(shù)據(jù)類型有差異,所以這里不在過多敘述,當然無論什么格式,占用空間越少越好,但也要根據(jù)業(yè)務的計算量來綜合考慮。
解決問題
cpu性能問題
畢竟要把用戶每次最新的觀看數(shù)據(jù)和老數(shù)據(jù)做合并工作,在用戶量大的情況下不容小覷。在綜合了各種條件之后,最終采用10進制來做合并工作,客戶端上傳上來16進制數(shù)據(jù),然后轉化為十進制,然后和觀看記錄(10進制)做合并運算,這部分cpu省略不了,具體轉化程序為:
//需要新加的數(shù)據(jù)ConcurrentQueue<UserVideoInfo>?AddQueue?=?new?ConcurrentQueue<UserVideoInfo>();//把16進制的字符串按照兩位?分割成十進制數(shù)組protected?List<int>?ConvertToProgressArray(string?progressString){if?(string.IsNullOrWhiteSpace(progressString)){return?null;}//驗證是否為2的倍數(shù)長度if?(progressString.Length?%?2?!=?0){return?null;}var?proStrSpan?=?progressString.AsSpan();List<int>?ret?=?new?List<int>();int?i?=?0;while?(i?<?proStrSpan.Length){ret.Add(int.Parse(proStrSpan.Slice(i,?2).ToString(),?System.Globalization.NumberStyles.HexNumber));?;i?=?i?+?2;}return?ret;}客戶端請求數(shù)量問題
如果同時一萬用戶在同時觀看視頻,上傳數(shù)據(jù)時間間隔為2秒,意味著每秒有5000請求。由于這個業(yè)務只是一個用戶log型業(yè)務,何為log型,就是說可以容忍一部分數(shù)據(jù)丟失,針對這個數(shù)據(jù)形態(tài),客戶端可以先在本地做緩沖記錄,沒有必要一秒上傳一次記錄,例如現(xiàn)在約定的客戶端30秒上傳一次記錄,如果用戶關掉客戶端,下次啟動的時候會重新上傳未成功的記錄。
數(shù)據(jù)庫壓力
如果每次請求都單獨更新數(shù)據(jù)庫,按照第二條的計算每秒高達5000次update請求。用戶觀看每次視頻都加載內(nèi)存中緩存,仔細分析這種業(yè)務,由于是log型數(shù)據(jù),所以每次你請求沒有必要都去更新數(shù)據(jù)庫,而是先更新了緩存,然后定時去更新數(shù)據(jù)庫。
由于數(shù)據(jù)量的問題,所有的更新操作都會發(fā)送到一個任務隊列,隊列的執(zhí)行者會根據(jù)配置批量更新數(shù)據(jù)庫,這樣比單條更新數(shù)據(jù)庫性能要高很多,其實這種方案在很多l(xiāng)og型的業(yè)務中都有使用,批量更新對數(shù)據(jù)庫的壓力要小很多,代碼類似以下
public?async?Task<int>?AddUserVideoData(UserVideoInfo?data,?DBProcessEnum?processType?=?DBProcessEnum.Update){if(processType==?DBProcessEnum.Add){AddQueue.Enqueue(data);}return?1;}void?MulProcessData(){//每次更新的條數(shù)int?maxNumber?=?50;List<UserVideoInfo>?data?=?new?List<UserVideoInfo>();while?(true){if?(data?==?null){data?=?new?List<UserVideoInfo>();}try{???????????????????if?(!AddQueue.Any()?&&?!UpdateQueue.Any()){System.Threading.Thread.Sleep(500);}???????????????????else{//先處理?需要更新的data.Clear();while?(data.Count?<=?maxNumber?&&?AddQueue.Any()){if?(!AddQueue.TryDequeue(out?UserVideoInfo?value)){????????????????????????????????continue;}//判斷是否有重復對象if?(data.Any(s?=>?s.UserId?==?value.UserId?&&?s.VideoId?==?value.VideoId)){var?exsitItem?=?data.First(s?=>?s.UserId?==?value.UserId?&&?s.VideoId?==?value.VideoId);exsitItem?=?value;}else{data.Add(value);}}if?(data?!=?null?&&?data.Any()){var?ret?=?UserVideoProgressProxy.Add(data);}}}catch?(Exception?err){}}}寫在最后
其實這種高IO的操作用sqlserver這種關系型數(shù)據(jù)庫反而不好,Nosql在這種簡單高IO的情境下要很多,改天可以改為redis試一試,估計會比sqlserver要好很多。
完
●程序員修神之路--為什么我會了SOA,你們還要逼我學微服務?
●程序員過關斬將--數(shù)據(jù)庫的樂觀鎖和悲觀鎖并非真實的鎖
●程序員修神之路--設計一套RPC框架并非易事
●程序員過關斬將--要想獲取我的用戶信息,就得按照規(guī)矩來
●程序員過關斬將--更加優(yōu)雅的Token認證方式JWT
●程序員過關斬將--cookie和session的關系其實很簡單
●程序員修神之路--用NOSql給高并發(fā)系統(tǒng)加速
●程序員修神之路--高并發(fā)系統(tǒng)設計負載均衡架構
●程序員過關斬將--你為什么還在用存儲過程?
●程序員修神之路--問世間異步為何物?
●程序員修神之路--提高網(wǎng)站的吞吐
長按添加菜菜好友
關注后回復:“大禮包”和“福利”,領取驚喜點亮在看,你最好看!
總結
以上是生活随笔為你收集整理的程序员过关斩将--从每秒6000写请求谈起的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: C# 视频监控系统
- 下一篇: Magicodes.IE 2.2里程碑需
