日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

程序员过关斩将--从每秒6000写请求谈起

發(fā)布時(shí)間:2023/12/4 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员过关斩将--从每秒6000写请求谈起 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

點(diǎn)擊上方“藍(lán)字”關(guān)注我們

菜菜哥,緊急求助呀

怎么回事?產(chǎn)品經(jīng)理砍你了?

沒(méi)有,只是寫(xiě)了個(gè)新項(xiàng)目,上線就被壓垮了

什么功能,這么強(qiáng)悍?

一個(gè)記錄用戶觀看視頻進(jìn)度信息的功能

那如果用戶基數(shù)大,確實(shí)是需要注意的,那我給你分析一下哈

背景

每一個(gè)片子的幕后,都保留了你的觀看記錄,詳細(xì)的記著你觀看了幾次,跳過(guò)了那些時(shí)長(zhǎng) ,據(jù)說(shuō)根據(jù)這些數(shù)據(jù)可以分析出你喜歡哪個(gè)日本明星,以此來(lái)做定向推送......

雖然看起來(lái)很簡(jiǎn)單的一個(gè)功能,其實(shí)涉及到的數(shù)據(jù)量非常大,極限情況下為你的用戶數(shù)*視頻數(shù)的乘積。

那么在只有兩個(gè)網(wǎng)站服務(wù)器,一臺(tái)sqlserver的情況下,該如何面對(duì)這樣不算大數(shù)據(jù)量的寫(xiě)請(qǐng)求呢?為什么說(shuō)是寫(xiě)請(qǐng)求呢?因?yàn)橛脩粲^看視頻的每一秒你都需要記錄下來(lái),例如:視頻的第十秒用戶觀看了。要想把這個(gè)功能搞定,首先需要定義幾個(gè)事情:

1. 記錄用戶觀看視頻情況的數(shù)據(jù)定義

2. 和客戶端交互的數(shù)據(jù)協(xié)議

3. 數(shù)據(jù)庫(kù)中記錄的數(shù)據(jù)格式

4. 如何解決服務(wù)器寫(xiě)的壓力(畢竟單臺(tái)服務(wù)器請(qǐng)求數(shù)還是比較大)

解決方案

用戶觀看視頻進(jìn)度定義

對(duì)于一個(gè)視頻來(lái)說(shuō),假如有1個(gè)小時(shí)的時(shí)長(zhǎng),這3600秒對(duì)應(yīng)著3600個(gè)是否已經(jīng)觀看的狀態(tài),對(duì)于觀看狀態(tài)來(lái)說(shuō),只有觀看和未觀看兩種狀態(tài),所以一個(gè)bit足以,一個(gè)字節(jié)(byte)有8個(gè)bit,所以一個(gè)byte可以表示8秒的觀看狀態(tài),以此為基礎(chǔ),進(jìn)制越高,同樣數(shù)量的字符表示的狀態(tài)就越多。

客戶端每次上傳新的數(shù)據(jù),需要和服務(wù)端已經(jīng)存在的數(shù)據(jù)做位運(yùn)算,例如:01000? 表示第二秒觀看了 ,客戶端新上傳:00011 表示第4,5秒都觀看了,對(duì)于用戶而言這個(gè)視頻第2,4,5 秒都看過(guò),雖然只是一個(gè)簡(jiǎn)單的運(yùn)算,但是量大的時(shí)候,對(duì)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 二進(jìn)制:??0x88 ???0x40 字符串:? 8840

和客戶端交互協(xié)議

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

數(shù)據(jù)庫(kù)數(shù)據(jù)格式

每種數(shù)據(jù)庫(kù)支持的數(shù)據(jù)類型有差異,所以這里不在過(guò)多敘述,當(dāng)然無(wú)論什么格式,占用空間越少越好,但也要根據(jù)業(yè)務(wù)的計(jì)算量來(lái)綜合考慮。

解決問(wèn)題

cpu性能問(wèn)題

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

//需要新加的數(shù)據(jù)ConcurrentQueue<UserVideoInfo>?AddQueue?=?new?ConcurrentQueue<UserVideoInfo>();//把16進(jìn)制的字符串按照兩位?分割成十進(jìn)制數(shù)組protected?List<int>?ConvertToProgressArray(string?progressString){if?(string.IsNullOrWhiteSpace(progressString)){return?null;}//驗(yàn)證是否為2的倍數(shù)長(zhǎng)度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;}

客戶端請(qǐng)求數(shù)量問(wèn)題

如果同時(shí)一萬(wàn)用戶在同時(shí)觀看視頻,上傳數(shù)據(jù)時(shí)間間隔為2秒,意味著每秒有5000請(qǐng)求。由于這個(gè)業(yè)務(wù)只是一個(gè)用戶log型業(yè)務(wù),何為log型,就是說(shuō)可以容忍一部分?jǐn)?shù)據(jù)丟失,針對(duì)這個(gè)數(shù)據(jù)形態(tài),客戶端可以先在本地做緩沖記錄,沒(méi)有必要一秒上傳一次記錄,例如現(xiàn)在約定的客戶端30秒上傳一次記錄,如果用戶關(guān)掉客戶端,下次啟動(dòng)的時(shí)候會(huì)重新上傳未成功的記錄。

數(shù)據(jù)庫(kù)壓力

如果每次請(qǐng)求都單獨(dú)更新數(shù)據(jù)庫(kù),按照第二條的計(jì)算每秒高達(dá)5000次update請(qǐng)求。用戶觀看每次視頻都加載內(nèi)存中緩存,仔細(xì)分析這種業(yè)務(wù),由于是log型數(shù)據(jù),所以每次你請(qǐng)求沒(méi)有必要都去更新數(shù)據(jù)庫(kù),而是先更新了緩存,然后定時(shí)去更新數(shù)據(jù)庫(kù)。

由于數(shù)據(jù)量的問(wèn)題,所有的更新操作都會(huì)發(fā)送到一個(gè)任務(wù)隊(duì)列,隊(duì)列的執(zhí)行者會(huì)根據(jù)配置批量更新數(shù)據(jù)庫(kù),這樣比單條更新數(shù)據(jù)庫(kù)性能要高很多,其實(shí)這種方案在很多l(xiāng)og型的業(yè)務(wù)中都有使用,批量更新對(duì)數(shù)據(jù)庫(kù)的壓力要小很多,代碼類似以下

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;}//判斷是否有重復(fù)對(duì)象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){}}}

寫(xiě)在最后

其實(shí)這種高IO的操作用sqlserver這種關(guān)系型數(shù)據(jù)庫(kù)反而不好,Nosql在這種簡(jiǎn)單高IO的情境下要很多,改天可以改為redis試一試,估計(jì)會(huì)比sqlserver要好很多。

●程序員修神之路--為什么我會(huì)了SOA,你們還要逼我學(xué)微服務(wù)?

●程序員過(guò)關(guān)斬將--數(shù)據(jù)庫(kù)的樂(lè)觀鎖和悲觀鎖并非真實(shí)的鎖

●程序員修神之路--設(shè)計(jì)一套R(shí)PC框架并非易事

●程序員過(guò)關(guān)斬將--要想獲取我的用戶信息,就得按照規(guī)矩來(lái)

●程序員過(guò)關(guān)斬將--更加優(yōu)雅的Token認(rèn)證方式JWT

●程序員過(guò)關(guān)斬將--cookie和session的關(guān)系其實(shí)很簡(jiǎn)單

●程序員修神之路--用NOSql給高并發(fā)系統(tǒng)加速

●程序員修神之路--高并發(fā)系統(tǒng)設(shè)計(jì)負(fù)載均衡架構(gòu)

●程序員過(guò)關(guān)斬將--你為什么還在用存儲(chǔ)過(guò)程?

●程序員修神之路--問(wèn)世間異步為何物?

●程序員修神之路--提高網(wǎng)站的吞吐

長(zhǎng)按添加菜菜好友

關(guān)注后回復(fù):“大禮包”和“福利”,領(lǐng)取驚喜

點(diǎn)亮在看,你最好看!

總結(jié)

以上是生活随笔為你收集整理的程序员过关斩将--从每秒6000写请求谈起的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。