新聞中心
go語言select的作用
Go里面提供了一個關(guān)鍵字select,通過select可以監(jiān)聽channel上的數(shù)據(jù)流動。
創(chuàng)新互聯(lián)公司始終堅持【策劃先行,效果至上】的經(jīng)營理念,通過多達(dá)十余年累計超上千家客戶的網(wǎng)站建設(shè)總結(jié)了一套系統(tǒng)有效的全網(wǎng)整合營銷推廣解決方案,現(xiàn)已廣泛運用于各行各業(yè)的客戶,其中包括:成都石雕等企業(yè),備受客戶贊譽。
select的用法與switch語言非常類似,由select開始一個新的選擇塊,每個選擇條件由case語句來描述。
與switch語句相比, select有比較多的限制,其中最大的一條限制就是每個case語句里必須是一個IO操作,大致的結(jié)構(gòu)如下:
在一個select語句中,Go語言會按順序從頭至尾評估每一個發(fā)送和接收的語句。
如果其中的任意一語句可以繼續(xù)執(zhí)行(即沒有被阻塞),那么就從那些可以執(zhí)行的語句中任意選擇一條來使用。
如果沒有任意一條語句可以執(zhí)行(即所有的通道都被阻塞),那么有兩種可能的情況:
如果給出了default語句,那么就會執(zhí)行default語句,同時程序的執(zhí)行會從select語句后的語句中恢復(fù)。
如果沒有default語句,那么select語句將被阻塞,直到至少有一個通信可以進行下去
有時候會出現(xiàn)goroutine阻塞的情況,那么我們?nèi)绾伪苊庹麄€程序進入阻塞的情況呢?我們可以利用select來設(shè)置超時,通過如下的方式實現(xiàn):
select總結(jié):
作用: 用來監(jiān)聽 channel 上的數(shù)據(jù)流動方向。 讀?寫?
select實現(xiàn)fibonacci數(shù)列:
golang實現(xiàn)本地延遲隊列
有個服務(wù)會大量使用延遲消息,進行事件處理。隨著業(yè)務(wù)量不斷上漲。在晚間、節(jié)假日等流量高峰期消息延遲消息隊列限流會導(dǎo)致事件丟失,影響業(yè)務(wù)。與下游溝通后給上調(diào)到了最大限流值,問題依然存在,于是決定自己搞一套降級方案。
下游服務(wù)觸發(fā)限流時,能降級部分流量到本地延遲隊列,把業(yè)務(wù)損失降到最低。
本地延遲隊列承接部分mq流量
流程如下:
1. 使用zset 存儲延遲消息,其中:score為執(zhí)行時間,value為消息體
2. 啟動協(xié)程輪詢zset,獲取score最小的10條數(shù)據(jù),協(xié)程執(zhí)行間隔時間xs
如果最小分值小于等于當(dāng)前時間戳,則發(fā)送消息
若最小分值大于當(dāng)前時間戳,sleep等待執(zhí)行
需要對key進行hash,打散到多個分片中,避免大key和熱key問題,官方大key定義
因此,需保證每個key中value數(shù)量n5000,單個value大小不超過 10240/n kb
假設(shè)承接10w qps,如何處理?
10w qps延遲120s時,最開始消息隊列會積累100000*120=12000000條消息
假如每條消息大小500b,需占用存儲6000000kb = 6000Mb = 6GB
為避免大key問題,每個zset存放4000個元素,需要哈希到3000(3000是key的數(shù)量,可配置)個zset中。
整個集群假設(shè)500臺實例,每個處理qps平均在200左右。
單實例消費能力計算:
遍歷每個zset,針對每個zset起goroutine處理,此示例中需要 起3000個
但是每秒能處理成功的只有200個,其他都在空跑
綜上:
將redis key分片數(shù)n和每次處理的消息數(shù)m進行動態(tài)配置,便于調(diào)整
當(dāng)流量上漲時,調(diào)大分片數(shù)n和單實例單分片并發(fā)數(shù)m即可,假如消費間隔200ms,集群處理能力為n*m*5 qps
n = (qps * 120) / 4000
若qps=q,則計算公式如下
zadd = q
zRange = 500 * 5 * n / 500
zRemove = q
setNx = 500 * 5 * n
若10w qps,則
讀qps = 15000 + 500*3000*5 =7515000,寫 20w
pros
redis 讀寫性能好,可支持較大并發(fā)量,zrange可直接取出到達(dá)執(zhí)行時間的消息
cons
redis 大key問題導(dǎo)致對數(shù)據(jù)量有一定的限制
分片數(shù)量擴縮容會漏消費,會導(dǎo)致事件丟失,業(yè)務(wù)有損
key分片數(shù)量過多時,redis讀寫壓力較大
機器資源浪費,3000個協(xié)程,單實例同一秒只有200個針對處理,其他都在空跑
流程如下:
使用帶緩沖的channel來實現(xiàn)延遲隊列,channel中存放的數(shù)據(jù)為消息體(包括執(zhí)行時間),channel能保證先進先出
從channel中取出數(shù)據(jù)后,判斷是否到達(dá)執(zhí)行時間
到達(dá),同步發(fā)送mq
未到達(dá),sleep 剩余執(zhí)行時間,然后再次執(zhí)行
從channel讀出的數(shù)據(jù)如果未到達(dá)執(zhí)行時間,無法再次放入channel中,需要協(xié)程sleep(執(zhí)行時間-當(dāng)前時間)
10w qps延遲120s時,最開始消息隊列會積累100000*120=12000000條消息,假設(shè)每條消息大小500b,需要6G存儲空間
channel 大小 = (qps*120)/ c , c=集群實例數(shù),c=500 = channel大小為24000,占用12M內(nèi)存
要處理10w qps,分?jǐn)偟矫總€機器的處理速度為 100000/500 = 200,假設(shè)單協(xié)程處理10qps,開20個即可。
pros:
本地存儲,相比redis,讀寫速度更快;協(xié)程數(shù)量少,開銷低;資源利用率較方案一高
cons:
穩(wěn)定性不如redis,實例故障可能導(dǎo)致數(shù)據(jù)丟失;worker池和channel擴縮容依賴服務(wù)重啟,成本高速度慢
綜上,我們以10w qps為例,對比兩種方案在以下指標(biāo)差異,選擇方案二。
附上demo
Go時區(qū)設(shè)置
全球以英國倫敦格林威治作為零度經(jīng)線的起點,每隔15經(jīng)度為一個時區(qū),15度經(jīng)線為該時區(qū)的中央經(jīng)線,共分為24個時區(qū)。由西向東每隔15經(jīng)度增加一個時區(qū),相反的,每向西15經(jīng)度減少一個時區(qū)。中國所在時區(qū)為東8區(qū)。
當(dāng)前時間 time.Now() 返回的是當(dāng)?shù)貢r區(qū)的時間:
CST可以代表如下四個不同的時區(qū):
time.Now() 返回的 +0800 CST 表示的就是中國標(biāo)準(zhǔn)時間,與UTC時間有如下的轉(zhuǎn)化:
Wall Clocks表示掛鐘時間,存儲的是自1970 年 1 月 1 日 0 時 0 分 0 秒以來的時間戳,當(dāng)系統(tǒng)和授時服務(wù)器進行校準(zhǔn)時間時間操作時,有可能造成這一秒是2018-1-1 00:00:00,而下一秒變成了2017-12-31 23:59:59的情況。
Monotonic Clocks,意思是單調(diào)時間的,所謂單調(diào),就是只會不停的往前增長,不受校時操作的影響,這個時間是自進程啟動以來的秒數(shù)。
time.Now() 返回的 m=+0.004002201 就是表示Monotonic Clocks
go語言中如果不設(shè)置指定的時區(qū),通過 time.Now() 獲取到的就是本地時區(qū)
設(shè)置時區(qū)有兩種方式:
固定時區(qū)到東八區(qū)。但這種不是對程序的全局設(shè)置,每次獲取時都需要固定時區(qū)
加載指定時區(qū)。但如果沒有g(shù)o環(huán)境使用這種方式就會加載失敗,因為時區(qū)信息是放在go的安裝包中的。
如果你用第二種方式加載時區(qū),在打docker鏡像時就需要進行時區(qū)相關(guān)的配置,配置文件如下:
參考文章:
golang 讀取服務(wù)器時間 延遲問題怎么解決
簡單減少slave同步延案架構(gòu)做優(yōu)化盡量讓主庫DDL快速執(zhí)行主庫寫數(shù)據(jù)安全性較高比sync_binlog=1innodb_flush_log_at_trx_commit = 1 類設(shè)置slave則需要高數(shù)據(jù)安全完全講sync_binlog設(shè)置0或者關(guān)閉binloginnodb_flushlog設(shè)置0提高sql執(zhí)行效率另外使用比主庫更硬件設(shè)備作slave
mysql-5.6.3已經(jīng)支持線程主復(fù)制原理丁奇類似丁奇表做線程Oracle使用數(shù)據(jù)庫(schema)單位做線程同庫使用同復(fù)制線程
sync_binlog=1
This makes MySQL synchronize the binary log’s contents to disk each time it commits a transaction
默認(rèn)情況并每寫入都binlog與硬盤同步操作系統(tǒng)或機器(僅僅MySQL服務(wù)器)崩潰能binlog語句丟 失要想防止種情況使用sync_binlog全局變量(1安全值慢)使binlog每Nbinlog寫入與硬盤 同步即使sync_binlog設(shè)置1,現(xiàn)崩潰能表內(nèi)容binlog內(nèi)容間存致性使用InnoDB表MySQL服務(wù)器 處理COMMIT語句整事務(wù)寫入binlog并事務(wù)提交InnoDB兩操作間現(xiàn)崩潰重啟事務(wù)InnoDB滾仍 存binlog用--innodb-safe-binlog選項增加InnoDB表內(nèi)容binlog間致性(注釋:MySQL 5.1需要--innodb-safe-binlog;由于引入XA事務(wù)支持該選項作廢)該選項提供更程度安全使每事務(wù) binlog(sync_binlog =1)(默認(rèn)情況真)InnoDB志與硬盤同步該選項效崩潰重啟滾事務(wù)MySQL服務(wù)器binlog剪切滾 InnoDB事務(wù)確保binlog反饋InnoDB表確切數(shù)據(jù)等并使服務(wù)器保持與主服務(wù)器保持同步(接收 滾語句)
innodb_flush_log_at_trx_commit (管用)
抱怨Innodb比MyISAM慢 100倍概忘調(diào)整值默認(rèn)值1意思每事務(wù)提交或事務(wù)外指令都需要志寫入(flush)硬盤費特別使用電 池供電緩存(Battery backed up cache)設(shè)2于運用特別MyISAM表轉(zhuǎn)意思寫入硬盤寫入系統(tǒng)緩存志仍每秒flush硬 盤所般丟失超1-2秒更新設(shè)0更快點安全面比較差即使MySQL掛能丟失事務(wù)數(shù)據(jù)值2整操作系統(tǒng) 掛才能丟數(shù)據(jù)
網(wǎng)站標(biāo)題:go語言設(shè)置延時 go語言 效率
文章網(wǎng)址:http://fisionsoft.com.cn/article/docgggp.html