自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

消息“時序”與“一致性”為何這么難?

開發(fā) 開發(fā)工具
消息時序是分布式系統(tǒng)架構設計中非常難的問題,ta為什么難,有什么常見優(yōu)化實踐,是本文要討論的問題。

[[176390]]

分布式系統(tǒng)中,很多業(yè)務場景都需要考慮消息投遞的時序,例如:

(1)單聊消息投遞,保證發(fā)送方發(fā)送順序與接收方展現(xiàn)順序一致

(2)群聊消息投遞,保證所有接收方展現(xiàn)順序一致

(3)充值支付消息,保證同一個用戶發(fā)起的請求在服務端執(zhí)行序列一致

消息時序是分布式系統(tǒng)架構設計中非常難的問題,ta為什么難,有什么常見優(yōu)化實踐,是本文要討論的問題。

一、為什么時序難以保證,消息一致性難?

為什么分布式環(huán)境下,消息的時序難以保證,這邊簡要分析了幾點原因:

【時鐘不一致】

分布式環(huán)境下,有多個客戶端、有web集群、service集群、db集群,他們都分布在不同的機器上,機器之間都是使用的本地時鐘,而沒有一個所謂的“全局時鐘”,所以不能用“本地時間”來完全決定消息的時序。

【多客戶端(發(fā)送方)】

多服務器不能用“本地時間”進行比較,假設只有一個接收方,能否用接收方本地時間表示時序呢?遺憾的是,由于多個客戶端的存在,即使是一臺服務器的本地時間,也無法表示“絕對時序”。

如上圖,絕對時序上,APP1先發(fā)出msg1,APP2后發(fā)出msg2,都發(fā)往服務器web1,網(wǎng)絡傳輸是不能保證msg1一定先于msg2到達的,所以即使以一臺服務器web1的時間為準,也不能精準描述msg1與msg2的絕對時序。

【服務集群(多接收方)】

多發(fā)送方不能保證時序,假設只有一個發(fā)送方,能否用發(fā)送方的本地時間表示時序呢?遺憾的是,由于多個接收方的存在,無法用發(fā)送方的本地時間,表示“絕對時序”。

如上圖,絕對時序上,web1先發(fā)出msg1,后發(fā)出msg2,由于網(wǎng)絡傳輸及多接收方的存在,無法保證msg1先被接收到先被處理,故也無法保證msg1與msg2的處理時序。

【網(wǎng)絡傳輸與多線程】

多發(fā)送方與多接收方都難以保證絕對時序,假設只有單一的發(fā)送方與單一的接收方,能否保證消息的絕對時序呢?結論是悲觀的,由于網(wǎng)絡傳輸與多線程的存在,仍然不行。

如上圖,web1先發(fā)出msg1,后發(fā)出msg2,即使msg1先到達(網(wǎng)絡傳輸其實還不能保證msg1先到達),由于多線程的存在,也不能保證msg1先被處理完。

【怎么保證絕對時序】

通過上面的分析,假設只有一個發(fā)送方,一個接收方,上下游連接只有一條連接池,通過阻塞的方式通訊,難道不能保證先發(fā)出的消息msg1先處理么?

回答:可以,但吞吐量會非常低,而且單發(fā)送方單接收方單連接池的假設不太成立,高并發(fā)高可用的架構不會允許這樣的設計出現(xiàn)。

二、優(yōu)化實踐

【以客戶端或者服務端的時序為準】

多客戶端、多服務端導致“時序”的標準難以界定,需要一個標尺來衡量時序的先后順序,可以根據(jù)業(yè)務場景,以客戶端或者服務端的時間為準,例如:

(1)郵件展示順序,其實是以客戶端發(fā)送時間為準的,潛臺詞是,發(fā)送方只要將郵件協(xié)議里的時間調(diào)整為1970年或者2970年,就可以在接收方收到郵件后一直“置頂”或者“置底”

(2)秒殺活動時間判斷,肯定得以服務器的時間為準,不可能讓客戶端修改本地時間,就能夠提前秒殺

【服務端能夠生成單調(diào)遞增的id】

這個是毋庸置疑的,不展開討論,例如利用單點寫db的seq/auto_inc_id肯定能生成單調(diào)遞增的id,只是說性能及擴展性會成為潛在瓶頸。對于嚴格時序的業(yè)務場景,可以利用服務器的單調(diào)遞增id來保證時序。

【大部分業(yè)務能接受誤差不大的趨勢遞增id】

消息發(fā)送、帖子發(fā)布時間、甚至秒殺時間都沒有這么精準時序的要求:

(1)同1s內(nèi)發(fā)布的聊天消息時序亂了

(2)同1s內(nèi)發(fā)布的帖子排序不對

(3)用1s內(nèi)發(fā)起的秒殺,由于服務器多臺之間時間有誤差,落到A服務器的秒殺成功了,落到B服務器的秒殺還沒開始,業(yè)務上也是可以接受的(用戶感知不到)

所以,大部分業(yè)務,長時間趨勢遞增的時序就能夠滿足業(yè)務需求,非常短時間的時序誤差一定程度上能夠接受。

關于絕對遞增id,趨勢遞增id的生成架構,詳見文章《細聊分布式ID生成方法》,此處不展開。

【利用單點序列化,可以保證多機相同時序】

數(shù)據(jù)為了保證高可用,需要做到進行數(shù)據(jù)冗余,同一份數(shù)據(jù)存儲在多個地方,怎么保證這些數(shù)據(jù)的修改消息是一致的呢?利用的就是“單點序列化”:

(1)先在一臺機器上序列化操作

(2)再將操作序列分發(fā)到所有的機器,以保證多機的操作序列是一致的,最終數(shù)據(jù)是一致的

典型場景一:數(shù)據(jù)庫主從同步

數(shù)據(jù)庫的主從架構,上游分別發(fā)起了op1,op2,op3三個操作,主庫master來序列化所有的SQL寫操作op3,op1,op2,然后把相同的序列發(fā)送給從庫slave執(zhí)行,以保證所有數(shù)據(jù)庫數(shù)據(jù)的一致性,就是利用“單點序列化”這個思路。

典型場景二:GFS中文件的一致性

GFS(Google File System)為了保證文件的可用性,一份文件要存儲多份,在多個上游對同一個文件進行寫操作時,也是由一個主chunk-server先序列化寫操作,再將序列化后的操作發(fā)送給其他chunk-server,來保證冗余文件的數(shù)據(jù)一致性的。

【單對單聊天,怎么保證發(fā)送順序與接收順序一致】

單人聊天的需求,發(fā)送方A依次發(fā)出了msg1,msg2,msg3三個消息給接收方B,這三條消息能否保證顯示時序的一致性(發(fā)送與顯示的順序一致)?

回答:

(1)如果利用服務器單點序列化時序,可能出現(xiàn)服務端收到消息的時序為msg3,msg1,msg2,與發(fā)出序列不一致

(2)業(yè)務上不需要全局消息一致,只需要對于同一個發(fā)送方A,ta發(fā)給B的消息時序一致就行,常見優(yōu)化方案,在A往B發(fā)出的消息中,加上發(fā)送方A本地的一個絕對時序,來表示接收方B的展現(xiàn)時序

msg1{seq:10, receiver:B,msg:content1 }

msg2{seq:20, receiver:B,msg:content2 }

msg3{seq:30, receiver:B,msg:content3 }

潛在問題:如果接收方B先收到msg3,msg3會先展現(xiàn),后收到msg1和msg2后,會展現(xiàn)在msg3的前面。

無論如何,是按照接收方收到時序展現(xiàn),還是按照服務端收到的時序展現(xiàn),還是按照發(fā)送方發(fā)送時序展現(xiàn),是pm需要思考的點,技術上都能夠實現(xiàn)(接收方按照發(fā)送時序展現(xiàn)是更合理的)。

總之,需要一桿標尺來衡量這個時序。

【群聊消息,怎么保證各接收方收到順序一致】

群聊消息的需求,N個群友在一個群里聊,怎么保證所有群友收到的消息顯示時序一致?

回答:

(1)不能再利用發(fā)送方的seq來保證時序,因為發(fā)送方不單點,時間也不一致

(2)可以利用服務器的單點做序列化

此時群聊的發(fā)送流程為:

(1)sender1發(fā)出msg1,sender2發(fā)出msg2

(2)msg1和msg2經(jīng)過接入集群,服務集群

(3)service層到底層拿一個***seq,來確定接收方展示時序

(4)service拿到msg2的seq是20,msg1的seq是30

(5)通過投遞服務講消息給多個群友,群友即使接收到msg1和msg2的時間不同,但可以統(tǒng)一按照seq來展現(xiàn)

這個方法能實現(xiàn),所有群友的消息展示時序相同。

缺點是,這個生成全局遞增序列號的服務很容易成為系統(tǒng)瓶頸,還有沒有進一步的優(yōu)化方法呢?

思路:群消息其實也不用保證全局消息序列有序,而只要保證一個群內(nèi)的消息有序即可,這樣的話,“id串行化”就成了一個很好的思路。

這個方案中,service層不再需要去一個統(tǒng)一的后端拿全局seq,而是在service連接池層面做細小的改造,保證一個群的消息落在同一個service上,這個service就可以用本地seq來序列化同一個群的所有消息,保證所有群友看到消息的時序是相同的。

關于id串行化的細節(jié),可詳見《利用id串行化解決緩存與數(shù)據(jù)庫一致性問題》,此處不展開。

三、總結

(1)分布式環(huán)境下,消息的有序性是很難的,原因多種多樣:時鐘不一致,多發(fā)送方,多接收方,多線程,網(wǎng)絡傳輸不確定性等

(2)要“有序”,先得有衡量“有序”的標尺,可以是客戶端標尺,可以是服務端標尺

(3)大部分業(yè)務能夠接受大范圍趨勢有序,小范圍誤差;絕對有序的業(yè)務,可以借助服務器絕對時序的能力

(4)單點序列化,是一種常見的保證多機時序統(tǒng)一的方法,典型場景有db主從一致,gfs多文件一致

(5)單對單聊天,只需保證發(fā)出的時序與接收的時序一致,可以利用客戶端seq

(6)群聊,只需保證所有接收方消息時序一致,需要利用服務端seq,方法有兩種,一種單點絕對時序,另一種id串行化

文章來源微信號:gh_10a6b96351a9,已獲授權轉載

責任編輯:趙寧寧 來源: 架構師之路
相關推薦

2019-01-10 09:11:51

消息順序性分布式服務端

2017-07-25 14:38:56

數(shù)據(jù)庫一致性非鎖定讀一致性鎖定讀

2022-12-14 08:23:30

2021-06-22 10:22:08

業(yè)務IT一致性首席信息官

2016-12-19 18:41:09

哈希算法Java數(shù)據(jù)

2021-03-04 06:49:53

RocketMQ事務

2021-02-05 08:00:48

哈希算法?機器

2021-02-02 12:40:50

哈希算法數(shù)據(jù)

2025-03-14 08:00:00

分布式系統(tǒng)服務器一致性

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫

2020-11-24 09:03:41

一致性MySQLMVCC

2024-05-28 00:50:00

RedisMySQL緩存

2022-03-22 09:54:22

Hash算法

2022-10-19 12:22:53

并發(fā)扣款一致性

2021-06-30 21:13:49

CPUCache數(shù)據(jù)

2024-05-08 16:37:17

MySQLRedis數(shù)據(jù)庫

2021-04-24 16:58:03

數(shù)據(jù)庫工具技術

2021-09-15 07:46:42

哈希一致性哈希算法

2021-06-03 15:27:31

RaftSOFAJRaft

2009-06-18 09:18:08

Oracle檢索數(shù)據(jù)數(shù)據(jù)一致性事務恢復
點贊
收藏

51CTO技術棧公眾號