MySQL Binlog 技術(shù)原理和業(yè)務(wù)應(yīng)用案例分析

一、背景

Binlog 是 MySQL 中一個(gè)很重要的日志,主要用于 MySQL 主從間的數(shù)據(jù)同步復(fù)制。正是因?yàn)?Binlog 的這項(xiàng)功用判帮,它也被用于 MySQL 向其它類型數(shù)據(jù)庫(kù)同步數(shù)據(jù),以及業(yè)務(wù)流程的事件驅(qū)動(dòng)設(shè)計(jì)溉箕。通過(guò)研究分析晦墙,我們發(fā)現(xiàn)使用 MySQL Binlog 實(shí)現(xiàn)事件驅(qū)動(dòng)設(shè)計(jì)并沒(méi)有想象中那么簡(jiǎn)單,所以接下來(lái)帶大家了解 MySQL 的 Binlog肴茄、Redo Log晌畅、數(shù)據(jù)更新內(nèi)部流程,并通過(guò)對(duì)這些技術(shù)原理的介紹寡痰,來(lái)分析對(duì)業(yè)務(wù)流程可能造成的問(wèn)題抗楔,以及如何避免這些問(wèn)題。希望通過(guò)本文的解析拦坠,能夠幫助大家了解到 MySQL 的一些原理连躏,從而幫助大家能夠更順利地使用 MySQL。

二贪婉、基于 Binlog 的事件驅(qū)動(dòng)

首先介紹一下系統(tǒng)設(shè)計(jì)反粥。起初,我們的訂單系統(tǒng)直接向 MQ 發(fā)送消息疲迂,通過(guò)異步消息驅(qū)動(dòng)后續(xù)業(yè)務(wù)流程,以實(shí)現(xiàn)消息驅(qū)動(dòng)的設(shè)計(jì)莫湘。大致的業(yè)務(wù)流程如下:

▼ 圖:直接發(fā)送消息的訂單事件驅(qū)動(dòng)

這種設(shè)計(jì)需要保證數(shù)據(jù)庫(kù)操作和消息操作的數(shù)據(jù)一致性尤蒿,即數(shù)據(jù)保存和消息發(fā)送要不全部成功,要不全部失敗幅垮。顯然在數(shù)據(jù)保存前和事務(wù)中進(jìn)行消息發(fā)送都是不合適的腰池。我們是在數(shù)據(jù)更新操作后,數(shù)據(jù)庫(kù)事務(wù)外發(fā)送消息。如果數(shù)據(jù)保存成功示弓,但消息發(fā)送失敗讳侨,支付系統(tǒng)需要重新通知(上圖步驟1),直至通知成功奏属。

這種設(shè)計(jì)雖然實(shí)現(xiàn)了功能和對(duì)可用性的基本要求跨跨,但存在如下缺點(diǎn):

  1. 業(yè)務(wù)系統(tǒng)直接依賴消息中間件:消息中間件的故障,不僅會(huì)影響支付通知的處理囱皿,也可能影響業(yè)務(wù)系統(tǒng)上的其它接口勇婴。
  2. 業(yè)務(wù)系統(tǒng)必須實(shí)現(xiàn)可靠的重試:不論是請(qǐng)求發(fā)起方還是請(qǐng)求接收方,都必須實(shí)現(xiàn)可靠的重試嘱腥,才能實(shí)現(xiàn)最大努力通知的目標(biāo)耕渴。
  3. 重試間隔增大會(huì)造成業(yè)務(wù)延遲:隨著重試次數(shù)增加,每次重試的間隔通常也越來(lái)越大齿兔,這被稱為 Exponential Backoff(指數(shù)級(jí)退避)橱脸。這種設(shè)計(jì)能夠讓請(qǐng)求接收方的故障處理更加從容,避免因密集重試造成請(qǐng)求接收方服務(wù)難以恢復(fù)分苇。但這樣做可能會(huì)使請(qǐng)求接收方在恢復(fù)服務(wù)之后很長(zhǎng)時(shí)間后才處理完積壓的消息慰技,從而造成業(yè)務(wù)延遲。我們可以采用類似 Hystrix 的自適應(yīng)設(shè)計(jì)组砚,在請(qǐng)求接收方服務(wù)恢復(fù)后回到到正常的請(qǐng)求速率吻商。但這樣的設(shè)計(jì)顯然會(huì)復(fù)雜許多。

為了解決上述問(wèn)題糟红,簡(jiǎn)化技術(shù)架構(gòu)艾帐,我們采用事件表的設(shè)計(jì)思想,將訂單表作為事件表盆偿。通過(guò)訂閱訂單表的 Binlog柒爸,生成訂單事件,驅(qū)動(dòng)后續(xù)業(yè)務(wù)流程事扭。在系統(tǒng)架構(gòu)上捎稚,業(yè)務(wù)系統(tǒng)不用直接依賴消息中間件,只需專注數(shù)據(jù)庫(kù)操作求橄。而通過(guò)引入一個(gè)接收 Binlog 的獨(dú)立的系統(tǒng)今野,將 MySQL 數(shù)據(jù)變化轉(zhuǎn)換成業(yè)務(wù)事件驅(qū)動(dòng)后續(xù)流程。具體流程如下:

▼ 圖:基于 Binlog 的訂單事件驅(qū)動(dòng)

三罐农、暗藏問(wèn)題

上文提到条霜,雖然基于 Binlog 的訂單事件驅(qū)動(dòng)設(shè)計(jì)存在諸多優(yōu)點(diǎn),但后來(lái)發(fā)現(xiàn)其實(shí)暗藏問(wèn)題涵亏。

最近在一個(gè)業(yè)務(wù)量較低的新站點(diǎn)上宰睡,我們發(fā)現(xiàn)偶爾會(huì)有訂單履約延遲蒲凶。正常流程中,訂單履約服務(wù)收到訂單支付事件后拆内,會(huì)檢查訂單狀態(tài)旋圆,如果此時(shí)訂單狀態(tài)為已支付,則進(jìn)行履約流程的處理麸恍。但對(duì)于有履約延遲的訂單灵巧,訂單履約服務(wù)收到此訂單的支付事件后,查詢數(shù)據(jù)庫(kù)發(fā)現(xiàn)此訂單并非支付狀態(tài)或南。經(jīng)過(guò)調(diào)查孩等,我們排除了數(shù)據(jù)并發(fā)覆蓋問(wèn)題,并且訂單狀態(tài)查詢是發(fā)生在主庫(kù)上采够,也不存在主從同步延遲問(wèn)題肄方。

那究竟是什么原因?qū)е聵I(yè)務(wù)系統(tǒng)收到根據(jù) Binlog 生成的訂單支付事件后,再查詢主庫(kù)得到的訂單數(shù)據(jù)卻是未支付狀態(tài)的蹬癌?

對(duì)于此問(wèn)題的原因我們先放下不談权她,先來(lái)看看 MySQL 在更新數(shù)據(jù)時(shí)的內(nèi)部原理。

四逝薪、MySQL 數(shù)據(jù)更新相關(guān)原理

本節(jié)將向大家介紹 MySQL 數(shù)據(jù)更新相關(guān)原理隅要,以及在這一過(guò)程中最重要的兩種日志:Redo Log 和 Binlog。

Redo Log 和 Binlog

先來(lái)介紹 Redo Log 和 Binary Log(Binlog):

  • Redo Log:Redo Log 是 InnoDB 存儲(chǔ)引擎提供的一種物理日志結(jié)構(gòu)董济,用來(lái)描述對(duì)底層數(shù)據(jù)頁(yè)操作的具體內(nèi)容步清,主要用于實(shí)現(xiàn) crash-safe,并提升磁盤(pán)操作效率虏肾。
  • Binlog:Binlog 是 MySQL 本身提供的一種邏輯日志廓啊,和具體存儲(chǔ)引擎無(wú)關(guān),描述的是數(shù)據(jù)庫(kù)所執(zhí)行的 SQL 語(yǔ)句或數(shù)據(jù)變更情況封豪,主要用于數(shù)據(jù)復(fù)制谴轮。

InnoDB 引入 Redo Log 的目的在于實(shí)現(xiàn) crash-safe 和提升數(shù)據(jù)更新效率。如果 InnoDB 每次數(shù)據(jù)寫(xiě)操作都要直接持久化到磁盤(pán)上的數(shù)據(jù)頁(yè)中吹埠,那樣會(huì)大量增加磁盤(pán)隨機(jī) IO 次數(shù)第步。引入 Redo Log 后,在對(duì)數(shù)據(jù)寫(xiě)操作時(shí)缘琅,會(huì)將部分隨機(jī) IO 寫(xiě)變?yōu)轫樞驅(qū)懻扯肌R驗(yàn)榇疟P(pán)的順序 IO 效率遠(yuǎn)高于隨機(jī) IO,因此引入 Redo Log 機(jī)制有助于提升更新數(shù)據(jù)時(shí)的性能(如何實(shí)現(xiàn) crash-safe 將在下一節(jié)介紹)胯杭。

Binlog 主要用于數(shù)據(jù)的復(fù)制驯杜,MySQL 的主從復(fù)制就是基于 Binlog 實(shí)現(xiàn)的。另外現(xiàn)在很多數(shù)據(jù)同步做个、業(yè)務(wù)事件驅(qū)動(dòng)也是基于 Binlog 實(shí)現(xiàn)的鸽心。Binlog 有三種格式:Statement、Row 和 Mixed居暖。Statement 格式的 Binlog 直接記錄 SQL 語(yǔ)句的內(nèi)容顽频,日志數(shù)據(jù)量較小,但在部分情況下可能會(huì)導(dǎo)致數(shù)據(jù)復(fù)制錯(cuò)誤太闺;而 Row 模式則是記錄變更的前后變化糯景,數(shù)據(jù)量較大,但好處是數(shù)據(jù)可以被準(zhǔn)確復(fù)制省骂;Mixed 則結(jié)合了兩者的優(yōu)點(diǎn)蟀淮。

下面的表格說(shuō)明了兩種日志的作用和它們的不同:

Redo Log Binlog
日志類型 物理日志,即數(shù)據(jù)頁(yè)中的真實(shí)二級(jí)制數(shù)據(jù)钞澳,恢復(fù)速度快 邏輯日志怠惶,SQL 語(yǔ)句 (statement) 或數(shù)據(jù)邏輯變化 (row),恢復(fù)速度慢
存儲(chǔ)格式 基于 InnoDB 數(shù)據(jù)頁(yè)格式進(jìn)行存儲(chǔ) SQL 語(yǔ)句或數(shù)據(jù)變化內(nèi)容
用途 重做數(shù)據(jù)頁(yè) 數(shù)據(jù)復(fù)制
層級(jí) InnoDB 存儲(chǔ)引擎層 MySQL Server 層
記錄方式 循環(huán)寫(xiě) 追加寫(xiě)

這時(shí)問(wèn)題來(lái)了轧粟,現(xiàn)在 MySQL 中存在了兩種日志結(jié)構(gòu):Redo Log 和 Binlog策治。雖然它們的結(jié)構(gòu)和功能有所不同,但卻記錄著相同的數(shù)據(jù)兰吟。如何保證這兩種日志數(shù)據(jù)的一致性通惫,以及如何實(shí)現(xiàn) crash-safe 呢?這就引出了兩階段提交設(shè)計(jì)混蔼。

兩階段提交

兩階段提交不是 Redo Log 或 InnoDB 中的設(shè)計(jì)履腋,而是 MySQL 服務(wù)器的設(shè)計(jì)(但通常說(shuō)到兩階段提交時(shí)都和 Redo Log 放在一起)。因?yàn)?MySQL 采用插件化的存儲(chǔ)引擎設(shè)計(jì)惭嚣,事務(wù)提交時(shí)遵湖,服務(wù)器本身和存儲(chǔ)引擎都需要提交數(shù)據(jù)。所以從 MySQL 服務(wù)器角度看料按,其本身就面臨著分布式事務(wù)問(wèn)題奄侠。

為解決此問(wèn)題,MySQL 引入了兩階段提交载矿。在兩階段提交過(guò)程中垄潮,Redo Log 會(huì)有兩次操作:Prepare 和 Commit。而 Binlog 寫(xiě)操作則夾在 Redo Log 的 Prepare 和 Commit 操作之間闷盔。我們可以設(shè)想一下不同失敗場(chǎng)景下兩階段提交的設(shè)計(jì)是如何保證數(shù)據(jù)一致的:

  1. Redo Log Prepare 成功弯洗,在寫(xiě) Binlog 前崩潰:在故障恢復(fù)后事務(wù)就會(huì)回滾。這樣 Redo Log 和 Binlog 的內(nèi)容還是一致的逢勾。這種情況比較簡(jiǎn)單牡整,比較復(fù)雜的是下一種情況,即在寫(xiě) Binlog 和 Redo Log Commit 中間崩潰時(shí)溺拱,MySQL 是如何處理的逃贝?
  2. 在寫(xiě) Binlog 之后谣辞,但 Redo Log 還沒(méi)有 Commit 之前崩潰
    1. 如果 Redo Log 有 Commit 標(biāo)識(shí),說(shuō)明 Redo Log 其實(shí)已經(jīng) Commit 成功沐扳。這時(shí)直接提交事務(wù)泥从。
    2. 如果 Redo Log 沒(méi)有 Commit 標(biāo)識(shí),則使用 XID(事務(wù) ID)查詢 Binlog 相應(yīng)日志沪摄,并檢查日志的完整躯嫉。如果 Binlog 是完整的,則提交事務(wù)杨拐,否則回滾祈餐。

如何判斷 Binlog 是否完整?簡(jiǎn)單來(lái)說(shuō) Statement 格式的 Binlog 最后有 Commit哄陶,或 Row 格式的 Binlog 有 XID Event帆阳,那 Binlog 就是完整的。

MySQL 數(shù)據(jù)更新流程

接下來(lái)看一下 MySQL 執(zhí)行器和 InnoDB 存儲(chǔ)引擎在執(zhí)行簡(jiǎn)單 update 語(yǔ)句 update t set n = n + 1 where id = 2 時(shí)的流程(因?yàn)榇死粓?zhí)行單條更新語(yǔ)句奕筐,所以其自身就是一個(gè)事務(wù))舱痘。

  1. 執(zhí)行器先找引擎取 ID=2 這一行。ID 是主鍵离赫,引擎直接用樹(shù)搜索找到這一行芭逝。如果 ID=2 這一行所在的數(shù)據(jù)頁(yè)本來(lái)就在內(nèi)存中,就直接返回給執(zhí)行器渊胸;否則旬盯,需要先從磁盤(pán)讀入內(nèi)存,然后再返回翎猛。
  2. 執(zhí)行器拿到引擎給的行數(shù)據(jù)胖翰,把這個(gè)值加上1,比如原來(lái)是 N切厘,現(xiàn)在就是 N+1萨咳,得到新的一行數(shù)據(jù),再調(diào)用引擎接口寫(xiě)入這行新數(shù)據(jù)疫稿。
  3. 引擎將這行新數(shù)據(jù)更新到內(nèi)存中培他。然后將對(duì)內(nèi)存數(shù)據(jù)頁(yè)的更新內(nèi)容記錄在 Redo Log Buffer 中(這里不詳細(xì)介紹 Redo Log Buffer。只需知道對(duì) Redo Log 的操作并不會(huì)直接寫(xiě)在文件上遗座,而是先記錄在內(nèi)存中舀凛,然后在特定時(shí)刻才會(huì)寫(xiě)入磁盤(pán))。此時(shí)完成了數(shù)據(jù)更新操作途蒋。
  4. 接下來(lái)要進(jìn)行事務(wù)提交的操作猛遍。事務(wù)提交時(shí),Redo Log 被標(biāo)記為 Prepare 狀態(tài)。通常此時(shí)懊烤,Redo Log 會(huì)從 Buffer 寫(xiě)入磁盤(pán)(innodb_flush_log_at_trx_commit梯醒,值為1時(shí),每次提交事務(wù) Redo Log 都會(huì)寫(xiě)入磁盤(pán))奸晴。然后 InnoDB 告知執(zhí)行器執(zhí)行完成冤馏,可以提交事務(wù)日麸。
  5. 執(zhí)行器生成本次操作的 Binlog寄啼,并把 Binlog 寫(xiě)入磁盤(pán)。
  6. 執(zhí)行器調(diào)用引擎的提交事務(wù)接口代箭,引擎把剛剛寫(xiě)入的 Redo Log 改成提交 Commit 狀態(tài)墩划,更新完成。

▼ 下圖描述了 update 語(yǔ)句執(zhí)行過(guò)程中 MySQL 執(zhí)行器嗡综、InnoDB乙帮,以及 Binlog、Redo Log 交互過(guò)程(圖中深綠底色的是 MySQL 執(zhí)行器負(fù)責(zé)的階段极景,淺綠底色是 InnoDB 負(fù)責(zé)的階段)

五察净、問(wèn)題原因簡(jiǎn)析

從上面對(duì) MySQL 原理的介紹我們得知,寫(xiě) Binlog 發(fā)生在事務(wù)提交階段盼樟,但是 MySQL 因?yàn)樵?Server 層和存儲(chǔ)引擎層都引入了不同的日志結(jié)構(gòu)氢卡,從而引入了兩階段提交。Binlog 的寫(xiě)入發(fā)生在存儲(chǔ)引擎真正提交事務(wù)之前晨缴,這導(dǎo)致理論上通過(guò) Binlog 同步數(shù)據(jù)的系統(tǒng)(MySQL 從庫(kù)译秦、其它數(shù)據(jù)庫(kù)或業(yè)務(wù)系統(tǒng))有可能早于 MySQL 主庫(kù)使最新提交的數(shù)據(jù)生效。

所以上面提到的訂單履約服務(wù)在收到基于 Binlog 的訂單支付事件后卻查到相應(yīng)訂單是未支付的击碗,原因很可能是訂單履約服務(wù)在查詢數(shù)據(jù)時(shí)筑悴,訂單支付數(shù)據(jù)更新操作在 MySQL 內(nèi)部尚未徹底完成事務(wù)的提交。

我們通過(guò)開(kāi)發(fā)驗(yàn)證程序重現(xiàn)了這一現(xiàn)象稍途。驗(yàn)證程序接收到事務(wù)提交完成后的完整 Binlog 時(shí)會(huì)再次在 MySQL 主庫(kù)上查詢對(duì)應(yīng)的記錄阁吝,結(jié)果會(huì)有一定概覽獲得事務(wù)提交前的數(shù)據(jù)。

另外經(jīng)過(guò)了解械拍,也有同行反映遇到過(guò)從庫(kù)早于主庫(kù)看到數(shù)據(jù)提交的問(wèn)題突勇。

六、問(wèn)題解決方法

在了解問(wèn)題背后的原因之后殊者,我們需要思考如何解決此問(wèn)題与境。目前解決此問(wèn)題有兩個(gè)方法:重試和直接使用 Binlog 數(shù)據(jù)。

重試這種做法簡(jiǎn)單粗暴猖吴,既然問(wèn)題原因是 Binlog 早于事務(wù)提交摔刁,那等一下再重試查詢自然就解決了。但在實(shí)踐中海蔽,需要考慮重試的實(shí)現(xiàn)方法共屈、以及是否會(huì)因?yàn)橹卦囘^(guò)多甚至無(wú)限重試導(dǎo)致服務(wù)異常绑谣。對(duì)于重試的實(shí)現(xiàn),可使用的方法有線程 Sleep 大法和消息重投等方式拗引。線程 Sleep 大法通常是不被推薦的借宵,因?yàn)樗鼤?huì)導(dǎo)致線程利用率降低,甚至導(dǎo)致服務(wù)無(wú)法響應(yīng)矾削。但考慮到本次問(wèn)題出現(xiàn)概率較低壤玫,我們認(rèn)為線程 Sleep 大法是可以使用的,并且此方式簡(jiǎn)單易行哼凯,可用于問(wèn)題的快速修復(fù)欲间。

第二種重試方式是消息重投,比如 RocketMQ 中 Consumer 返回 ConsumeConcurrentlyStatus.RECONSUME_LATER 即可觸發(fā)消息重投断部。但這種重試方法成本較前一種方法高猎贴,另外重試間隔也相對(duì)較大,對(duì)時(shí)間敏感的業(yè)務(wù)影響也較大蝴光,因此是否采用此方法需從業(yè)務(wù)和技術(shù)兩個(gè)角度綜合考慮她渴。

除了考慮用何種方式重試,還要考慮 ABA 問(wèn)題蔑祟,即狀態(tài)變化按照 A->B->A 的方式進(jìn)行趁耗。業(yè)務(wù)系統(tǒng)期待的狀態(tài)是 B,但實(shí)際可能沒(méi)辦法再變成 B 了做瞪。因此在用重試解決此問(wèn)題之前对粪,需要先排除業(yè)務(wù)系統(tǒng)存在 ABA 問(wèn)題的可能。對(duì)于狀態(tài) ABA 問(wèn)題装蓬,可用狀態(tài)機(jī)等方式解決著拭,這里不再展開(kāi)討論。

除了重試牍帚,另一種方法就是直接使用 Binlog儡遮。因?yàn)?Binlog (row 格式) 直接反映了數(shù)據(jù)的變化情況,其中可以記錄事務(wù)提交涉及到的完整數(shù)據(jù)暗赶,因此可直接用作業(yè)務(wù)處理鄙币。這樣還可以降低數(shù)據(jù)庫(kù) QPS。如果是新設(shè)計(jì)的系統(tǒng)蹂随,我認(rèn)為這樣做法比較理想十嘿。但對(duì)于已有系統(tǒng),這種方式改動(dòng)可能較大岳锁,是否采用需權(quán)衡成本和收益绩衷。

我的技術(shù)公眾號(hào)“編走編想”
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咳燕,更是在濱河造成了極大的恐慌勿决,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件招盲,死亡現(xiàn)場(chǎng)離奇詭異低缩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)曹货,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)咆繁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人控乾,你說(shuō)我怎么就攤上這事么介。” “怎么了蜕衡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)设拟。 經(jīng)常有香客問(wèn)我慨仿,道長(zhǎng),這世上最難降的妖魔是什么纳胧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任镰吆,我火速辦了婚禮,結(jié)果婚禮上跑慕,老公的妹妹穿的比我還像新娘万皿。我一直安慰自己,他們只是感情好核行,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布牢硅。 她就那樣靜靜地躺著,像睡著了一般芝雪。 火紅的嫁衣襯著肌膚如雪减余。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天惩系,我揣著相機(jī)與錄音位岔,去河邊找鬼。 笑死堡牡,一個(gè)胖子當(dāng)著我的面吹牛抒抬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晤柄,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼擦剑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起抓于,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤做粤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后捉撮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體怕品,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年巾遭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肉康。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灼舍,死狀恐怖吼和,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骑素,我是刑警寧澤炫乓,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站献丑,受9級(jí)特大地震影響末捣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜创橄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一箩做、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妥畏,春花似錦邦邦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至馍管,卻和暖如春郭赐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背确沸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工捌锭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人罗捎。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓观谦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親桨菜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子豁状,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345