淺談分布式事務(wù)那些事

本篇文章我們重點討論關(guān)于分布式事務(wù)的一些相關(guān)知識點锋叨。這是學(xué)習(xí)分布式系統(tǒng)的一個必不可少的技術(shù)含鳞。我們最常見的案例就是銀行轉(zhuǎn)賬問題城丧,A賬戶向B賬戶轉(zhuǎn)100元延曙,那么A賬戶余額要減少100,B賬戶上要增加100亡哄。兩個步驟必須都要成功才算成功枝缔,只成功一個的話應(yīng)當(dāng)回滾掉。如果A和B不在同一個環(huán)境或者系統(tǒng)上蚊惯,這個事務(wù)就是分布式事務(wù)了愿卸,那么在這種情況下,如何保證事務(wù)的正確執(zhí)行拣挪,有哪些執(zhí)行方案呢擦酌?

CAP理論和BASE理論

在將分布式事務(wù)的開始,我們先從幾個分布式系統(tǒng)方面的基礎(chǔ)知識點說起菠劝,首先是大名鼎鼎的CAP理論,CAP三個字母代表了三個單詞睁搭,Consistency(一致性)赶诊,Availability(可用性),Partition Tolerance(分區(qū)容忍性)园骆。CAP理論指的是任何一個分布式系統(tǒng)舔痪,最多只能保證CAP三項中的兩項。

首先锌唾,一致性锄码,它表示所有的數(shù)據(jù)節(jié)點上的數(shù)據(jù)要保證是一致且正確的夺英。可用性指的是每一個操作總是能夠在一定時間內(nèi)返回結(jié)果即是說每個讀寫操作都是成功的滋捶。我們平時經(jīng)惩疵酰看到的一些對于系統(tǒng)穩(wěn)定性的描述都是達(dá)到了幾個9,比如3個9就是99.9%重窟,4個9就是99.99%载萌。這就意味著系統(tǒng)只有在極少數(shù)情況下才會發(fā)生故障或錯誤。分區(qū)容忍性指的是當(dāng)出現(xiàn)部分節(jié)點故障時巡扇,分布式系統(tǒng)仍然能夠正常運(yùn)行扭仁。

常見的分布式系統(tǒng)應(yīng)用架構(gòu)都是AP或者CP,因為如果沒有P那本質(zhì)上就是個單機(jī)應(yīng)用談不上分布式了厅翔。工作中最常用到的幾個注冊中心乖坠,ZooKeeper就是基于CP架構(gòu)的,Eureka是基于AP的刀闷。

在工程實踐中熊泵,基于CAP理論又演化出一個新的理論-BASE理論。Base代表了三個單詞:Basically Available(基本可用)涩赢,Soft State(軟狀態(tài))和Eventally Consistent(最終一致性)戈次。它的核心思想是最終一致性,即無法做到強(qiáng)一致性筒扒,但我們可以根據(jù)實際業(yè)務(wù)情況怯邪,使系統(tǒng)達(dá)到最終一致性。

首先花墩,Base理論中的基本可用悬秉,就是不追求CAP中的任何時候的讀寫操作都是成功的,但系統(tǒng)能夠保證基本運(yùn)行冰蘑。比如我們平時雙十一的時候可能會出現(xiàn)排隊或者失敗的情況和泌,其實就是犧牲了部分可用性來保證系統(tǒng)的穩(wěn)定。

軟狀態(tài)可以對標(biāo)ACID中的強(qiáng)一致性祠肥,ACID中要么全做要么全不做武氓,所有用戶看到的數(shù)據(jù)都是絕對一致的。但軟狀態(tài)是允許出現(xiàn)數(shù)據(jù)不一致的時刻仇箱,相當(dāng)于是一個中間狀態(tài)县恕,幾個數(shù)據(jù)節(jié)點的數(shù)據(jù)出現(xiàn)了延遲的情況。

最終一致性指的是數(shù)據(jù)不能一直處于軟狀態(tài)的情況剂桥,最終還是要達(dá)到所有節(jié)點數(shù)據(jù)一致的忠烛。這也是我們大部分開發(fā)過程中所追求的。

數(shù)據(jù)一致性模型

數(shù)據(jù)一致性模型一般分為弱一致性和強(qiáng)一致性权逗,上述的BASE理論是實現(xiàn)的最終一致性其實就是弱一致性美尸,而強(qiáng)一致性有時候也稱為線性一致性冤议,就是每次更新操作后,其他每個進(jìn)程獲取到的數(shù)據(jù)都是最新的师坎,這種方式對用戶友好恕酸,即用戶之前做了什么操作,下一步就能保證得到什么屹耐。但這種方式會犧牲系統(tǒng)的可用性尸疆,可以理解為我們實現(xiàn)了CP犧牲了A。

除了強(qiáng)一致性之外的一致性模型都是弱一致性惶岭,也就是說系統(tǒng)不承諾更新操作后一定能保證下次能讀取到最新數(shù)據(jù)寿弱,要能正確讀取到這個數(shù)據(jù)需要等待一段時間,這個時間差稱作“不一致窗口”按灶。

最終一致性是弱一致性的特例症革,它強(qiáng)調(diào)的是所有節(jié)點的數(shù)據(jù)副本,經(jīng)過一段時間后鸯旁,一定能達(dá)到全部一致噪矛。它的不一致窗口的時間主要受通信延遲,系統(tǒng)負(fù)載和復(fù)制副本的個數(shù)影響铺罢。其根據(jù)不同的保證也可以分為不同模型艇挨,包括因果一致性會話一致性等。

因果一致性要求有因果關(guān)系的操作順序得到保證韭赘,非因果關(guān)系的操作順序則無所謂缩滨。

會話一致性將對系統(tǒng)數(shù)據(jù)的訪問過程框定在了一個會話當(dāng)中,約定了系統(tǒng)能保證在同一個有效的會話中實現(xiàn)“讀己之所寫”的一致性泉瞻,就是在你的一次訪問中脉漏,執(zhí)行更新操作之后,客戶端能夠在同一個會話中始終讀取到該數(shù)據(jù)項的最新值袖牙。

那么為了實現(xiàn)數(shù)據(jù)一致性侧巨,我們就自然要回到我們一開始就要說的分布式事務(wù)的概念了,它不同于我們平時單機(jī)應(yīng)用上的服務(wù)鞭达,由于在數(shù)據(jù)分布在多臺服務(wù)器上司忱,我們就不能用傳統(tǒng)的方式來保證事務(wù)的正確提交,這就引出了集中針對分布式事務(wù)的解決方案畴蹭。

2PC 兩階段提交

兩階段提交(2PC烘贴,Two-phase Commit Protocol)是非常經(jīng)典的強(qiáng)一致性、中心化的原子提交協(xié)議撮胧。這個算法包含了兩類角色,協(xié)調(diào)者(Coordinator)和參與者(Participants)老翘。所謂的兩階段指的是準(zhǔn)備階段(Commit-request)和執(zhí)行階段(Commit)芹啥。

在準(zhǔn)備階段的時候锻离,協(xié)調(diào)者通知各個參與者準(zhǔn)備提交事務(wù),詢問它們是否接受墓怀。參與者們會各自反饋自己的響應(yīng)汽纠,同意或者取消(故障),在這個階段里面傀履,所有參與者都沒有進(jìn)行commit事務(wù)操作虱朵。

協(xié)調(diào)者收到參與者們的反饋結(jié)果后,進(jìn)行決策钓账,如果所有的參與者都表示同意碴犬,則要提交事務(wù),否則就是取消梆暮。此時通知所有參與者們進(jìn)行事務(wù)提交/取消服协,參與者們接受到協(xié)調(diào)者的通知后進(jìn)行事務(wù)操作commit/rollback。

但是兩階段提交存在著一些問題啦粹,列舉如下:

  • 資源被同步阻塞:在執(zhí)行過程中偿荷,所有參與者都是事務(wù)獨占的,也就意味著唠椭,當(dāng)參與者占用公共資源的時候跳纳,其他節(jié)點訪問公共資源會處于阻塞狀態(tài)。
  • 協(xié)調(diào)者可能出現(xiàn)單點故障:協(xié)調(diào)者作為這個算法中的核心角色贪嫂,一旦發(fā)生故障寺庄,參與者會一直阻塞下去。如果在第二階段發(fā)生的撩荣,所有的參與者還處于鎖定事務(wù)資源的狀態(tài)铣揉,但收不到協(xié)調(diào)者的決策通知,導(dǎo)致一直鎖定無法繼續(xù)完成事務(wù)餐曹。
  • Commit階段出現(xiàn)數(shù)據(jù)不一致:在第二階段中逛拱,協(xié)調(diào)者發(fā)起了commit的通知,但由于網(wǎng)絡(luò)等原因?qū)е虏糠止?jié)點收到部分節(jié)點每收到通知台猴,會導(dǎo)致沒收到的還處于阻塞狀態(tài)朽合,收到的會進(jìn)行commit操作,從而出現(xiàn)了數(shù)據(jù)不一致問題饱狂。

XA規(guī)范

因為講了二階段提交曹步,那么這里也順便提一下我們被問到MySQL時經(jīng)常會說的XA規(guī)范,因為它實際上是實現(xiàn)了二階段提交的休讳。它是由 X/Open 組織提出的分布式事務(wù)規(guī)范讲婚,XA 規(guī)范主要定義了事務(wù)協(xié)調(diào)者(Transaction Manager)和資源管理器(Resource Manager)之間的接口。

XA

事務(wù)管理器擔(dān)任著協(xié)調(diào)者的角色俊柔,它來負(fù)責(zé)協(xié)調(diào)和管理事務(wù)筹麸,提供給AP應(yīng)用程序編程接口并管理資源管理器活合。事務(wù)管理器向事務(wù)指定標(biāo)識,監(jiān)視它們的進(jìn)程物赶,并負(fù)責(zé)處理事務(wù)的完成和失敗白指。資源管理器,可以理解為一個DBMS系統(tǒng)酵紫,或者消息服務(wù)器管理系統(tǒng)告嘲。應(yīng)用程序通過資源管理器對資源進(jìn)行控制,資源必須實現(xiàn)XA定義的接口奖地。資源管理器提供了存儲共享資源的支持橄唬。

目前,主流數(shù)據(jù)庫都提供了對 XA 的支持鹉动,在 JMS 規(guī)范中轧坎,即 Java 消息服務(wù)(Java Message Service)中,也基于 XA 定義了對事務(wù)的支持泽示。

根據(jù)2PC的規(guī)范缸血,XA也是將事務(wù)分為兩個步驟準(zhǔn)備(Prepare)和提交(Commit)階段。準(zhǔn)備階段就是TM向RM發(fā)送Prepare命令械筛,準(zhǔn)備提交捎泻,RM執(zhí)行數(shù)據(jù)操作后,返回TM結(jié)果埋哟。TM根據(jù)收到的結(jié)果笆豁,進(jìn)入提交階段,通知RM進(jìn)行Commit或者Rollback操作赤赊。

在MySQL中闯狱,有兩種XA事務(wù),一種是內(nèi)部XA抛计,一種是外部XA哄孤。

在 MySQL 的 InnoDB 存儲引擎中,開啟 binlog 的情況下吹截,MySQL 會同時維護(hù) binlog 日志與 InnoDB 的 redo log瘦陈,為了保證這兩個日志的一致性,MySQL 使用了 XA 事務(wù)波俄,由于是在 MySQL 單機(jī)上工作晨逝,所以被稱為內(nèi)部 XA。內(nèi)部 XA 事務(wù)由 binlog 作為協(xié)調(diào)者懦铺,在事務(wù)提交時捉貌,則需要將提交信息寫入二進(jìn)制日志,也就是說,binlog 的參與者是 MySQL 本身昏翰。

外部 XA 就是典型的分布式事務(wù)苍匆,MySQL 支持 XA START/END/PREPARE/Commit 這些 SQL 語句,通過使用這些命令棚菊,可以完成分布式事務(wù)。

3PC 三階段提交

三階段提交(3PC叔汁,Three-phase commit)是基于2PC的改進(jìn)版本统求,它引入了兩個改動點。

  1. 引入超時機(jī)制据块,同時在協(xié)調(diào)者和參與者都加入超時機(jī)制码邻。
  2. 把2PC的第一個階段拆分成了兩步:詢問,然后再鎖資源另假,最后真正提交像屋。

它的三個階段叫做Can Commit, PreCommit和Do Commit。

CanCommit 階段

和2PC的準(zhǔn)備階段很像边篮,就是協(xié)調(diào)者向參與者發(fā)起CanCommit 請求己莺,參與者返回yes或no。

PreCommit階段

協(xié)調(diào)者根據(jù)參與者的反應(yīng)情況來決定是否可以繼續(xù)事務(wù)的 PreCommit 操作戈轿。根據(jù)響應(yīng)情況凌受,有以下兩種可能。

  • 全部返回ok
    • 如果全部返回OK的話思杯,就要進(jìn)行事務(wù)預(yù)提交胜蛉,協(xié)調(diào)者向參與者發(fā)送PreCommit請求,參與者接受到后進(jìn)行事務(wù)操作但不提交色乾,如果成功執(zhí)行了則返回ACK響應(yīng)誊册。
  • 部分返回ok
    • 如果部分返回OK可能指的是有部分參與者返回了NO或者是超時后協(xié)調(diào)者依然未收到參與者的反饋。那么此時進(jìn)行中斷事務(wù)暖璧,協(xié)調(diào)者發(fā)送中斷請求給參與者案怯,參與者收到后進(jìn)行abort中斷。

DoCommit階段

此階段進(jìn)行真正的提交漆撞,跟2PC的最終階段有點相似殴泰。如果協(xié)調(diào)者上一步收到了所有的ACK則會通知參與者進(jìn)行提交操作,參與者收到后進(jìn)行提交并反饋協(xié)調(diào)者ACK浮驳。但如果協(xié)調(diào)者上一步未收到ACK響應(yīng)悍汛,同樣也要執(zhí)行中斷事務(wù)。如果超過超時時間參與者都沒有收到協(xié)調(diào)者的通知至会,則自動進(jìn)行Commit离咐。

很顯然3PC由于協(xié)調(diào)者和參與者都有了超時機(jī)制(2PC只有協(xié)調(diào)者有),可以保證資源不會因為協(xié)調(diào)者的故障而一直鎖定,并且由于多了一個PreCommit階段宵蛀,使得參與者在提交之前的狀態(tài)是一致的昆著。但這并不能解決最終可能出現(xiàn)的一致性問題,因為在上面DoCommit階段也有介紹术陶,如果參與者未收到協(xié)調(diào)者的通知凑懂,達(dá)到了超時時間后,依然會進(jìn)行提交梧宫,這就出現(xiàn)了數(shù)據(jù)的不一致性接谨。

TCC(Try-Confirm-Cancel)

TCC(Try-Confirm-Cancel)的概念來源于 Pat Helland 發(fā)表的一篇名為“Life beyond Distributed Transactions:an Apostate’s Opinion”的論文。它的三個字母也對應(yīng)了三個階段:

  • Try階段:調(diào)用Try接口塘匣,嘗試執(zhí)行業(yè)務(wù)脓豪,完成業(yè)務(wù)檢查,預(yù)留業(yè)務(wù)資源忌卤。
  • Confirm階段:確認(rèn)執(zhí)行業(yè)務(wù)操作扫夜,不做業(yè)務(wù)檢查,只使用Try階段預(yù)留的業(yè)務(wù)資源驰徊。
  • Cancel階段:跟Confirm互斥笤闯,兩者只能進(jìn)入其中一個。在業(yè)務(wù)執(zhí)行錯誤的時候進(jìn)行回滾辣垒,執(zhí)行業(yè)務(wù)取消望侈,釋放資源。

Try階段失敗可以Cancel勋桶,但Confirm/Cancel階段沒有脱衙,為了解決此問題,TCC中添加了事務(wù)日志例驹,如果Confirm或者Cancle階段出錯捐韩,是允許進(jìn)行重試的,所以這兩個接口需要支持冪等鹃锈,如果重試依然失敗那就要靠人工介入了荤胁。

TCC的特點

通過上面的描述,很顯然屎债,TCC相對于之前的2PC等方式仅政,它關(guān)注的是業(yè)務(wù)層而不是數(shù)據(jù)庫或者存儲資源層面的事務(wù)。它的核心思想是針對每個業(yè)務(wù)操作盆驹,都要添加相應(yīng)的確認(rèn)和補(bǔ)償操作圆丹,同時把相關(guān)的處理從數(shù)據(jù)庫拿到了業(yè)務(wù)層,以此實現(xiàn)了跨數(shù)據(jù)庫的事務(wù)躯喇。

但正因為它是在業(yè)務(wù)層進(jìn)行事務(wù)的處理辫封,因此對微服務(wù)的侵入性強(qiáng)硝枉,業(yè)務(wù)邏輯的每個分支都要實現(xiàn)Try,Confirm,Cancel三個操作,而且Confirm倦微,Cancel還要實現(xiàn)冪等妻味。另外TCC 的事務(wù)管理器要記錄事務(wù)日志,也會損耗一定的性能欣福。

在業(yè)務(wù)中引入 TCC 一般是依賴單獨的 TCC 事務(wù)框架责球,最常見的就是Seata框架了,這個可以自己嘗試去使用體驗下劣欢。

基于消息補(bǔ)償?shù)淖罱K一致性

在實際生產(chǎn)工作中棕诵,我們還經(jīng)常會用到一種方案,基于消息補(bǔ)償?shù)姆绞皆浣且环N異步事務(wù)機(jī)制。常見的實現(xiàn)方案有本地消息表价脾、消息隊列等牧抵。

本地消息表

首先說下本地消息表,它最初是由 ebay 的工程師提出侨把,核心思想是將分布式事務(wù)拆分成本地事務(wù)進(jìn)行處理犀变,通過消息日志的方式來異步執(zhí)行。所以其實就是利用了各系統(tǒng)本地的事務(wù)實現(xiàn)了分布式事務(wù)秋柄。在本地要創(chuàng)建一張消息表获枝,業(yè)務(wù)執(zhí)行的時候也要往這個消息表里面存放一條數(shù)據(jù),這樣可以保證存放消息和業(yè)務(wù)數(shù)據(jù)都是同時成功或失敗的骇笔。成功存放后再進(jìn)行后續(xù)的業(yè)務(wù)操作省店,如果成功了則將消息狀態(tài)更新為成功。如果失敗了笨触,首先會有個定時任務(wù)經(jīng)常去掃描未成功的任務(wù)去執(zhí)行懦傍,如果失敗也是可以重試的,所以要保證業(yè)務(wù)處理接口的冪等芦劣。

所以能看出本地消息表的方式是能保證最終一致性的粗俱,但可能出現(xiàn)部分時間的數(shù)據(jù)不一致。

可靠消息隊列

我們常見的消息隊列中RocketMQ就支持消息事務(wù)虚吟。所以我這里講下RocketMQ實現(xiàn)分布式事務(wù)寸认。這部分我從阿里云的文檔上找的,感興趣的可以自己去看串慰,顯示幾個概念:

  • 半事務(wù)消息:暫不能投遞的消息偏塞,發(fā)送方已經(jīng)成功地將消息發(fā)送到了消息隊列RocketMQ版服務(wù)端,但是服務(wù)端未收到生產(chǎn)者對該消息的二次確認(rèn)模庐,此時該消息被標(biāo)記成“暫不能投遞”狀態(tài)烛愧,處于該種狀態(tài)下的消息即半事務(wù)消息。
  • 消息回查:由于網(wǎng)絡(luò)閃斷、生產(chǎn)者應(yīng)用重啟等原因怜姿,導(dǎo)致某條事務(wù)消息的二次確認(rèn)丟失慎冤,消息隊列RocketMQ版服務(wù)端通過掃描發(fā)現(xiàn)某條消息長期處于“半事務(wù)消息”時,需要主動向消息生產(chǎn)者詢問該消息的最終狀態(tài)(Commit或是Rollback)沧卢,該詢問過程即消息回查蚁堤。

交互流程如下

交互流程

事務(wù)消息發(fā)送步驟如下:

  1. 發(fā)送方將半事務(wù)消息發(fā)送至消息隊列RocketMQ版服務(wù)端。
  2. 消息隊列RocketMQ版服務(wù)端將消息持久化成功之后但狭,向發(fā)送方返回Ack確認(rèn)消息已經(jīng)發(fā)送成功披诗,此時消息為半事務(wù)消息。
  3. 發(fā)送方開始執(zhí)行本地事務(wù)邏輯立磁。
  4. 發(fā)送方根據(jù)本地事務(wù)執(zhí)行結(jié)果向服務(wù)端提交二次確認(rèn)(Commit或是Rollback)呈队,服務(wù)端收到Commit狀態(tài)則將半事務(wù)消息標(biāo)記為可投遞,訂閱方最終將收到該消息唱歧;服務(wù)端收到Rollback狀態(tài)則刪除半事務(wù)消息宪摧,訂閱方將不會接受該消息。

事務(wù)消息回查步驟如下:

  1. 在斷網(wǎng)或者是應(yīng)用重啟的特殊情況下颅崩,上述步驟4提交的二次確認(rèn)最終未到達(dá)服務(wù)端几于,經(jīng)過固定時間后服務(wù)端將對該消息發(fā)起消息回查。
  2. 發(fā)送方收到消息回查后沿后,需要檢查對應(yīng)消息的本地事務(wù)執(zhí)行的最終結(jié)果沿彭。
  3. 發(fā)送方根據(jù)檢查得到的本地事務(wù)的最終狀態(tài)再次提交二次確認(rèn),服務(wù)端仍按照步驟4對半事務(wù)消息進(jìn)行操作尖滚。

盡最大努力通知

和上面的可靠消息隊列方式類似的喉刘,還有一種方案叫做盡最大努力通知。它的核心思想是發(fā)起通知方通過一定的機(jī)制最大努力將業(yè)務(wù)處理結(jié)果通知到接收方熔掺。一般也是通過MQ去實現(xiàn)的饱搏。

它和基于可靠消息一致的區(qū)別如下(摘自某博客):

1、解決方案思想不同

可靠消息一致性置逻,發(fā)起通知方需要保證將消息發(fā)出去推沸,并且將消息發(fā)到接收通知方,消息的可靠性關(guān)鍵由發(fā)起通知方來保證券坞。 最大努力通知鬓催,發(fā)起通知方盡最大的努力將業(yè)務(wù)處理結(jié)果通知為接收通知方,但是可能消息接收不到恨锚,此時需要接收通知方主動調(diào)用發(fā)起通知方的接口查詢業(yè)務(wù)處理結(jié)果匿情,通知的可靠性關(guān)鍵在接收通知方蟆炊。

2猜绣、兩者的業(yè)務(wù)應(yīng)用場景不同

可靠消息一致性關(guān)注的是交易過程的事務(wù)一致,以異步的方式完成交易塌西。 最大努力通知關(guān)注的是交易后的通知事務(wù),即將交易結(jié)果可靠的通知出去筝尾。

3捡需、技術(shù)解決方向不同

可靠消息一致性要解決消息從發(fā)出到接收的一致性,即消息發(fā)出并且被接收到筹淫。 最大努力通知無法保證消息從發(fā)出到接收的一致性站辉,只提供消息接收的可靠性機(jī)制∷鸾可靠機(jī)制是饰剥,最大努力的將消息通知給接收方,當(dāng)消息無法被接收方接收時摧阅,由接收方主動查詢消費(fèi)(業(yè)務(wù)處理結(jié)果)汰蓉。

總結(jié)

2PC和3PC都是一種強(qiáng)一致性事務(wù),基于數(shù)據(jù)庫層面棒卷,但也存在一些數(shù)據(jù)不一致的風(fēng)險古沥。TCC是一種補(bǔ)償性的事務(wù)思想,由于需要在業(yè)務(wù)層實現(xiàn)娇跟,所以對業(yè)務(wù)侵入大√基于消息補(bǔ)償?shù)姆绞桨琓CC還有盡最大努力通知其實都是一種柔性事務(wù),都是保證了最終一致性龄章,允許出現(xiàn)部分時刻數(shù)據(jù)不一致的情況吃谣。

這篇文章有點水,其實就是講了點概念做裙,很多還是摘錄自其他博客和拉勾教育-分布式技術(shù)原理與實戰(zhàn)45講這門課程的岗憋,就當(dāng)個讀書筆記看吧,至少擴(kuò)展了一些對分布式事務(wù)的基礎(chǔ)概念的了解锚贱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仔戈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拧廊,更是在濱河造成了極大的恐慌监徘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吧碾,死亡現(xiàn)場離奇詭異凰盔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)倦春,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門户敬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來落剪,“玉大人,你說我怎么就攤上這事尿庐≈也溃” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵屁倔,是天一觀的道長脑又。 經(jīng)常有香客問我,道長锐借,這世上最難降的妖魔是什么问麸? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮钞翔,結(jié)果婚禮上严卖,老公的妹妹穿的比我還像新娘。我一直安慰自己布轿,他們只是感情好哮笆,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汰扭,像睡著了一般稠肘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萝毛,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天项阴,我揣著相機(jī)與錄音,去河邊找鬼笆包。 笑死环揽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庵佣。 我是一名探鬼主播歉胶,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼巴粪!你這毒婦竟也來了通今?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤验毡,失蹤者是張志新(化名)和其女友劉穎衡创,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晶通,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡璃氢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狮辽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片一也。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡巢寡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椰苟,到底是詐尸還是另有隱情抑月,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布舆蝴,位于F島的核電站谦絮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏洁仗。R本人自食惡果不足惜层皱,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赠潦。 院中可真熱鬧叫胖,春花似錦、人聲如沸她奥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哩俭。三九已至绷跑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凡资,已是汗流浹背你踩。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留讳苦,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓吩谦,卻偏偏與公主長得像鸳谜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子式廷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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