分布式事務(wù)最經(jīng)典的七種解決方案,這次可以懂了吧

隨著業(yè)務(wù)的快速發(fā)展尚骄、業(yè)務(wù)復(fù)雜度越來越高块差,幾乎每個(gè)公司的系統(tǒng)都會(huì)從單體走向分布式,特別是轉(zhuǎn)向微服務(wù)架構(gòu)倔丈。隨之而來就必然遇到分布式事務(wù)這個(gè)難題憨闰,這篇文章總結(jié)了分布式事務(wù)最經(jīng)典的解決方案,分享給大家需五。

基礎(chǔ)理論

在講解具體方案之前鹉动,我們先了解一下分布式事務(wù)所涉及到的基礎(chǔ)理論知識(shí)。

我們拿轉(zhuǎn)賬作為例子宏邮,A需要轉(zhuǎn)100元給B泽示,那么需要給A的余額-100元,給B的余額+100元蜜氨,整個(gè)轉(zhuǎn)賬要保證械筛,A-100和B+100同時(shí)成功,或者同時(shí)失敗飒炎”湟蹋看看在各種場景下,是如何解決這個(gè)問題的厌丑。

事務(wù)

把多條語句作為一個(gè)整體進(jìn)行操作的功能定欧,被稱為數(shù)據(jù)庫事務(wù)。數(shù)據(jù)庫事務(wù)可以確保該事務(wù)范圍內(nèi)的所有操作都可以全部成功或者全部失敗怒竿。

事務(wù)具有 4 個(gè)屬性:原子性砍鸠、一致性、隔離性耕驰、持久性爷辱。這四個(gè)屬性通常稱為 ACID 特性。

  • Atomicity(原子性):一個(gè)事務(wù)中的所有操作朦肘,要么全部完成饭弓,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)媒抠。事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤弟断,會(huì)被恢復(fù)到事務(wù)開始前的狀態(tài),就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣趴生。
  • Consistency(一致性):在事務(wù)開始之前和事務(wù)結(jié)束以后阀趴,數(shù)據(jù)庫的完整性沒有被破壞。完整性包括外鍵約束苍匆、應(yīng)用定義的等約束不會(huì)被破壞刘急。
  • Isolation(隔離性):數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對其數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致浸踩。
  • Durability(持久性):事務(wù)處理結(jié)束后叔汁,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失检碗。

分布式事務(wù)

銀行跨行轉(zhuǎn)賬業(yè)務(wù)是一個(gè)典型分布式事務(wù)場景据块,假設(shè)A需要跨行轉(zhuǎn)賬給B,那么就涉及兩個(gè)銀行的數(shù)據(jù)后裸,無法通過一個(gè)數(shù)據(jù)庫的本地事務(wù)保證轉(zhuǎn)賬的ACID瑰钮,只能夠通過分布式事務(wù)來解決。

分布式事務(wù)就是指事務(wù)的發(fā)起者微驶、資源及資源管理器和事務(wù)協(xié)調(diào)者分別位于分布式系統(tǒng)的不同節(jié)點(diǎn)之上浪谴。在上述轉(zhuǎn)賬的業(yè)務(wù)中,用戶A-100操作和用戶B+100操作不是位于同一個(gè)節(jié)點(diǎn)上因苹。本質(zhì)上來說苟耻,分布式事務(wù)就是為了保證在分布式場景下,數(shù)據(jù)操作的正確執(zhí)行扶檐。

分布式事務(wù)在分布式環(huán)境下凶杖,為了滿足可用性、性能與降級(jí)服務(wù)的需要款筑,降低一致性與隔離性的要求智蝠,一方面遵循 BASE 理論(BASE相關(guān)理論腾么,涉及內(nèi)容非常多,感興趣的同學(xué)杈湾,可以參考BASE理論):

基本業(yè)務(wù)可用性(Basic Availability)
柔性狀態(tài)(Soft state)
最終一致性(Eventual consistency)
同樣的解虱,分布式事務(wù)也部分遵循 ACID 規(guī)范:

原子性:嚴(yán)格遵循
一致性:事務(wù)完成后的一致性嚴(yán)格遵循;事務(wù)中的一致性可適當(dāng)放寬
隔離性:并行事務(wù)間不可影響漆撞;事務(wù)中間結(jié)果可見性允許安全放寬
持久性:嚴(yán)格遵循

分布式事務(wù)的解決方案

兩階段提交/XA

XA是由X/Open組織提出的分布式事務(wù)的規(guī)范殴泰,XA規(guī)范主要定義了(全局)事務(wù)管理器(TM)和(局部)資源管理器(RM)之間的接口。本地的數(shù)據(jù)庫如mysql在XA中扮演的是RM角色

XA一共分為兩階段:

第一階段(prepare):即所有的參與者RM準(zhǔn)備執(zhí)行事務(wù)并鎖住需要的資源浮驳。參與者ready時(shí)悍汛,向TM報(bào)告已準(zhǔn)備就緒。
第二階段 (commit/rollback):當(dāng)事務(wù)管理者(TM)確認(rèn)所有參與者(RM)都ready后至会,向所有參與者發(fā)送commit命令离咐。
目前主流的數(shù)據(jù)庫基本都支持XA事務(wù),包括mysql奋献、oracle健霹、sqlserver、postgre

XA 事務(wù)由一個(gè)或多個(gè)資源管理器(RM)瓶蚂、一個(gè)事務(wù)管理器(TM)和一個(gè)應(yīng)用程序(ApplicationProgram)組成糖埋。

把上面的轉(zhuǎn)賬作為例子,一個(gè)成功完成的XA事務(wù)時(shí)序圖如下:

如果有任何一個(gè)參與者prepare失敗窃这,那么TM會(huì)通知所有完成prepare的參與者進(jìn)行回滾瞳别。

XA事務(wù)的特點(diǎn)是:

  • 簡單易理解,開發(fā)較容易
  • 對資源進(jìn)行了長時(shí)間的鎖定杭攻,并發(fā)度低

如果讀者想要進(jìn)一步研究XA祟敛,go語言可參考DTM,java語言可參考seata

SAGA

Saga是這一篇數(shù)據(jù)庫論文saga提到的一個(gè)方案兆解。其核心思想是將長事務(wù)拆分為多個(gè)本地短事務(wù)馆铁,由Saga事務(wù)協(xié)調(diào)器協(xié)調(diào),如果正常結(jié)束那就正常完成锅睛,如果某個(gè)步驟失敗埠巨,則根據(jù)相反順序一次調(diào)用補(bǔ)償操作。

把上面的轉(zhuǎn)賬作為例子现拒,一個(gè)成功完成的SAGA事務(wù)時(shí)序圖如下:

分布式事務(wù)最經(jīng)典的七種解決方案辣垒,這次可以懂了吧

SAGA事務(wù)的特點(diǎn):

  • 并發(fā)度高,不用像XA事務(wù)那樣長期鎖定資源
  • 需要定義正常操作以及補(bǔ)償操作印蔬,開發(fā)量比XA大
  • 一致性較弱勋桶,對于轉(zhuǎn)賬,可能發(fā)生A用戶已扣款,最后轉(zhuǎn)賬又失敗的情況

論文里面的SAGA內(nèi)容較多例驹,包括兩種恢復(fù)策略捐韩,包括分支事務(wù)并發(fā)執(zhí)行,我們這里的討論眠饮,僅包括最簡單的SAGA

SAGA適用的場景較多奥帘,長事務(wù)適用,對中間結(jié)果不敏感的業(yè)務(wù)場景適用

如果讀者想要進(jìn)一步研究SAGA仪召,go語言可參考DTM,java語言可參考seata

TCC

關(guān)于 TCC(Try-Confirm-Cancel)的概念松蒜,最早是由 Pat Helland 于 2007 年發(fā)表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出扔茅。

TCC分為3個(gè)階段

  • Try 階段:嘗試執(zhí)行,完成所有業(yè)務(wù)檢查(一致性), 預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性)
  • Confirm 階段:確認(rèn)執(zhí)行真正執(zhí)行業(yè)務(wù)秸苗,不作任何業(yè)務(wù)檢查召娜,只使用 Try 階段預(yù)留的業(yè)務(wù)資源,Confirm 操作要求具備冪等設(shè)計(jì)惊楼,Confirm 失敗后需要進(jìn)行重試玖瘸。
  • Cancel 階段:取消執(zhí)行,釋放 Try 階段預(yù)留的業(yè)務(wù)資源檀咙。Cancel 階段的異常和 Confirm 階段異常處理方案基本上一致雅倒,要求滿足冪等設(shè)計(jì)。

把上面的轉(zhuǎn)賬作為例子弧可,通常會(huì)在Try里面凍結(jié)金額蔑匣,但不扣款,Confirm里面扣款棕诵,Cancel里面解凍金額裁良,一個(gè)成功完成的TCC事務(wù)時(shí)序圖如下:

TCC特點(diǎn)如下:

  • 并發(fā)度較高,無長期資源鎖定校套。
  • 開發(fā)量較大价脾,需要提供Try/Confirm/Cancel接口。
  • 一致性較好笛匙,不會(huì)發(fā)生SAGA已扣款最后又轉(zhuǎn)賬失敗的情況
  • TCC適用于訂單類業(yè)務(wù)侨把,對中間狀態(tài)有約束的業(yè)務(wù)

如果讀者想要進(jìn)一步研究TCC,go語言可參考DTM膳算,java語言可參考seata

本地消息表

本地消息表這個(gè)方案最初是 ebay 架構(gòu)師 Dan Pritchett 在 2008 年發(fā)表給 ACM 的文章座硕。設(shè)計(jì)核心是將需要分布式處理的任務(wù)通過消息的方式來異步確保執(zhí)行。

大致流程如下:

寫本地消息和業(yè)務(wù)操作放在一個(gè)事務(wù)里涕蜂,保證了業(yè)務(wù)和發(fā)消息的原子性华匾,要么他們?nèi)汲晒Γ慈际 ?/p>

容錯(cuò)機(jī)制:

  • 扣減余額事務(wù) 失敗時(shí),事務(wù)直接回滾蜘拉,無后續(xù)步驟
  • 輪序生產(chǎn)消息失敗萨西, 增加余額事務(wù)失敗都會(huì)進(jìn)行重試

本地消息表的特點(diǎn):

  • 長事務(wù)僅需要分拆成多個(gè)任務(wù),使用簡單
  • 生產(chǎn)者需要額外的創(chuàng)建消息表
  • 每個(gè)本地消息表都需要進(jìn)行輪詢
  • 消費(fèi)者的邏輯如果無法通過重試成功旭旭,那么還需要更多的機(jī)制谎脯,來回滾操作

適用于可異步執(zhí)行的業(yè)務(wù),且后續(xù)操作無需回滾的業(yè)務(wù)

事務(wù)消息

在上述的本地消息表方案中持寄,生產(chǎn)者需要額外創(chuàng)建消息表源梭,還需要對本地消息表進(jìn)行輪詢,業(yè)務(wù)負(fù)擔(dān)較重稍味。阿里開源的RocketMQ 4.3之后的版本正式支持事務(wù)消息废麻,該事務(wù)消息本質(zhì)上是把本地消息表放到RocketMQ上,解決生產(chǎn)端的消息發(fā)送與本地事務(wù)執(zhí)行的原子性問題模庐。

事務(wù)消息發(fā)送及提交:

  • 發(fā)送消息(half消息)
  • 服務(wù)端存儲(chǔ)消息烛愧,并響應(yīng)消息的寫入結(jié)果
  • 根據(jù)發(fā)送結(jié)果執(zhí)行本地事務(wù)(如果寫入失敗,此時(shí)half消息對業(yè)務(wù)不可見掂碱,本地邏輯不執(zhí)行)
  • 根據(jù)本地事務(wù)狀態(tài)執(zhí)行Commit或者Rollback(Commit操作發(fā)布消息怜姿,消息對消費(fèi)者可見)

正常發(fā)送的流程圖如下:

補(bǔ)償流程:

對沒有Commit/Rollback的事務(wù)消息(pending狀態(tài)的消息),從服務(wù)端發(fā)起一次“回查”
Producer收到回查消息疼燥,返回消息對應(yīng)的本地事務(wù)的狀態(tài)沧卢,為Commit或者Rollback
事務(wù)消息方案與本地消息表機(jī)制非常類似,區(qū)別主要在于原先相關(guān)的本地表操作替換成了一個(gè)反查接口

事務(wù)消息特點(diǎn)如下:

  • 長事務(wù)僅需要分拆成多個(gè)任務(wù)悴了,并提供一個(gè)反查接口搏恤,使用簡單
  • 消費(fèi)者的邏輯如果無法通過重試成功,那么還需要更多的機(jī)制湃交,來回滾操作

適用于可異步執(zhí)行的業(yè)務(wù)熟空,且后續(xù)操作無需回滾的業(yè)務(wù)

如果讀者想要進(jìn)一步研究事務(wù)消息,可參考rocketmq搞莺,為了方便大家學(xué)習(xí)事務(wù)消息息罗,DTM也提供了簡單實(shí)現(xiàn)

最大努力通知

發(fā)起通知方通過一定的機(jī)制最大努力將業(yè)務(wù)處理結(jié)果通知到接收方。具體包括:

有一定的消息重復(fù)通知機(jī)制才沧。因?yàn)榻邮胀ㄖ娇赡軟]有接收到通知迈喉,此時(shí)要有一定的機(jī)制對消息重復(fù)通知。
消息校對機(jī)制温圆。如果盡最大努力也沒有通知到接收方挨摸,或者接收方消費(fèi)消息后要再次消費(fèi),此時(shí)可由接收方主動(dòng)向通知方查詢消息信息來滿足需求岁歉。
前面介紹的的本地消息表和事務(wù)消息都屬于可靠消息得运,與這里介紹的最大努力通知有什么不同?

可靠消息一致性,發(fā)起通知方需要保證將消息發(fā)出去熔掺,并且將消息發(fā)到接收通知方饱搏,消息的可靠性關(guān)鍵由發(fā)起通知方來保證。

最大努力通知置逻,發(fā)起通知方盡最大的努力將業(yè)務(wù)處理結(jié)果通知為接收通知方推沸,但是可能消息接收不到,此時(shí)需要接收通知方主動(dòng)調(diào)用發(fā)起通知方的接口查詢業(yè)務(wù)處理結(jié)果券坞,通知的可靠性關(guān)鍵在接收通知方鬓催。

解決方案上,最大努力通知需要:

  • 提供接口恨锚,讓接受通知放能夠通過接口查詢業(yè)務(wù)處理結(jié)果
  • 消息隊(duì)列ACK機(jī)制深浮,消息隊(duì)列按照間隔1min、5min眠冈、10min、30min菌瘫、1h蜗顽、2h、5h雨让、10h的方式雇盖,逐步拉大通知間隔 ,直到達(dá)到通知要求的時(shí)間窗口上限栖忠。之后不再通知

最大努力通知適用于業(yè)務(wù)通知類型崔挖,例如微信交易的結(jié)果,就是通過最大努力通知方式通知各個(gè)商戶庵寞,既有回調(diào)通知狸相,也有交易查詢接口

AT事務(wù)模式

這是阿里開源項(xiàng)目seata中的一種事務(wù)模式,在螞蟻金服也被稱為FMT捐川。優(yōu)點(diǎn)是該事務(wù)模式使用方式脓鹃,類似XA模式,業(yè)務(wù)無需編寫各類補(bǔ)償操作古沥,回滾由框架自動(dòng)完成瘸右,缺點(diǎn)也類似AT,存在較長時(shí)間的鎖岩齿,不滿足高并發(fā)的場景太颤。有興趣的同學(xué)可以參考seata-AT

分布式事務(wù)中的網(wǎng)絡(luò)異常

在分布式事務(wù)的各個(gè)環(huán)節(jié)都有可能出現(xiàn)網(wǎng)絡(luò)以及業(yè)務(wù)故障等問題,這些問題需要分布式事務(wù)的業(yè)務(wù)方做到防空回滾盹沈,冪等龄章,防懸掛三個(gè)特性,下面以TCC事務(wù)說明這些異常情況:

空回滾:

在沒有調(diào)用 TCC 資源 Try 方法的情況下,調(diào)用了二階段的 Cancel 方法瓦堵,Cancel 方法需要識(shí)別出這是一個(gè)空回滾基协,然后直接返回成功。

出現(xiàn)原因是當(dāng)一個(gè)分支事務(wù)所在服務(wù)宕機(jī)或網(wǎng)絡(luò)異常菇用,分支事務(wù)調(diào)用記錄為失敗澜驮,這個(gè)時(shí)候其實(shí)是沒有執(zhí)行Try階段,當(dāng)故障恢復(fù)后惋鸥,分布式事務(wù)進(jìn)行回滾則會(huì)調(diào)用二階段的Cancel方法杂穷,從而形成空回滾。

冪等

由于任何一個(gè)請求都可能出現(xiàn)網(wǎng)絡(luò)異常卦绣,出現(xiàn)重復(fù)請求耐量,所以所有的分布式事務(wù)分支,都需要保證冪等性

懸掛:

懸掛就是對于一個(gè)分布式事務(wù)滤港,其二階段 Cancel 接口比 Try 接口先執(zhí)行廊蜒。

出現(xiàn)原因是在 RPC 調(diào)用分支事務(wù)try時(shí),先注冊分支事務(wù)溅漾,再執(zhí)行RPC調(diào)用山叮,如果此時(shí) RPC 調(diào)用的網(wǎng)絡(luò)發(fā)生擁堵,RPC 超時(shí)以后添履,TM就會(huì)通知RM回滾該分布式事務(wù)屁倔,可能回滾完成后,RPC 請求才到達(dá)參與者真正執(zhí)行暮胧。

下面看一個(gè)網(wǎng)絡(luò)異常的時(shí)序圖锐借,更好的理解上述幾種問題

業(yè)務(wù)處理請求4的時(shí)候,Cancel在Try之前執(zhí)行往衷,需要處理空回滾
業(yè)務(wù)處理請求6的時(shí)候钞翔,Cancel重復(fù)執(zhí)行,需要冪等
業(yè)務(wù)處理請求8的時(shí)候炼绘,Try在Cancel后執(zhí)行嗅战,需要處理懸掛

面對上述復(fù)雜的網(wǎng)絡(luò)異常情況,目前看到各家建議的方案都是業(yè)務(wù)方通過唯一鍵俺亮,去查詢相關(guān)聯(lián)的操作是否已完成驮捍,如果已完成則直接返回成功。相關(guān)的判斷邏輯較復(fù)雜脚曾,易出錯(cuò)东且,業(yè)務(wù)負(fù)擔(dān)重。

在項(xiàng)目DTM中珊泳,出現(xiàn)了一種子事務(wù)屏障技術(shù)鲁冯,使用該技術(shù),能夠達(dá)到這個(gè)效果色查,看示意圖:

[圖片上傳失敗...(image-4f4c26-1631769525236)]

所有這些請求,到了子事務(wù)屏障后:不正常的請求,會(huì)被過濾晶通;正常請求,通過屏障狮辽。開發(fā)者使用子事務(wù)屏障之后喉脖,前面所說的各種異常全部被妥善處理塘秦,業(yè)務(wù)開發(fā)人員只需要關(guān)注實(shí)際的業(yè)務(wù)邏輯,負(fù)擔(dān)大大降低动看。
子事務(wù)屏障提供了方法ThroughBarrierCall,方法的原型為:

func ThroughBarrierCall(db *sql.DB, transInfo *TransInfo, busiCall BusiFunc)

業(yè)務(wù)開發(fā)人員爪幻,在busiCall里面編寫自己的相關(guān)邏輯菱皆,調(diào)用該函數(shù)。ThroughBarrierCall保證挨稿,在空回滾仇轻、懸掛等場景下,busiCall不會(huì)被調(diào)用奶甘;在業(yè)務(wù)被重復(fù)調(diào)用時(shí)篷店,有冪等控制,保證只被提交一次臭家。

子事務(wù)屏障會(huì)管理TCC疲陕、SAGA、XA钉赁、事務(wù)消息等蹄殃,也可以擴(kuò)展到其他領(lǐng)域

子事務(wù)屏障技術(shù)的原理是,在本地?cái)?shù)據(jù)庫你踩,建立分支事務(wù)狀態(tài)表sub_trans_barrier诅岩,唯一鍵為全局事務(wù)id-子事務(wù)id-子事務(wù)分支名稱(try|confirm|cancel)

  • 開啟事務(wù)
  • 如果是Try分支讳苦,則那么insert ignore插入gid-branchid-try,如果成功插入吩谦,則調(diào)用屏障內(nèi)邏輯
  • 如果是Confirm分支鸳谜,那么insert ignore插入gid-branchid-confirm,如果成功插入式廷,則調(diào)用屏障內(nèi)邏輯
  • 如果是Cancel分支咐扭,那么insert ignore插入gid-branchid-try,再插入gid-branchid-cancel懒棉,如果try未插入并且cancel插入成功草描,則調(diào)用屏障內(nèi)邏輯
  • 屏障內(nèi)邏輯返回成功,提交事務(wù)策严,返回成功
  • 屏障內(nèi)邏輯返回錯(cuò)誤穗慕,回滾事務(wù),返回錯(cuò)誤

在此機(jī)制下妻导,解決了網(wǎng)絡(luò)異常相關(guān)的問題

  • 空補(bǔ)償控制--如果Try沒有執(zhí)行逛绵,直接執(zhí)行了Cancel,那么Cancel插入gid-branchid-try會(huì)成功倔韭,不走屏障內(nèi)的邏輯术浪,保證了空補(bǔ)償控制
  • 冪等控制--任何一個(gè)分支都無法重復(fù)插入唯一鍵,保證了不會(huì)重復(fù)執(zhí)行
  • 防懸掛控制--Try在Cancel之后執(zhí)行寿酌,那么插入的gid-branchid-try不成功胰苏,就不執(zhí)行,保證了防懸掛控制

對于SAGA事務(wù)醇疼,也是類似的機(jī)制硕并。

子事務(wù)屏障技術(shù),為DTM首創(chuàng)秧荆,它的意義在于設(shè)計(jì)簡單易實(shí)現(xiàn)的算法倔毙,提供了簡單易用的接口,在首創(chuàng)乙濒,它的意義在于設(shè)計(jì)簡單易實(shí)現(xiàn)的算法陕赃,提供了簡單易用的接口,在這兩項(xiàng)的幫助下颁股,開發(fā)人員徹底的從網(wǎng)絡(luò)異常的處理中解放出來么库。

該技術(shù)目前需要搭配DTM事務(wù)管理器,目前SDK已經(jīng)提供給go語言的開發(fā)者甘有。其他語言的sdk正在規(guī)劃中廊散。對于其他的分布式事務(wù)框架,只要提供了合適的分布式事務(wù)信息梧疲,能夠按照上述原理允睹,快速實(shí)現(xiàn)該技術(shù)运准。

總結(jié)

本文介紹了分布式事務(wù)的一些基礎(chǔ)理論,并對常用的分布式事務(wù)方案進(jìn)行了講解缭受,在文章的后半部分還給出了事務(wù)異常的原因胁澳、分類以及優(yōu)雅的解決方案。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末米者,一起剝皮案震驚了整個(gè)濱河市韭畸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔓搞,老刑警劉巖胰丁,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喂分,居然都是意外死亡锦庸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門蒲祈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甘萧,“玉大人,你說我怎么就攤上這事梆掸⊙锞恚” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵酸钦,是天一觀的道長怪得。 經(jīng)常有香客問我,道長卑硫,這世上最難降的妖魔是什么汇恤? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮拔恰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘基括。我一直安慰自己颜懊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布风皿。 她就那樣靜靜地躺著河爹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桐款。 梳的紋絲不亂的頭發(fā)上咸这,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機(jī)與錄音魔眨,去河邊找鬼媳维。 笑死酿雪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的侄刽。 我是一名探鬼主播指黎,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼州丹!你這毒婦竟也來了醋安?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤墓毒,失蹤者是張志新(化名)和其女友劉穎吓揪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體所计,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柠辞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了醉箕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钾腺。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖讥裤,靈堂內(nèi)的尸體忽然破棺而出放棒,到底是詐尸還是另有隱情,我是刑警寧澤己英,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布间螟,位于F島的核電站,受9級(jí)特大地震影響损肛,放射性物質(zhì)發(fā)生泄漏厢破。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一治拿、第九天 我趴在偏房一處隱蔽的房頂上張望摩泪。 院中可真熱鬧,春花似錦劫谅、人聲如沸见坑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荞驴。三九已至,卻和暖如春贯城,著一層夾襖步出監(jiān)牢的瞬間熊楼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工能犯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鲫骗,地道東北人犬耻。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像挎峦,于是被迫代替她去往敵國和親香追。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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