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

老碼農(nóng)講述后端風云

開發(fā) 開發(fā)工具
原來大伙都居住在一個JVM中,模塊之間都是直接的函數(shù)調(diào)用,如今每個人對外提供的都是基于HTTP的API: 想要訪問別人,需要準備好JSON數(shù)據(jù),然后通過HTTP發(fā)送給過去,人家處理以后,再發(fā)送一個JSON的響應(yīng)。

 經(jīng)過一個月的折騰,終于分家了。

原來的訂單模塊,庫存模塊,積分模塊,支付模塊......搖身一變,成為了一個個獨立系統(tǒng)。

[[247444]]

主人給這些獨立的系統(tǒng)起了一個時髦的名字: 微服務(wù)!

有些微服務(wù)是主人的心頭肉,他們“霸占”了一臺或者多臺機器,像我這個積分模塊,哦不,是積分系統(tǒng),不受人待見,只能委屈一下,和另外幾個家伙共享一臺機器了。

主人說我們現(xiàn)在是分布式的系統(tǒng)了,大家要齊心協(xié)力,共同完成原來的任務(wù)。

原來大伙都居住在一個JVM中,模塊之間都是直接的函數(shù)調(diào)用,如今每個人對外提供的都是基于HTTP的API: 想要訪問別人,需要準備好JSON數(shù)據(jù),然后通過HTTP發(fā)送給過去,人家處理以后,再發(fā)送一個JSON的響應(yīng)。

 

 

[[247446]]

 

真是麻煩,哪怕一次最簡單的溝通都要跨越網(wǎng)絡(luò)了。

重復(fù)執(zhí)行

提起這網(wǎng)絡(luò)我心里就來氣, 想想原來大家都在一個進程中,那調(diào)用速度才叫爽。 現(xiàn)在可好,一是慢如蝸牛,二是不可靠,時不時就會出錯。

30毫秒以前,訂單這家伙調(diào)用我的接口,要給一個叫做U0002的用戶增加200積分,我很樂意地執(zhí)行了。

  1. POST /xxx/BonusPoint/U0002 
  2. {"value:200"

可是,當我想把積分的調(diào)用結(jié)果告訴訂單系統(tǒng)的時候,發(fā)現(xiàn)網(wǎng)絡(luò)已經(jīng)斷開,發(fā)送失敗。 怎么辦? 我想反正已經(jīng)執(zhí)行過了,F(xiàn)orget it !

可是訂單那小子對我這邊的情況一無所知,心里琢磨著也許是我這邊出錯了, 死心眼的他又發(fā)起了同樣的調(diào)用。

對我而言,這個新的調(diào)用和之前的那個沒有一毛錢關(guān)系。(不要忘了,HTTP是沒有狀態(tài)的)我就老老實實地再執(zhí)行一遍。

結(jié)果可想而知,用戶"U0002"的積分被無端地增加了兩次!

訂單小伙說:“這樣不行啊,你得記住我曾經(jīng)發(fā)起過調(diào)用,這樣第二次就不用執(zhí)行了!”

“開玩笑!HTTP是無狀態(tài)的, 我怎么可能記錄你曾經(jīng)的調(diào)用?”

“我們可以增加一點兒狀態(tài), 每次調(diào)用,我給你發(fā)一個Transaction ID, 簡稱TxID,你處理完以后, 需要把這個TxID,UserID, 積分等信息給保存到數(shù)據(jù)庫中。”

  1. POST /xxx/BonusPoint/U0002 
  2. {"txid":"T0001","value":"200"

我說:“這有什么用?”

“每次執(zhí)行的時候,你都可以從數(shù)據(jù)庫中查一下啊,如果看到同樣的TxID已經(jīng)存在了,那就說明之前執(zhí)行過,就不用重復(fù)執(zhí)行了。如果不存在,才真正去執(zhí)行。”

 

 


[[247446]]

 

 

這倒是一個好主意,雖然我增加了一點工作量,需要一點額外的存儲空間(正好借此機會要一個好點兒的服務(wù)器!),但是卻有一個很好的特性: 對于同一個TxID,無論調(diào)用多少次,那執(zhí)行效果就如同執(zhí)行了一次,肯定不會出錯。

后來我們才知道,人類把這個特性叫做冪等性。

一般來說,在后端數(shù)據(jù)不變的情況下,讀操作都是冪等的,不管讀取多少次,得到的結(jié)果都是一樣的。 但是寫操作就不同了,每次操作都會導致數(shù)據(jù)發(fā)生變化。要想讓一個操作可以執(zhí)行多次,而沒有副作用,一定得想辦法記錄下這個操作執(zhí)行過沒有。

遺漏執(zhí)行

我把新API告訴大家: 一定要給我傳遞過來一個TxID啊, 否則別怪我不處理!

這一天,我接收到了兩個HTTP的調(diào)用,***次是這樣的:

  1. POST /xxx/BonusPoint/U0002 
  2. {"txid":"T0010","value":"200"

于是我很高興地執(zhí)行了,并且把T0010這個txid給保存了下來。

然后第二個調(diào)用又來了, 和***個一模一樣:

  1. POST /xxx/BonusPoint/U0002 
  2. {"txid":"T0010","value":"200"

我用T0010一查,數(shù)據(jù)庫已經(jīng)存在,我就知道,不用再處理了, 直接告訴對方:處理完成。

沒想到的是, 用戶很快就抱怨了:為什么我增加了兩次積分(每次200),但實際上只增加了一次呢?

這肯定不是我的鍋, 我這邊沒有任何問題,一切按照設(shè)計執(zhí)行。 我說:“剛才是誰發(fā)起的調(diào)用,檢查下調(diào)用的日志!”

調(diào)查了調(diào)用方的日志才發(fā)現(xiàn),那兩次調(diào)用是兩個系統(tǒng)發(fā)出的!

碰巧,這兩個系統(tǒng)生成了相同的TxID : T0010 , 這就導致我認為是同一個調(diào)用的兩次嘗試, 實際上這是這是完全不同的兩次調(diào)用。

真相大白,TxID是罪魁禍首,可見這個TxID在整個分布式的系統(tǒng)中不能重復(fù),一定得是唯一的才行。

分布式ID

怎么在一個分布式的系統(tǒng)中生成為一個唯一的ID呢?

訂單小伙說:“這很簡單,我們使用UUID就可以了,UUID中包含了網(wǎng)卡的MAC地址,時間戳,隨機數(shù)等信息, 從時間和空間上保證了唯一性, 肯定不會重復(fù)。 ”

UUID可以在本機輕松生成,不用再發(fā)起什么遠程調(diào)用,效率極高。

844A6D2B-CF7B-47C9-9B2B-2AC5C1B1C56B

我說:“只是這長達128位數(shù)字和字母顯得很凌亂,沒法排序,也無法保證有序遞增(尤其是在數(shù)據(jù)庫中,有序的ID更容易確定位置)。”

大家紛紛點頭,UUID被否定。

MySQL提議:“你們竟然把我忘了! 我可以支持自增的(auto_increment)列啊, 天然的ID啊,同志們,絕對可以保證有序性。”

 

 


[[247446]]

 

 

“啊? 用數(shù)據(jù)庫? 你萬一要是罷工了怎么辦? 我們沒有ID可用,什么事兒都干不成了!” 大家一想到慢吞吞的老頭兒,讓大家去依賴它,把生殺大權(quán)交到它的手上,都有點不樂意。

Ngnix說:“你們怕他罷工,就多弄幾個MySQL唄,比如2個。

***個的初始值是1,每次增加2,它產(chǎn)生的ID就是 1, 3, 5,7......

第二個的初始值是2,每次也增加2,它產(chǎn)生的ID就是 2,4,6,8,10......

再弄一個ID生成服務(wù),如果一個MySQL罷工了,就訪問另外一個。”

 

 


[[247446]]

 

 

“如果這個ID生成服務(wù)也完蛋了呢?” 有人問道。

“那可以多部署幾個ID生成服務(wù)啊, 這不就是你們微服務(wù)的優(yōu)勢所在嗎?” Nginx反問。

Ngnix不虧是搞負載均衡的,這個方法可是相當?shù)孛睿?不但提高了可用性, ID還能保持趨勢遞增。

“可是,我每次需要一個TxID,都需要訪問一次數(shù)據(jù)庫啊,這該多慢啊!” 訂單小伙說道。

負責緩存的Redis說道:“不要每次都訪問數(shù)據(jù)庫,學我,緩存一些數(shù)據(jù)到內(nèi)存中。”

“緩存? 怎么緩存?”

Redis 說:“每次訪問數(shù)據(jù)庫的時候,可以獲取一批ID,比如10個, 然后保存的內(nèi)存中,這樣別人就可以直接使用,不用訪問數(shù)據(jù)庫了, 當然,數(shù)據(jù)庫需要記錄下當前的***ID是多少。”

假設(shè)初始的***ID是1 , 獲取10個ID, 即 1,2,3......10 ,保存到內(nèi)存中, 此時 ***ID變成10。

下次再獲取10個,即11,12,13......20 , ***ID變成20。

 

 


[[247446]]

 

 

“可是,你這個唯一的MySQL罷工了,系統(tǒng)還是要停擺啊!” 我說。

Ngnix說:“這種事情很簡單,多加一個MySQL,弄一個一主一從的結(jié)構(gòu), 嗯,如果數(shù)據(jù)沒有及時從Master復(fù)制到Slave的時候,Master就罷工了,此時Slave的中的Max ID就不是***的,那接下來就可能出問題,也許可以搞一個雙主的結(jié)構(gòu)......”

唉,搞一個分布式的唯一ID這么復(fù)雜啊!

Ngnix在那里嘟嘟囔囔,大家都沒有注意到,一個新的服務(wù)上線了,一上來就說:“嗨,大家好,我是snowflake......”

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請通過作者微信公眾號coderising獲取授權(quán)】

 

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2013-08-12 11:18:00

2015-05-12 10:15:15

程序員

2020-09-30 11:14:24

AI碼農(nóng)架構(gòu)

2023-07-16 22:34:55

2018-10-17 22:01:06

2017-09-18 08:21:42

碼農(nóng)AI人工智能

2024-01-15 15:11:03

物聯(lián)網(wǎng)5G數(shù)字孿生

2015-04-21 12:48:37

老碼農(nóng)技術(shù)理想

2023-08-27 21:07:02

2019-04-19 09:09:51

2018-01-16 15:02:20

存儲RAIDSAN

2020-08-05 12:27:18

Go語言碼農(nóng)

2013-09-16 10:03:06

代碼碼農(nóng)

2021-06-21 08:19:26

碼農(nóng)工作工程師

2022-11-30 14:57:39

產(chǎn)業(yè)互聯(lián)網(wǎng)

2013-08-15 10:15:34

英語程序員

2013-11-14 13:58:06

硅谷碼農(nóng)

2013-02-20 09:46:39

軟件開發(fā)程序員

2018-04-08 10:41:31

2018-03-30 15:19:24

點贊
收藏

51CTO技術(shù)棧公眾號