微服務(wù) - 怎么考慮數(shù)據(jù)一致性問題

學(xué)習(xí)完整課程請移步 互聯(lián)網(wǎng) Java 全棧工程師

單體應(yīng)用的數(shù)據(jù)一致性

想象一下如果我們經(jīng)營著一家大型企業(yè),下屬有航空公司、租車公司、和連鎖酒店。我們?yōu)榭蛻籼峁┮徽臼降穆糜涡谐桃?guī)劃服務(wù)间学,這樣客戶只需要提供出行目的地,我們幫助客戶預(yù)訂機(jī)票印荔、租車低葫、以及預(yù)訂酒店。從業(yè)務(wù)的角度躏鱼,我們必須保證上述三個(gè)服務(wù)的預(yù)訂都完成才能滿足一個(gè)成功的旅游行程氮采,否則不能成行。

我們的單體應(yīng)用要滿足這個(gè)需求非常簡單染苛,只需將這個(gè)三個(gè)服務(wù)請求放到同一個(gè)數(shù)據(jù)庫事務(wù)中鹊漠,數(shù)據(jù)庫會幫我們保證全部成功或者全部回滾。

image

當(dāng)這個(gè)功能上線以后茶行,公司非常滿意躯概,客戶也非常高興。

微服務(wù)場景下的數(shù)據(jù)一致性

這幾年中畔师,我們的行程規(guī)劃服務(wù)非常成功娶靡,企業(yè)蒸蒸日上,用戶量也翻了數(shù)十倍看锉。企業(yè)的下屬航空公司姿锭、租車公司塔鳍、和連鎖酒店也相繼推出了更多服務(wù)以滿足客戶需求,我們的應(yīng)用和開發(fā)團(tuán)隊(duì)也因此日漸龐大呻此。如今我們的單體應(yīng)用已變得如此復(fù)雜轮纫,以至于沒人了解整個(gè)應(yīng)用是怎么運(yùn)作的。更糟的是新功能的上線現(xiàn)在需要所有研發(fā)團(tuán)隊(duì)合作焚鲜,日夜奮戰(zhàn)數(shù)周才能完成掌唾。看著市場占有率每況愈下忿磅,公司高層對研發(fā)部門越來越不滿意糯彬。

經(jīng)過數(shù)輪討論,我們最終決定將龐大的單體應(yīng)用一分為四:機(jī)票預(yù)訂服務(wù)葱她、租車服務(wù)撩扒、酒店預(yù)訂服務(wù)、和支付服務(wù)览效。服務(wù)各自使用自己的數(shù)據(jù)庫却舀,并通過 HTTP 協(xié)議通信虫几。負(fù)責(zé)各服務(wù)的團(tuán)隊(duì)根據(jù)市場需求按照自己的開發(fā)節(jié)奏發(fā)版上線锤灿。如今我們面臨新的挑戰(zhàn):如何保證最初三個(gè)服務(wù)的預(yù)訂都完成才能滿足一個(gè)成功的旅游行程, 否則不能成行的業(yè)務(wù)規(guī)則辆脸?現(xiàn)在服務(wù)有各自的邊界但校,而且數(shù)據(jù)庫選型也不盡相同,通過數(shù)據(jù)庫保證數(shù)據(jù)一致性的方案已不可行啡氢。

image

Sagas

幸運(yùn)的是我們在互聯(lián)網(wǎng)找到一篇精彩的論文状囱,文中提出的數(shù)據(jù)一致性解決方案 Saga 恰好滿足我們的業(yè)務(wù)要求。

Saga 是一個(gè)長活事務(wù)倘是,可被分解成可以交錯(cuò)運(yùn)行的子事務(wù)集合亭枷。其中每個(gè)子事務(wù)都是一個(gè)保持?jǐn)?shù)據(jù)庫一致性的真實(shí)事務(wù)。

在我們的業(yè)務(wù)場景下搀崭,一個(gè)行程規(guī)劃的事務(wù)就是一個(gè) Saga叨粘,其中包含四個(gè)子事務(wù):機(jī)票預(yù)訂、租車瘤睹、酒店預(yù)訂升敲、和支付。

image

Chris Richardson 在他的文章 Pattern: Saga 中對 Saga 有所描述轰传。 Caitie McCaffrey 也在她的演講中提到如何在微軟的 光暈4 游戲中如何應(yīng)用 saga 解決數(shù)據(jù)一致性問題驴党。

Saga 的運(yùn)行原理

Saga 中的事務(wù)相互關(guān)聯(lián),應(yīng)作為(非原子)單位執(zhí)行获茬。任何未完全執(zhí)行的 Saga 是不滿足要求的港庄,如果發(fā)生倔既,必須得到補(bǔ)償。要修正未完全執(zhí)行的部分鹏氧,每個(gè) saga 子交易 T1 應(yīng)提供對應(yīng)補(bǔ)償事務(wù) C1

我們根據(jù)上述規(guī)則定義以下事務(wù)及其相應(yīng)的事務(wù)補(bǔ)償:

服務(wù) 事務(wù) 補(bǔ)償
機(jī)票預(yù)訂 預(yù)訂機(jī)票 取消預(yù)訂
租車 租車 取消預(yù)訂
酒店預(yù)訂 預(yù)訂房間 取消預(yù)訂
支付 支付 退款
當(dāng)每個(gè) saga 子事務(wù) T1, T2, …, Tn 都有對應(yīng)的補(bǔ)償定義 C1, C2, …, Cn-1, 那么 saga 系統(tǒng)可以保證

子事務(wù)序列 T1, T2, …, Tn 得以完成 (最佳情況)
或者序列 T1, T2, …, Tj, Cj, …, C2, C1, 0 < j < n, 得以完成

換句話說叉存,通過上述定義的事務(wù)/補(bǔ)償,saga 保證滿足以下業(yè)務(wù)規(guī)則:

  • 所有的預(yù)訂都被執(zhí)行成功度帮,如果任何一個(gè)失敗歼捏,都會被取消
  • 如果最后一步付款失敗,所有預(yù)訂也將被取消

Saga 的恢復(fù)方式

原論文中描述了兩種類型的 Saga 恢復(fù)方式:

向后恢復(fù) 補(bǔ)償所有已完成的事務(wù)笨篷,如果任一子事務(wù)失敗
向前恢復(fù) 重試失敗的事務(wù)瞳秽,假設(shè)每個(gè)子事務(wù)最終都會成功

顯然,向前恢復(fù)沒有必要提供補(bǔ)償事務(wù)率翅,如果你的業(yè)務(wù)中练俐,子事務(wù)(最終)總會成功,或補(bǔ)償事務(wù)難以定義或不可能冕臭,向前恢復(fù)更符合你的需求腺晾。

理論上補(bǔ)償事務(wù)永不失敗,然而辜贵,在分布式世界中悯蝉,服務(wù)器可能會宕機(jī),網(wǎng)絡(luò)可能會失敗托慨,甚至數(shù)據(jù)中心也可能會停電鼻由。在這種情況下我們能做些什么?最后的手段是提供回退措施厚棵,比如人工干預(yù)蕉世。

使用 Saga 的條件

Saga 看起來很有希望滿足我們的需求。所有長活事務(wù)都可以這樣做嗎婆硬?這里有一些限制:

  • Saga 只允許兩個(gè)層次的嵌套狠轻,頂級的 Saga 和簡單子事務(wù)
  • 在外層,全原子性不能得到滿足彬犯。也就是說向楼,sagas 可能會看到其他 sagas 的部分結(jié)果
  • 每個(gè)子事務(wù)應(yīng)該是獨(dú)立的原子行為
  • 在我們的業(yè)務(wù)場景下,航班預(yù)訂躏嚎、租車蜜自、酒店預(yù)訂和付款是自然獨(dú)立的行為,而且每個(gè)事務(wù)都可以用對應(yīng)服務(wù)的數(shù)據(jù)庫保證原子操作卢佣。

我們在行程規(guī)劃事務(wù)層面也不需要原子性重荠。一個(gè)用戶可以預(yù)訂最后一張機(jī)票,而后由于信用卡余額不足而被取消虚茶。同時(shí)另一個(gè)用戶可能開始會看到已無余票戈鲁,接著由于前者預(yù)訂被取消仇参,最后一張機(jī)票被釋放,而搶到最后一個(gè)座位并完成行程規(guī)劃婆殿。

補(bǔ)償也有需考慮的事項(xiàng):

  • 補(bǔ)償事務(wù)從語義角度撤消了事務(wù) Ti 的行為诈乒,但未必能將數(shù)據(jù)庫返回到執(zhí)行 Ti 時(shí)的狀態(tài)。(例如婆芦,如果事務(wù)觸發(fā)導(dǎo)彈發(fā)射怕磨,則可能無法撤消此操作)

但這對我們的業(yè)務(wù)來說不是問題。其實(shí)難以撤消的行為也有可能被補(bǔ)償消约。例如肠鲫,發(fā)送電郵的事務(wù)可以通過發(fā)送解釋問題的另一封電郵來補(bǔ)償。

現(xiàn)在我們有了通過 Saga 來解決數(shù)據(jù)一致性問題的方案或粮。它允許我們成功地執(zhí)行所有事務(wù)导饲,或在任何事務(wù)失敗的情況下,補(bǔ)償已成功的事務(wù)氯材。雖然 Saga 不提供 ACID 保證渣锦,但仍適用于許多數(shù)據(jù)最終一致性的場景。那我們?nèi)绾卧O(shè)計(jì)一個(gè) Saga 系統(tǒng)氢哮?

Saga Log

Saga 保證所有的子事務(wù)都得以完成或補(bǔ)償袋毙,但 Saga 系統(tǒng)本身也可能會崩潰。Saga 崩潰時(shí)可能處于以下幾個(gè)狀態(tài):

  • Saga 收到事務(wù)請求命浴,但尚未開始娄猫。因子事務(wù)對應(yīng)的微服務(wù)狀態(tài)未被 Saga 修改贱除,我們什么也不需要做生闲。
  • 一些子事務(wù)已經(jīng)完成。重啟后月幌,Saga 必須接著上次完成的事務(wù)恢復(fù)碍讯。
  • 子事務(wù)已開始,但尚未完成扯躺。由于遠(yuǎn)程服務(wù)可能已完成事務(wù)捉兴,也可能事務(wù)失敗,甚至服務(wù)請求超時(shí)录语,saga 只能重新發(fā)起之前未確認(rèn)完成的子事務(wù)倍啥。這意味著子事務(wù)必須冪等。
  • 子事務(wù)失敗澎埠,其補(bǔ)償事務(wù)尚未開始虽缕。Saga 必須在重啟后執(zhí)行對應(yīng)補(bǔ)償事務(wù)。
  • 補(bǔ)償事務(wù)已開始但尚未完成蒲稳。解決方案與上一個(gè)相同氮趋。這意味著補(bǔ)償事務(wù)也必須是冪等的伍派。
  • 所有子事務(wù)或補(bǔ)償事務(wù)均已完成,與第一種情況相同剩胁。

為了恢復(fù)到上述狀態(tài)诉植,我們必須追蹤子事務(wù)及補(bǔ)償事務(wù)的每一步。我們決定通過事件的方式達(dá)到以上要求昵观,并將以下事件保存在名為 saga log 的持久存儲中:

  • Saga started event 保存整個(gè) saga 請求晾腔,其中包括多個(gè)事務(wù)/補(bǔ)償請求
  • Transaction started event 保存對應(yīng)事務(wù)請求
  • Transaction ended event 保存對應(yīng)事務(wù)請求及其回復(fù)
  • Transaction aborted event 保存對應(yīng)事務(wù)請求和失敗的原因
  • Transaction compensated event 保存對應(yīng)補(bǔ)償請求及其回復(fù)
  • Saga ended event 標(biāo)志著 saga 事務(wù)請求的結(jié)束,不需要保存任何內(nèi)容
image

通過將這些事件持久化在 saga log 中啊犬,我們可以將 saga 恢復(fù)到上述任何狀態(tài)建车。

由于 Saga 只需要做事件的持久化,而事件內(nèi)容以 JSON 的形式存儲椒惨,Saga log 的實(shí)現(xiàn)非常靈活缤至,數(shù)據(jù)庫(SQL 或 NoSQL),持久消息隊(duì)列康谆,甚至普通文件可以用作事件存儲领斥,當(dāng)然有些能更快得幫 saga 恢復(fù)狀態(tài)。

Saga 請求的數(shù)據(jù)結(jié)構(gòu)

在我們的業(yè)務(wù)場景下沃暗,航班預(yù)訂月洛、租車、和酒店預(yù)訂沒有依賴關(guān)系孽锥,可以并行處理嚼黔,但對于我們的客戶來說,只在所有預(yù)訂成功后一次付費(fèi)更加友好惜辑。那么這四個(gè)服務(wù)的事務(wù)關(guān)系可以用下圖表示:

image

將行程規(guī)劃請求的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)為有向非循環(huán)圖恰好合適唬涧。圖的根是 saga 啟動任務(wù),葉是 saga 結(jié)束任務(wù)盛撑。

image

Parallel Saga

如上所述碎节,航班預(yù)訂,租車和酒店預(yù)訂可以并行處理抵卫。但是這樣做會造成另一個(gè)問題:如果航班預(yù)訂失敗狮荔,而租車正在處理怎么辦?我們不能一直等待租車服務(wù)回應(yīng)介粘,因?yàn)椴恢佬枰榷嗑谩?/p>

最好的辦法是再次發(fā)送租車請求殖氏,獲得回應(yīng),以便我們能夠繼續(xù)補(bǔ)償操作姻采。但如果租車服務(wù)永不回應(yīng)雅采,我們可能需要采取回退措施,比如手動干預(yù)。

超時(shí)的預(yù)訂請求可能最后仍被租車服務(wù)收到总滩,這時(shí)服務(wù)已經(jīng)處理了相同的預(yù)訂和取消請求纲堵。

image

因此,服務(wù)的實(shí)現(xiàn)必須保證補(bǔ)償請求執(zhí)行以后闰渔,再次收到的對應(yīng)事務(wù)請求無效席函。 Caitie McCaffrey 在她的演講 Distributed Sagas: A Protocol for Coordinating MicroServices 中把這個(gè)稱為可交換的補(bǔ)償請求 (commutative compensating request)。

ACID and Saga

ACID 是具有以下屬性的一致性模型:

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔離性(Isolation)
  • 持久性(Durability)

Saga 不提供 ACID 保證冈涧,因?yàn)樵有院透綦x性不能得到滿足茂附。原論文描述如下:

full atomicity is not provided. That is, sagas may view the partial results of other sagas

通過 saga log,saga 可以保證一致性和持久性督弓。

Saga 架構(gòu)

最后营曼,我們的 Saga 架構(gòu)如下:

image
  • Saga Execution Component 解析請求 JSON 并構(gòu)建請求圖
  • TaskRunner 用任務(wù)隊(duì)列確保請求的執(zhí)行順序
  • TaskConsumer 處理 Saga 任務(wù),將事件寫入 saga log愚隧,并將請求發(fā)送到遠(yuǎn)程服務(wù)

在上文中蒂阱,我談到了 ServiceComb 下的 Saga 是怎么設(shè)計(jì)的。 然而狂塘,業(yè)界還有其他數(shù)據(jù)一致性解決方案录煤,如 兩階段提交(2PC)Try-Confirm / Cancel(TCC)。那 saga 相比之下有什么特別荞胡?

兩階段提交 Two-Phase Commit (2PC)

兩階段提交協(xié)議是一種分布式算法妈踊,用于協(xié)調(diào)參與分布式原子事務(wù)的所有進(jìn)程,以保證他們均完成提交或中止(回滾)事務(wù)泪漂。

2PC 包含兩個(gè)階段:

  • 投票階段 協(xié)調(diào)器向所有服務(wù)發(fā)起投票請求廊营,服務(wù)回答 yes 或 no。如果有任何服務(wù)回復(fù) no 以拒絕或超時(shí)萝勤,協(xié)調(diào)器則在下一階段發(fā)送中止消息露筒。
image
  • 決定階段 如果所有服務(wù)都回復(fù) yes,協(xié)調(diào)器則向服務(wù)發(fā)送 commit 消息纵刘,接著服務(wù)告知事務(wù)完成或失敗邀窃。如果任何服務(wù)提交失敗, 協(xié)調(diào)器將啟動額外的步驟以中止該事務(wù)假哎。
image

在投票階段結(jié)束之后與決策階段結(jié)束之前,服務(wù)處于不確定狀態(tài)鞍历,因?yàn)樗麄儾淮_定交易是否繼續(xù)進(jìn)行舵抹。當(dāng)服務(wù)處于不確定狀態(tài)并與協(xié)調(diào)器失去連接時(shí),它只能選擇等待協(xié)調(diào)器的恢復(fù)劣砍,或者咨詢其他在確定狀態(tài)下的服務(wù)來得知協(xié)調(diào)器的決定惧蛹。在最壞的情況下,n 個(gè)處于不確定狀態(tài)的服務(wù)向其他 n-1 個(gè)服務(wù)咨詢將產(chǎn)生 O(n2) 個(gè)消息。

另外香嗓,2PC 是一個(gè)阻塞協(xié)議迅腔。服務(wù)在投票后需要等待協(xié)調(diào)器的決定,此時(shí)服務(wù)會阻塞并鎖定資源靠娱。由于其阻塞機(jī)制和最差時(shí)間復(fù)雜度高沧烈,2PC 不能適應(yīng)隨著事務(wù)涉及的服務(wù)數(shù)量增加而擴(kuò)展的需要。

Try-Confirm/Cancel (TCC)

TCC 也是補(bǔ)償型事務(wù)模式像云,支持兩階段的商業(yè)模型锌雀。

  • 嘗試階段 將服務(wù)置于待處理狀態(tài)。例如迅诬,收到嘗試請求時(shí)腋逆,航班預(yù)訂服務(wù)將為客戶預(yù)留一個(gè)座位,并在數(shù)據(jù)庫插入客戶預(yù)訂記錄侈贷,將記錄設(shè)為預(yù)留狀態(tài)惩歉。如果任何服務(wù)失敗或超時(shí),協(xié)調(diào)器將在下一階段發(fā)送取消請求俏蛮。
image
  • 確認(rèn)階段 將服務(wù)設(shè)為確認(rèn)狀態(tài)柬泽。確認(rèn)請求將確認(rèn)客戶預(yù)訂的座位,這時(shí)服務(wù)已可向客戶收取機(jī)票費(fèi)用嫁蛇。數(shù)據(jù)庫中的客戶預(yù)訂記錄也會被更新為確認(rèn)狀態(tài)锨并。如果任何服務(wù)無法確認(rèn)或超時(shí),協(xié)調(diào)器將重試確認(rèn)請求直到成功睬棚,或在重試了一定次數(shù)后采取回退措施第煮,比如人工干預(yù)。
image

與 saga 相比抑党,TCC 的優(yōu)勢在于包警,嘗試階段將服務(wù)轉(zhuǎn)為待處理狀態(tài)而不是最終狀態(tài),這使得設(shè)計(jì)相應(yīng)的取消操作輕而易舉底靠。

例如害晦,電郵服務(wù)的嘗試請求可將郵件標(biāo)記為準(zhǔn)備發(fā)送,并且僅在確認(rèn)后發(fā)送郵件暑中,其相應(yīng)的取消請求只需將郵件標(biāo)記為已廢棄壹瘟。但如果使用 saga,事務(wù)將發(fā)送電子郵件鳄逾,及其相應(yīng)的補(bǔ)償事務(wù)可能需要發(fā)送另一封電子郵件作出解釋稻轨。

TCC 的缺點(diǎn)是其兩階段協(xié)議需要設(shè)計(jì)額外的服務(wù)待處理狀態(tài),以及額外的接口來處理嘗試請求雕凹。另外殴俱,TCC 處理事務(wù)請求所花費(fèi)的時(shí)間可能是 saga 的兩倍政冻,因?yàn)?TCC 需要與每個(gè)服務(wù)進(jìn)行兩次通信,并且其確認(rèn)階段只能在收到所有服務(wù)對嘗試請求的響應(yīng)后開始线欲。

事件驅(qū)動的架構(gòu)

和 TCC 一樣明场,在事件驅(qū)動的架構(gòu)中,長活事務(wù)涉及的每個(gè)服務(wù)都需要支持額外的待處理狀態(tài)李丰。接收到事務(wù)請求的服務(wù)會在其數(shù)據(jù)庫中插入一條新的記錄苦锨,將該記錄狀態(tài)設(shè)為待處理并發(fā)送一個(gè)新的事件給事務(wù)序列中的下一個(gè)服務(wù)。

因?yàn)樵诓迦胗涗浐蠓?wù)可能崩潰嫌套,我們無法確定是否新事件已發(fā)送逆屡,所以每個(gè)服務(wù)還需要額外的事件表來跟蹤當(dāng)前長活事務(wù)處于哪一步。

image

一旦長活事務(wù)中的最后一個(gè)服務(wù)完成其子事務(wù)踱讨,它將通知它在事務(wù)中的前一個(gè)服務(wù)魏蔗。接收到完成事件的服務(wù)將其在數(shù)據(jù)庫中的記錄狀態(tài)設(shè)為完成。

image

如果仔細(xì)比較痹筛,事件驅(qū)動的架構(gòu)就像非集中式的基于事件的 TCC 實(shí)現(xiàn)莺治。如果去掉待處理狀態(tài)而直接把服務(wù)記錄設(shè)為最終狀態(tài),這個(gè)架構(gòu)就像非集中式的基于事件的 saga 實(shí)現(xiàn)帚稠。去中心化能達(dá)到服務(wù)自治谣旁,但也造成了服務(wù)之間更緊密的的耦合。假設(shè)新的業(yè)務(wù)需求在服務(wù) B 和 C 之間的增加了新的流程 D滋早。在事件驅(qū)動架構(gòu)下榄审,服務(wù) B 和 C 必須改動代碼以適應(yīng)新的流程 D。

image

Saga 則正好相反杆麸,所有這些耦合都在 saga 系統(tǒng)中搁进,當(dāng)在長活事務(wù)中添加新流程時(shí),現(xiàn)有服務(wù)不需要任何改動昔头。

集中式與非集中式實(shí)現(xiàn)

這個(gè) Saga 系列的文章討論的都是集中式的 saga 設(shè)計(jì)饼问。但 saga 也可用非集中式的方案來實(shí)現(xiàn)。那么非集中式的版本有什么不同揭斧?

非集中式 saga 沒有專職的協(xié)調(diào)器莱革。啟動下一個(gè)服務(wù)調(diào)用的服務(wù)就是當(dāng)前的協(xié)調(diào)器。例如:

  • 服務(wù) A 收到要求服務(wù) A讹开,B 和 C 之間的數(shù)據(jù)一致性的事務(wù)請求盅视。
  • A 完成其子事務(wù),并將請求傳遞給事務(wù)中的下一個(gè)服務(wù)萧吠,服務(wù) B.
  • B 完成其子事務(wù)左冬,并將請求傳遞給 C,依此類推纸型。
  • 如果 C 處理請求失敗,B 有責(zé)任啟動補(bǔ)償事務(wù),并要求 A 回滾狰腌。
image

與集中式相比除破,非集中式的實(shí)現(xiàn)具有服務(wù)自治的優(yōu)勢。但每個(gè)服務(wù)都需要包含數(shù)據(jù)一致性協(xié)議琼腔,并提供其所需的額外持久化設(shè)施瑰枫。

我們更傾向于自治的業(yè)務(wù)服務(wù),但服務(wù)還關(guān)聯(lián)很多應(yīng)用的復(fù)雜性丹莲,如數(shù)據(jù)一致性光坝,服務(wù)監(jiān)控和消息傳遞,將這些棘手問題集中處理甥材,能將業(yè)務(wù)服務(wù)從應(yīng)用的復(fù)雜性中釋放盯另,專注于處理復(fù)雜的業(yè)務(wù),因此我們采用了集中式的 saga 設(shè)計(jì)洲赵。

另外鸳惯,隨著長活事務(wù)中涉及的服務(wù)數(shù)量增長,服務(wù)之間的關(guān)系變得越來越難理解叠萍。

總結(jié)

本文將 saga 與其他數(shù)據(jù)一致性解決方案進(jìn)行了比較芝发。Saga 比兩階段提交更易擴(kuò)展。在事務(wù)可補(bǔ)償?shù)那闆r下苛谷,相比 TCC辅鲸,saga 對業(yè)務(wù)邏輯幾乎沒有改動的需要,而且性能更高腹殿。集中式的 saga 設(shè)計(jì)解耦了服務(wù)與數(shù)據(jù)一致性邏輯及其持久化設(shè)施独悴,并使排查事務(wù)中的問題更容易。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赫蛇,一起剝皮案震驚了整個(gè)濱河市绵患,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悟耘,老刑警劉巖落蝙,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暂幼,居然都是意外死亡筏勒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門旺嬉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來管行,“玉大人,你說我怎么就攤上這事邪媳【枨辏” “怎么了荡陷?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長迅涮。 經(jīng)常有香客問我废赞,道長,這世上最難降的妖魔是什么叮姑? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任唉地,我火速辦了婚禮,結(jié)果婚禮上传透,老公的妹妹穿的比我還像新娘耘沼。我一直安慰自己,他們只是感情好朱盐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布群嗤。 她就那樣靜靜地躺著,像睡著了一般托享。 火紅的嫁衣襯著肌膚如雪骚烧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天闰围,我揣著相機(jī)與錄音赃绊,去河邊找鬼。 笑死羡榴,一個(gè)胖子當(dāng)著我的面吹牛碧查,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播校仑,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼忠售,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了迄沫?” 一聲冷哼從身側(cè)響起稻扬,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羊瘩,沒想到半個(gè)月后泰佳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尘吗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年逝她,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睬捶。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡黔宛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出擒贸,到底是詐尸還是另有隱情臀晃,我是刑警寧澤觉渴,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站积仗,受9級特大地震影響疆拘,放射性物質(zhì)發(fā)生泄漏蜕猫。R本人自食惡果不足惜寂曹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望回右。 院中可真熱鬧隆圆,春花似錦、人聲如沸翔烁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹬屹。三九已至侣背,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慨默,已是汗流浹背贩耐。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厦取,地道東北人潮太。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像虾攻,于是被迫代替她去往敵國和親铡买。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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