分布式事務的一致性

問題

舉個轉(zhuǎn)賬的例子,小韓給小馬轉(zhuǎn)賬100元遣妥,如何保證兩者賬戶金額正確?

將轉(zhuǎn)賬的過程分成兩步:
1.小韓的賬戶扣減100元
2.小馬的賬戶增加100元

要保證賬戶金額正確,無論先進行哪一步央拖,我們都必須要保證兩步動作要么同時進行,要么同時不進行。

如果小韓和小馬的賬戶在同一系統(tǒng)鲜戒、同一數(shù)據(jù)庫中管理专控,我們可以將兩個操作放到同一個事務中(不考慮賬戶金額是否充足),利用事務原子性我們可以保證賬戶的金額正確遏餐。

begin transaction;
// 小韓的賬戶扣減100
update Account set balance = balance - 100 where user = '小韓'; 
// 小馬的賬戶增加100
update Account set balance = balance + 100 where user = '小馬'; 
commit;

如果小韓和小馬的賬戶不在同一系統(tǒng)管理伦腐,需要使用http請求來操作訂單與庫存的話呢?

可能會碰到的幾種問題:

1.小韓賬戶扣減成功失都,調(diào)用B系統(tǒng)接口失敗
2.小韓賬戶扣減成功柏蘑,系統(tǒng)崩潰
3.小韓賬戶扣減成功,調(diào)用B系統(tǒng)接口超時

什么是分布式事務粹庞?

而隨著微服務架構(gòu)的普及咳焚,一個大型業(yè)務系統(tǒng)往往由若干個子系統(tǒng)構(gòu)成,這些子系統(tǒng)又擁有各自獨立的數(shù)據(jù)庫信粮。往往一個業(yè)務流程需要由多個子系統(tǒng)共同完成黔攒,而且這些操作可能需要在一個事務中完成。在微服務系統(tǒng)中强缘,這些業(yè)務場景是普遍存在的督惰。此時,我們就需要在數(shù)據(jù)庫之上通過某種手段旅掂,實現(xiàn)支持跨數(shù)據(jù)庫的事務支持赏胚,這也就是大家常說的“分布式事務”。

分布式事務的常見解決辦法

1. 兩階段提交(2PC)與三階段提交(3PC)

在分布式系統(tǒng)中商虐,每個節(jié)點雖然可以知道自己操作是否成功觉阅,但是卻無法得知其他節(jié)點上操作是否成功,因此當一個事務跨越了多個節(jié)點的時候秘车,就需要一個協(xié)調(diào)者典勇,能夠掌控到所有節(jié)點的執(zhí)行情況。

兩階段提交

第一階段(提交請求階段):

協(xié)調(diào)者節(jié)點向所有參與者節(jié)點詢問是否可以執(zhí)行提交操作(vote)叮趴,并開始等待各參與者節(jié)點的響應割笙。
參與者節(jié)點執(zhí)行詢問發(fā)起為止的所有事務操作,并將Undo信息和Redo信息寫入日志眯亦。(注意:若成功這里其實每個參與者已經(jīng)執(zhí)行了事務操作)
各參與者節(jié)點響應協(xié)調(diào)者節(jié)點發(fā)起的詢問伤溉。如果參與者節(jié)點的事務操作實際執(zhí)行成功,則它返回一個"同意"消息妻率;如果參與者節(jié)點的事務操作實際執(zhí)行失敗乱顾,則它返回一個"中止"消息。

第二階段(提交執(zhí)行階段):

當協(xié)調(diào)者節(jié)點從所有參與者節(jié)點獲得的相應消息都為"同意"時:

協(xié)調(diào)者節(jié)點向所有參與者節(jié)點發(fā)出"正式提交(commit)"的請求宫静。
參與者節(jié)點正式完成操作走净,并釋放在整個事務期間內(nèi)占用的資源券时。
參與者節(jié)點向協(xié)調(diào)者節(jié)點發(fā)送"完成"消息。
協(xié)調(diào)者節(jié)點受到所有參與者節(jié)點反饋的"完成"消息后伏伯,完成事務革为。

如果任一參與者節(jié)點在第一階段返回的響應消息為"中止",或者 協(xié)調(diào)者節(jié)點在第一階段的詢問超時之前無法獲取所有參與者節(jié)點的響應消息時:

協(xié)調(diào)者節(jié)點向所有參與者節(jié)點發(fā)出"回滾操作(rollback)"的請求舵鳞。
參與者節(jié)點利用之前寫入的Undo信息執(zhí)行回滾,并釋放在整個事務期間內(nèi)占用的資源琢蛤。
參與者節(jié)點向協(xié)調(diào)者節(jié)點發(fā)送"回滾完成"消息蜓堕。
協(xié)調(diào)者節(jié)點受到所有參與者節(jié)點反饋的"回滾完成"消息后,取消事務博其。

不管最后結(jié)果如何套才,第二階段都會結(jié)束當前事務。

2PC實現(xiàn)的思路倒是很簡單慕淡,不過這個思路中存在著幾個的問題:

  1. 執(zhí)行過程中背伴,所有參與節(jié)點都是事務阻塞型的。當參與者占有公共資源時峰髓,其他第三方節(jié)點訪問公共資源不得不處于阻塞狀態(tài)傻寂。
  2. 協(xié)調(diào)者發(fā)生故障。參與者會一直阻塞下去携兵,需要額外的備機進行容錯疾掰。

三階段提交協(xié)議是兩階段提交協(xié)議的改進版本。它通過超時機制解決阻塞的問題徐紧,并且把兩個階段增加為三個階段:

三階段提交

詢問階段:協(xié)調(diào)者詢問參與者是否可以完成指令静檬,協(xié)調(diào)者只需要回答是還是不是,而不需要做真正的操作并级,這個階段超時導致中止

準備階段:如果在詢問階段所有的參與者都返回可以執(zhí)行操作拂檩,協(xié)調(diào)者向參與者發(fā)送預執(zhí)行請求,然后參與者寫redo和undo日志嘲碧,執(zhí)行操作稻励,但是不提交操作;如果在詢問階段任何參與者返回不能執(zhí)行操作的結(jié)果呀潭,則協(xié)調(diào)者向參與者發(fā)送中止請求量没,這里的邏輯與兩階段提交協(xié)議的的準備階段是相似的,這個階段超時導致成功

提交階段:如果每個參與者在準備階段返回準備成功堂竟,也就是預留資源和執(zhí)行操作成功婆排,協(xié)調(diào)者向參與者發(fā)起提交指令,參與者提交資源變更的事務谐鼎,釋放鎖定的資源舰蟆;如果任何一個參與者返回準備失敗趣惠,也就是預留資源或者執(zhí)行操作失敗,協(xié)調(diào)者向參與者發(fā)起中止指令身害,參與者取消已經(jīng)變更的事務味悄,執(zhí)行undo日志,釋放鎖定的資源塌鸯,這里的邏輯與兩階段提交協(xié)議的提交階段一致

3PC的出現(xiàn)就是通過增加復雜度(性能也因此降低)來解決或優(yōu)化2PC中的一部分問題侍瑟。

2.TCC

這個概念最初是由Pat Helland于2007年提出的,在2008年的軟件開發(fā)2.0技術大會上支付寶將其在國內(nèi)推廣開來丙猬。

TCC

TCC編程模式本質(zhì)上也是一種二階段協(xié)議涨颜,不同在于TCC編程模式需要與具體業(yè)務耦合,下面首先看下TCC編程模式步驟:

  1. 所有事務參與方都需要實現(xiàn)try,confirm,cancel接口茧球。
  2. 事務發(fā)起方向事務協(xié)調(diào)器發(fā)起事務請求庭瑰,事務協(xié)調(diào)器調(diào)用所有事務參與者的try方法完成資源的預留,這時候并沒有真正執(zhí)行業(yè)務抢埋,而是為后面具體要執(zhí)行的業(yè)務預留資源弹灭,這里完成了一階段。
  3. 如果事務協(xié)調(diào)器發(fā)現(xiàn)有參與者的try方法預留資源時候發(fā)現(xiàn)資源不夠揪垄,則調(diào)用參與方的cancel方法回滾預留的資源穷吮,需要注意cancel方法需要實現(xiàn)業(yè)務冪等,因為有可能調(diào)用失敿⑴(比如網(wǎng)絡原因參與者接受到了請求酒来,但是由于網(wǎng)絡原因事務協(xié)調(diào)器沒有接受到回執(zhí))會重試。
  4. 如果事務協(xié)調(diào)器發(fā)現(xiàn)所有參與者的try方法返回都OK肪凛,則事務協(xié)調(diào)器調(diào)用所有參與者的confirm方法堰汉,不做資源檢查,直接進行具體的業(yè)務操作伟墙。
  5. 如果協(xié)調(diào)器發(fā)現(xiàn)所有參與者的confirm方法都OK了翘鸭,則分布式事務結(jié)束。
  6. 如果協(xié)調(diào)器發(fā)現(xiàn)有些參與者的confirm方法失敗了戳葵,或者由于網(wǎng)絡原因沒有收到回執(zhí)就乓,則協(xié)調(diào)器會進行重試。這里如果重試一定次數(shù)后還是失敗拱烁,會怎么樣那生蚁?常見的是做事務補償。

繼續(xù)使用上面的轉(zhuǎn)賬例子戏自,我們將賬戶系統(tǒng)簡化成只有賬戶和余額 2 個字段邦投,并且為了適應 DTS 的兩階段設計要求,業(yè)務上又增加了一個凍結(jié)金額(凍結(jié)金額是指在一筆轉(zhuǎn)賬期間擅笔,在一階段的時候使用該字段臨時存儲轉(zhuǎn)賬金額志衣,該轉(zhuǎn)賬額度不能被使用屯援,只有等這筆分布式事務全部提交成功時,才會真正的計入可用余額)念脯。按這樣的設計狞洋,用戶的可用余額等于賬戶余額減去凍結(jié)金額。

在try階段并沒有對A系統(tǒng)和B系統(tǒng)中的余額字段做操作绿店,而是對凍結(jié)金額做的操作吉懊,對應A系統(tǒng)中預留資源操作是對凍結(jié)金額加上100元,這時候A系統(tǒng)賬號上可用錢為余額字段-凍結(jié)金額假勿;對應B系統(tǒng)的操作是對凍結(jié)金額上減去100惕它,這時候B系統(tǒng)賬號上可用的錢為余額字段-凍結(jié)金額。

如果事務協(xié)調(diào)器調(diào)用A系統(tǒng)和B系統(tǒng)的try方法有一個失敗了(比如A系統(tǒng)的賬戶余額不夠了)废登,則調(diào)用cancel進行回滾操作(具體是對凍結(jié)金額做反向操作)。如果調(diào)用try方法都OK了郁惜,則進入confirm階段堡距,confirm階段則不做資源檢查,直接做業(yè)務操作兆蕉,對應A系統(tǒng)要在賬戶余額減去100羽戒,然后凍金額減去100;對應B系統(tǒng)要對賬戶余額字段加上100虎韵,然后凍結(jié)金額加上100易稠。

優(yōu)點:TCC是對二階段的一個改進,try階段通過預留資源的方式避免了同步阻塞資源的情況包蓝。

缺點: 缺點還是比較明顯的驶社,業(yè)務侵入性太強,需要大量開發(fā)工作進行業(yè)務改造测萎,給業(yè)務升級亡电、運維都帶來困難;在一些場景中硅瞧,一些業(yè)務流程可能用TCC不太好定義及處理份乒。

3.本地消息表(非事務消息)
本地消息表

該方案關鍵是要有個消息表。另外腕唧,一般會有個隊列或辖,而且我們一般都會假設這個MQ不丟消息。

本地消息表的基本思路就是:

上游系統(tǒng)在完成任務后枣接,向消息中間件同步地發(fā)送一條消息颂暇,確保消息中間件成功持久化這條消息,然后上游系統(tǒng)可以去做別的事情了但惶;
消息中間件收到消息后負責將該消息同步投遞給相應的下游系統(tǒng)蟀架,并觸發(fā)下游系統(tǒng)的任務執(zhí)行瓣赂;
當下游系統(tǒng)處理成功后,向消息中間件反饋確認應答片拍,消息中間件便可以將該條消息刪除煌集,從而該事務完成。

// 1. 執(zhí)行本地事務
begin transaction;
update Account set balance = balance - 100 where user = '小韓'; 
insert into send_message_log  ...; //消息狀態(tài)為未發(fā)送
commit;
// 2. 發(fā)送消息
// 3. 修改消息狀態(tài)未已發(fā)送

上面是一個理想化的過程捌省,但在實際場景中苫纤,往往會出現(xiàn)如下幾種意外情況:

  • 上游系統(tǒng)向消息中間件發(fā)送消息失敗
  • 消息中間件向下游系統(tǒng)投遞消息失敗

對于第一種情況,需要在上游系統(tǒng)中建立消息重發(fā)機制纲缓【砭校可以在上游系統(tǒng)建立一張本地消息表,并將 任務處理過程 和 向本地消息表中插入消息 這兩個步驟放在一個本地事務中完成祝高。如果向本地消息表插入消息失敗栗弟,那么就會觸發(fā)回滾,之前的任務處理結(jié)果就會被取消工闺。如果這量步都執(zhí)行成功乍赫,那么該本地事務就完成了。接下來會有一個專門的消息發(fā)送者不斷地發(fā)送本地消息表中的消息陆蟆,如果發(fā)送失敗它會返回重試雷厂。當然,也要給消息發(fā)送者設置重試的上限叠殷,一般而言改鲫,達到重試上限仍然發(fā)送失敗,那就意味著消息中間件出現(xiàn)嚴重的問題林束,此時也只有人工干預才能解決問題像棘。

對于第二種情況,消息中間件具有重試機制壶冒,我們可以在消息中間件中設置消息的重試次數(shù)和重試時間間隔讲弄,對于網(wǎng)絡不穩(wěn)定導致的消息投遞失敗的情況,往往重試幾次后消息便可以成功投遞依痊,如果超過了重試的上限仍然投遞失敗避除,那么消息中間件不再投遞該消息,而是記錄在失敗消息表中胸嘁,消息中間件需要提供失敗消息的查詢接口瓶摆,下游系統(tǒng)會定期查詢失敗消息,并將其消費性宏,這就是所謂的“定期校對”群井。

如果重復投遞和定期校對都不能解決問題,往往是因為下游系統(tǒng)出現(xiàn)了嚴重的錯誤毫胜,此時就需要人工干預书斜。

對于不支持事務型消息的消息中間件诬辈,如果要實現(xiàn)分布式事務的話,就可以采用這種方式荐吉。它能夠通過重試機制+定期校對實現(xiàn)分布式事務焙糟,但相比于第二種方案,它達到數(shù)據(jù)一致性的周期較長样屠,而且還需要在上游系統(tǒng)中實現(xiàn)消息重試發(fā)布機制穿撮,以確保消息成功發(fā)布給消息中間件。

因此痪欲,盡量選擇支持事務型消息的消息中間件來實現(xiàn)分布式事務悦穿,如RocketMQ。

4.事務消息

這種實現(xiàn)分布式事務的方式需要通過消息中間件來實現(xiàn)业踢。假設有A和B兩個系統(tǒng)栗柒,分別可以處理任務A和任務B。此時系統(tǒng)A中存在一個業(yè)務流程知举,需要將任務A和任務B在同一個事務中處理瞬沦。下面來介紹基于消息中間件來實現(xiàn)這種分布式事務。

  • 在系統(tǒng)A處理任務A前负蠕,首先向消息中間件發(fā)送一條消息
  • 消息中間件收到后將該條消息持久化,但并不投遞倦畅。此時下游系統(tǒng)B仍然不知道該條消息的存在遮糖。
  • 消息中間件持久化成功后,便向系統(tǒng)A返回一個確認應答叠赐;
  • 系統(tǒng)A收到確認應答后欲账,則可以開始處理任務A;
  • 任務A處理完成后芭概,向消息中間件發(fā)送Commit請求赛不。該請求發(fā)送完成后,對系統(tǒng)A而言罢洲,該事務的處理過程就結(jié)束了踢故,此時它可以處理別的任務了。
  • 消息中間件收到Commit指令后惹苗,便向系統(tǒng)B投遞該消息殿较,從而觸發(fā)任務B的執(zhí)行;
  • 當任務B執(zhí)行完成后桩蓉,系統(tǒng)B向消息中間件返回一個確認應答淋纲,告訴消息中間件該消息已經(jīng)成功消費,此時院究,這個分布式事務完成洽瞬。

上述過程中本涕,如果任務A處理失敗,那么需要進入回滾流程伙窃,如下圖所示:

  • 若系統(tǒng)A在處理任務A時失敗菩颖,那么就會向消息中間件發(fā)送Rollback請求。和發(fā)送Commit請求一樣对供,系統(tǒng)A發(fā)完之后便可以認為回滾已經(jīng)完成位他,它便可以去做其他的事情。
  • 消息中間件收到回滾請求后产场,直接將該消息丟棄鹅髓,而不投遞給系統(tǒng)B,從而不會觸發(fā)系統(tǒng)B的任務B京景。

上面所介紹的Commit和Rollback都屬于理想情況窿冯,但在實際系統(tǒng)中,Commit和Rollback指令都有可能在傳輸途中丟失确徙。那么當出現(xiàn)這種情況的時候醒串,消息中間件是如何保證數(shù)據(jù)一致性呢?——答案就是超時詢問機制鄙皇。

系統(tǒng)A除了實現(xiàn)正常的業(yè)務流程外芜赌,還需提供一個事務詢問的接口,供消息中間件調(diào)用伴逸。當消息中間件收到一條事務型消息后便開始計時缠沈,如果到了超時時間也沒收到系統(tǒng)A發(fā)來的Commit或Rollback指令的話,就會主動調(diào)用系統(tǒng)A提供的事務詢問接口詢問該系統(tǒng)目前的狀態(tài)错蝴。該接口會返回三種結(jié)果:

  • 提交 若獲得的狀態(tài)是“提交”洲愤,則將該消息投遞給系統(tǒng)B。
  • 回滾 若獲得的狀態(tài)是“回滾”顷锰,則直接將條消息丟棄柬赐。
  • 處理中 若獲得的狀態(tài)是“處理中”,則繼續(xù)等待官紫。

整體交互流程如下圖所示:

事務消息

冪等與消息順序

即使沒有MQ肛宋,重試也是無處不在的。所以冪等問題不是因為用到MQ后引入的束世,而是老問題悼吱。

要實現(xiàn)嚴格的順序消息條件非常苛刻:從發(fā)送方到服務方到接受者都是單點單線程良狈。

雖然很難做到消息全局有序后添,但是還是可以通過一些方法做到消息局部有序,說三種通用的解決方案:

  1. 唯一標示
  2. 版本號
  3. 狀態(tài)機

唯一標識

對于本身不具有冪等性的操作,主要思想是為每條事件存儲執(zhí)行結(jié)果遇西,當收到一條事件時我們需要根據(jù)事件的id查詢該事件是否已經(jīng)執(zhí)行過馅精,如果執(zhí)行過直接返回上一次的執(zhí)行結(jié)果,否則調(diào)度執(zhí)行事件粱檀。

版本號

舉個簡單的例子洲敢,一個產(chǎn)品的狀態(tài)有上線/下線狀態(tài)。如果消息1是下線茄蚯,消息2是上線压彭。

消息順序如果和想象的順序不一致。比如應該的順序是12渗常,到來的順序是21壮不。則最后會發(fā)生狀態(tài)錯誤。

如果到來的順序是21皱碘,則先把2存起來询一,待1到來后,先處理1癌椿,再處理2健蕊,這樣順序性要求就都達到了。

狀態(tài)機

業(yè)務流程本身可以表示成一個狀態(tài)機踢俄。那么在生產(chǎn)數(shù)據(jù)的時候可以把目標實體的當前狀態(tài)和目標狀態(tài)寫入消息中缩功,消費的過程中通過消息的當前狀態(tài)和實體實際的當前狀態(tài)進行對比,如果一致再進行處理都办。

舉個例子說明嫡锌,一個工單的狀態(tài)有:未接單,已接單脆丁,上門中世舰,已完成动雹。工單的開始狀態(tài)為未接單槽卫,切換到已接單時發(fā)送 消息1,切換到上門中時發(fā)送 消息2胰蝠,切換到已完成時發(fā)送 消息3歼培。正常情況下,下游接受到的消息順序是123茸塞,但是實際情況下收到的消息順序變成了312躲庄。

那么下游接收到消息3時,判斷狀態(tài)機與當前狀態(tài)不符钾虐,拒絕接受噪窘,要求重發(fā)。然后收到消息1效扫,狀態(tài)是未接單-->已接單倔监。然后是消息2直砂,狀態(tài)是已接單-->上門中。最后處理重發(fā)的消息3浩习,狀態(tài)上門中-->已完成静暂。

參考

https://docs.oracle.com/cd/E11882_01/server.112/e40540/transact.htm#CNCPT117

https://dev.mysql.com/doc/refman/5.6/en/mysql-acid.html

https://zh.wikipedia.org/wiki/ACID

https://www.ibm.com/support/knowledgecenter/en/SSGMCP_5.4.0/product-overview/acid.html

http://www.reibang.com/p/453c6e7ff81c

https://tech.antfin.com/docs/2/46886

https://juejin.im/post/5aa3c7736fb9a028bb189bca

https://tech.meituan.com/mq_design.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谱秽,隨后出現(xiàn)的幾起案子洽蛀,更是在濱河造成了極大的恐慌,老刑警劉巖疟赊,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郊供,死亡現(xiàn)場離奇詭異,居然都是意外死亡听绳,警方通過查閱死者的電腦和手機颂碘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椅挣,“玉大人头岔,你說我怎么就攤上這事∈笾ぃ” “怎么了峡竣?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長量九。 經(jīng)常有香客問我适掰,道長,這世上最難降的妖魔是什么荠列? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任类浪,我火速辦了婚禮,結(jié)果婚禮上肌似,老公的妹妹穿的比我還像新娘费就。我一直安慰自己,他們只是感情好川队,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布力细。 她就那樣靜靜地躺著,像睡著了一般固额。 火紅的嫁衣襯著肌膚如雪眠蚂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天斗躏,我揣著相機與錄音逝慧,去河邊找鬼。 笑死,一個胖子當著我的面吹牛笛臣,可吹牛的內(nèi)容都是我干的栅干。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼捐祠,長吁一口氣:“原來是場噩夢啊……” “哼碱鳞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起踱蛀,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤窿给,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后率拒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崩泡,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年猬膨,在試婚紗的時候發(fā)現(xiàn)自己被綠了角撞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡勃痴,死狀恐怖谒所,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沛申,我是刑警寧澤劣领,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站铁材,受9級特大地震影響尖淘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜著觉,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一村生、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饼丘,春花似錦趁桃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屡穗。三九已至贴捡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間村砂,已是汗流浹背烂斋。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人汛骂。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓罕模,卻偏偏與公主長得像,于是被迫代替她去往敵國和親帘瞭。 傳聞我的和親對象是個殘疾皇子淑掌,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容