溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么從每秒6000寫請求談起

發布時間:2021-10-21 14:36:01 來源:億速云 閱讀:123 作者:iii 欄目:編程語言

這篇文章主要介紹“怎么從每秒6000寫請求談起”,在日常操作中,相信很多人在怎么從每秒6000寫請求談起問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么從每秒6000寫請求談起”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

背景

每一個片子的幕后,都保留了你的觀看記錄,詳細的記著你觀看了幾次,跳過了那些時長 ,據說根據這些數據可以分析出你喜歡哪個日本明星,以此來做定向推送......

雖然看起來很簡單的一個功能,其實涉及到的數據量非常大,極限情況下為你的用戶數*視頻數的乘積。

那么在只有兩個網站服務器,一臺sqlserver的情況下,該如何面對這樣不算大數據量的寫請求呢?為什么說是寫請求呢?因為用戶觀看視頻的每一秒你都需要記錄下來,例如:視頻的第十秒用戶觀看了。要想把這個功能搞定,首先需要定義幾個事情:

  1. 記錄用戶觀看視頻情況的數據定義

  2. 和客戶端交互的數據協議

  3. 數據庫中記錄的數據格式

  4. 如何解決服務器寫的壓力(畢竟單臺服務器請求數還是比較大)

解決方案

用戶觀看視頻進度定義

對于一個視頻來說,假如有1個小時的時長,這3600秒對應著3600個是否已經觀看的狀態,對于觀看狀態來說,只有觀看和未觀看兩種狀態,所以一個bit足以,一個字節(byte)有8個bit,所以一個byte可以表示8秒的觀看狀態,以此為基礎,進制越高,同樣數量的字符表示的狀態就越多。

客戶端每次上傳新的數據,需要和服務端已經存在的數據做位運算,例如: 01000 表示第二秒觀看了 ,客戶端新上傳:00011 表示第4,5秒都觀看了,對于用戶而言這個視頻第2,4,5 秒都看過,雖然只是一個簡單的運算,但是量大的時候,對cpu的消耗不容小覷。

第一字節    第二字節
  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
和客戶端交互協議

用戶觀看視頻的進度實時信息,只有客戶端知道,客戶端需要上傳用戶的觀看進度數據,和服務端交互的進制可以選擇通用性比較強的16進制,當然你選擇100進制也無所謂,只要雙方能同時支持,并且能正常解析即可

數據庫數據格式

每種數據庫支持的數據類型有差異,所以這里不在過多敘述,當然無論什么格式,占用空間越少越好,但也要根據業務的計算量來綜合考慮。

解決問題

cpu性能問題

畢竟要把用戶每次最新的觀看數據和老數據做合并工作,在用戶量大的情況下不容小覷。在綜合了各種條件之后,最終采用10進制來做合并工作,客戶端上傳上來16進制數據,然后轉化為十進制,然后和觀看記錄(10進制)做合并運算,這部分cpu省略不了,具體轉化程序為:

 //需要新加的數據
        ConcurrentQueue<UserVideoInfo> AddQueue = new ConcurrentQueue<UserVideoInfo>();

//把16進制的字符串按照兩位 分割成十進制數組
        protected List<int> ConvertToProgressArray(string progressString)
        {
            if (string.IsNullOrWhiteSpace(progressString))
            {
                return null;
            }
            //驗證是否為2的倍數長度
            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;
        }
客戶端請求數量問題

如果同時一萬用戶在同時觀看視頻,上傳數據時間間隔為2秒,意味著每秒有5000請求。由于這個業務只是一個用戶log型業務,何為log型,就是說可以容忍一部分數據丟失,針對這個數據形態,客戶端可以先在本地做緩沖記錄,沒有必要一秒上傳一次記錄,例如現在約定的客戶端30秒上傳一次記錄,如果用戶關掉客戶端,下次啟動的時候會重新上傳未成功的記錄。

數據庫壓力

如果每次請求都單獨更新數據庫,按照第二條的計算每秒高達5000次update請求。用戶觀看每次視頻都加載內存中緩存,仔細分析這種業務,由于是log型數據,所以每次你請求沒有必要都去更新數據庫,而是先更新了緩存,然后定時去更新數據庫。

由于數據量的問題,所有的更新操作都會發送到一個任務隊列,隊列的執行者會根據配置批量更新數據庫,這樣比單條更新數據庫性能要高很多,其實這種方案在很多log型的業務中都有使用,批量更新對數據庫的壓力要小很多,代碼類似以下

public async Task<int> AddUserVideoData(UserVideoInfo data, DBProcessEnum processType = DBProcessEnum.Update)
        {
            if(processType== DBProcessEnum.Add)
            {
                AddQueue.Enqueue(data);
            }
           
            return 1;
        }

 void MulProcessData()
        {
            //每次更新的條數
            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)
                {
                    
                }


            }
        }

到此,關于“怎么從每秒6000寫請求談起”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女