淺談分布式任務(wù)調(diào)度框架

前言

上一篇文章談了單機(jī)的定時(shí)任務(wù)解決方案获洲,只能在單個(gè)JVM進(jìn)程中使用元潘;而我們的現(xiàn)在基本上是分布式場(chǎng)景,需要一套在分布式環(huán)境下高性能柴墩、高可用忙厌、可擴(kuò)展的分布式任務(wù)調(diào)度框架;是否將之前的單機(jī)解決方案部署到分布式就可以江咳?面臨的分布式場(chǎng)景如何實(shí)現(xiàn)分布式的任務(wù)調(diào)度逢净,如何解決單點(diǎn)故障問題實(shí)現(xiàn)高可用?接下來我們首先分析分布式任務(wù)調(diào)度框架相對(duì)單機(jī)的優(yōu)勢(shì)以及結(jié)合幾種任務(wù)調(diào)度框架分析是如何逐步實(shí)現(xiàn)分布式的高可用歼指、效率的爹土,最后綜合比較下業(yè)界比較流行的框架,在項(xiàng)目開發(fā)中方便選擇踩身。

Why 分布式任務(wù)調(diào)度框架

背景

1胀茵、單機(jī)單點(diǎn)故障

舉個(gè)例子,村里只有一口井惰赋,有口井突然被污染了宰掉,村里就都沒有井水喝了;分布式就是平時(shí)挖了多口井赁濒,一口井出問題照樣有水喝。


image.png
image.png

之前我們說到單機(jī)的定時(shí)任務(wù)可能機(jī)器存在異常孟害,如果沒有分布式任務(wù)調(diào)度拒炎,那這個(gè)機(jī)器上所有定時(shí)任務(wù)只能等到這個(gè)機(jī)器恢復(fù)后才可以執(zhí)行,這顯然可用性就很低挨务。

分布式任務(wù)調(diào)度就是在集群中多臺(tái)調(diào)度击你、多臺(tái)執(zhí)行玉组,一臺(tái)調(diào)度機(jī)器或者執(zhí)行機(jī)器出問題,能夠立刻故障轉(zhuǎn)移丁侄,不影響后續(xù)任務(wù)的執(zhí)行惯雳,提高整體的可用性。

2鸿摇、性能瓶頸

都知道一臺(tái)機(jī)器的CPU石景、內(nèi)存資源是有限的,像我們單機(jī)任務(wù)都直接寫在業(yè)務(wù)機(jī)器上拙吉,單機(jī)任務(wù)瓶頸立現(xiàn)潮孽;當(dāng)定時(shí)任務(wù)多,每秒執(zhí)行上W個(gè)定時(shí)任務(wù)筷黔,單機(jī)是難以支撐的往史,而且定時(shí)任務(wù)會(huì)影響到業(yè)務(wù)系統(tǒng)的資源,整個(gè)系統(tǒng)就會(huì)非常不可靠佛舱。單機(jī)靠多線程椎例,單機(jī)瓶頸達(dá)到后就要依靠分布式集群來水平擴(kuò)展,解決資源瓶頸問題请祖。

3粟矿、協(xié)同效率

每個(gè)定時(shí)任務(wù)調(diào)度的使用業(yè)務(wù)方都需要自己在業(yè)務(wù)系統(tǒng)構(gòu)造一套分布式定時(shí)任務(wù)調(diào)度框架嗎?這顯然是低效损拢?專業(yè)分工是必然的發(fā)展趨勢(shì)陌粹,這就需要分布式的任務(wù)調(diào)度框架的出現(xiàn),其他業(yè)務(wù)作為接入方福压,使用即可掏秩,不需要再考慮分布式調(diào)度的調(diào)度策略的高可用、異常故障恢復(fù)荆姆、控制臺(tái)配置等等問題蒙幻,只需要專注業(yè)務(wù)邏輯即可。

演進(jìn)過程

什么是分布式任務(wù)調(diào)度

分布式任務(wù)調(diào)度胆筒,三個(gè)關(guān)鍵詞:分布式邮破、任務(wù)調(diào)度、配置中心仆救。
分布式:平臺(tái)是分布式部署的抒和,各個(gè)節(jié)點(diǎn)之間可以無(wú)狀態(tài)和無(wú)限的水平擴(kuò)展(保證可擴(kuò)展);

任務(wù)調(diào)度:涉及到任務(wù)狀態(tài)管理彤蔽、任務(wù)調(diào)度請(qǐng)求的發(fā)送與接收摧莽、具體任務(wù)的分配、任務(wù)的具體執(zhí)行顿痪;(集群中哪些機(jī)器什么時(shí)候執(zhí)行什么任務(wù)镊辕,所以又需要一個(gè)可以感知整個(gè)集群運(yùn)行狀態(tài)的配置中心)

配置中心:可以感知整個(gè)集群的狀態(tài)油够、任務(wù)信息的注冊(cè)

常見的分布式任務(wù)調(diào)度框架一般有以下5個(gè)部分
1、控制臺(tái):負(fù)責(zé)調(diào)度任務(wù)的配置征懈、任務(wù)狀態(tài)石咬、信息展示
2、接入:將控制臺(tái)的任務(wù)轉(zhuǎn)化下發(fā)給調(diào)度器卖哎,并且向注冊(cè)中心注冊(cè)任務(wù)
3鬼悠、調(diào)度器:接收接入下發(fā)的調(diào)度任務(wù),進(jìn)行任務(wù)拆分下發(fā)棉饶,在注冊(cè)中心找執(zhí)行器厦章,然后把任務(wù)下發(fā)到執(zhí)行器執(zhí)行,同時(shí)也注冊(cè)到注冊(cè)中心
4照藻、執(zhí)行器:接收調(diào)度任務(wù)袜啃,并且上報(bào)狀態(tài)給注冊(cè)中心
5、注冊(cè)中心:機(jī)器幸缕、任務(wù)狀態(tài)的同步群发、協(xié)調(diào)

現(xiàn)在林林總總的框架,大部分都是在Quartz的基礎(chǔ)上進(jìn)行改進(jìn)发乔,我們先來看看經(jīng)典的Quartz怎么做的熟妓?

Quartz

Quartz是OpenSymphony開源組織在任務(wù)調(diào)度領(lǐng)域的一個(gè)開源項(xiàng)目,完全基于java實(shí)現(xiàn)栏尚。作為一個(gè)優(yōu)秀的開源框架起愈,Quartz具有以下特點(diǎn):強(qiáng)大的調(diào)度功能、靈活的應(yīng)用方式译仗、分布式和集群能力抬虽,另外作為spring默認(rèn)的調(diào)度框架,很容易實(shí)現(xiàn)與Spring集成纵菌,實(shí)現(xiàn)靈活可配置的調(diào)度功能阐污。

Quartz框架的核心對(duì)象

Scheduler – 核心調(diào)度器,就是任務(wù)調(diào)度咱圆、分配的控制器
Job – 任務(wù)笛辟,代表具體要執(zhí)行的任務(wù),是個(gè)接口序苏,里面有默認(rèn)方法手幢,開發(fā)者需要實(shí)現(xiàn)該接口,并且業(yè)務(wù)邏輯寫在默認(rèn)的execute方法中
JobDetail – 任務(wù)描述杠览,描述job的靜態(tài)消息弯菊,是調(diào)度器需要的數(shù)據(jù),跟Job區(qū)分開來踱阿,主要是為了一個(gè)Job可以在多臺(tái)機(jī)器并行管钳,每個(gè)調(diào)度器new一個(gè)Job的實(shí)現(xiàn)類
Trigger -- 觸發(fā)器,用于定義任務(wù)調(diào)度的時(shí)間規(guī)則

#對(duì)象之間的關(guān)系

這是單機(jī)Quartz最小的執(zhí)行單元的關(guān)系


image

集群部署

image.png

上圖3個(gè)節(jié)點(diǎn)在數(shù)據(jù)庫(kù)中都有同一份Job定義软舌,如果某一個(gè)節(jié)點(diǎn)失效才漆,那么Job會(huì)在其他節(jié)點(diǎn)上執(zhí)行。因?yàn)槊總€(gè)節(jié)點(diǎn)上的代碼都是一樣的佛点,那么如何保證只有一臺(tái)機(jī)器上觸發(fā)呢醇滥?答案是使用了數(shù)據(jù)庫(kù)鎖。在quartz集群解決方案了有張scheduler_locks超营,采用了悲觀鎖的方式對(duì)triggers表進(jìn)行了行加鎖鸳玩,以保證任務(wù)同步的正確性。

簡(jiǎn)單來說演闭,quartz的分布式調(diào)度策略是以數(shù)據(jù)庫(kù)為邊界的一種異步策略不跟。各個(gè)調(diào)度器都遵守一個(gè)基于數(shù)據(jù)庫(kù)鎖的操作規(guī)則從而保證了操作的唯一性,同時(shí)多個(gè)節(jié)點(diǎn)的異步運(yùn)行保證了服務(wù)的可靠米碰。(實(shí)際上是用數(shù)據(jù)庫(kù)鎖作為分布式鎖解決同步問題實(shí)現(xiàn)異步運(yùn)行窝革,跟redis、zk做分布式鎖時(shí)是一樣的)

但這種策略有自己的局限性:集群特性對(duì)于高CPU使用率的任務(wù)效果特別好吕座,但是對(duì)于大量的短任務(wù)虐译,各個(gè)節(jié)點(diǎn)都會(huì)搶占數(shù)據(jù)庫(kù)鎖,這樣就出現(xiàn)大量的線程等待資源吴趴。

因此Quartz的分布式只解決了任務(wù)高可用(減少單點(diǎn)故障)的問題漆诽,處理能力瓶頸會(huì)在數(shù)據(jù)庫(kù),而且沒有執(zhí)行層面的任務(wù)分片锣枝,無(wú)法最大化效率厢拭,只能依靠shedulex調(diào)度層面做分片,但是調(diào)度層做并行分片難以結(jié)合實(shí)際的運(yùn)行資源情況做最優(yōu)的分片。

quartz通過數(shù)據(jù)庫(kù)鎖的方式來保證分布式環(huán)境下定時(shí)任務(wù)調(diào)度的同步烤宙,解決了單點(diǎn)故障钞澳,只引入了數(shù)據(jù)庫(kù),整體的結(jié)構(gòu)簡(jiǎn)單回季;但是在效率上,由于數(shù)據(jù)庫(kù)鎖帶來的競(jìng)爭(zhēng)沖突正林,會(huì)使得在短任務(wù)較多時(shí)的低效泡一,并且沒有在執(zhí)行時(shí)對(duì)任務(wù)分片,無(wú)法充分利用集群性能觅廓,也就是說沒法真正的做到水平擴(kuò)展鼻忠,瓶頸被數(shù)據(jù)庫(kù)鎖限制住了。

Elastic-job

要解決這個(gè)分布式的水平擴(kuò)展杈绸、效率問題帖蔓,我們知道需要引入注冊(cè)中心進(jìn)行協(xié)調(diào)矮瘟,這里當(dāng)當(dāng)退出的Elastic-job就是Quartz的基礎(chǔ)上,引入ZK做注冊(cè)中心塑娇。并且在2.0版本后出現(xiàn)了兩個(gè)相互獨(dú)立的產(chǎn)品線:Elastic-job-lite和Elastic-job-cloud澈侠。Elastic-job-lite定位為輕量級(jí)無(wú)中心化的解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù)埋酬,外部依賴僅依賴于zookeeper哨啃。

elastic-job-lite的結(jié)構(gòu)

這款輕量級(jí)的架構(gòu)做了很多的改進(jìn),這里只談到兩點(diǎn)写妥,
1拳球、無(wú)中心調(diào)度節(jié)點(diǎn)
Elastic-job-lite并無(wú)作業(yè)調(diào)度中心節(jié)點(diǎn),不像我們談到單機(jī)定時(shí)任務(wù)調(diào)度有統(tǒng)一的排序隊(duì)列珍特,它是基于部署作業(yè)框架的程序在到達(dá)相應(yīng)時(shí)間點(diǎn)時(shí)各自觸發(fā)調(diào)度祝峻。注冊(cè)中心僅用于作業(yè)注冊(cè)和監(jiān)控信息存儲(chǔ),而主作業(yè)節(jié)點(diǎn)僅用于處理分片和清理的功能次坡。
2呼猪、實(shí)現(xiàn)彈性擴(kuò)容
通過zookeeper來動(dòng)態(tài)給job節(jié)點(diǎn)分片。如果很大體量的用戶需要我們?cè)谔囟ǖ臅r(shí)間段內(nèi)計(jì)算完成砸琅,那么我們肯定是希望我們的任務(wù)可以通過集群達(dá)到水平的擴(kuò)展宋距,集群里的每個(gè)節(jié)點(diǎn)都處理部分的用戶,不管用戶的數(shù)量有多大症脂,我們只需要增加機(jī)器就可以了谚赎。
舉個(gè)例子:比如我們希望3臺(tái)機(jī)器跑job,我么將我們的任務(wù)分成3片诱篷,框架通過zk的協(xié)調(diào)壶唤,最終會(huì)讓3臺(tái)機(jī)器分配到0,1棕所,2的任務(wù)片闸盔,比如server0->0、server1->1琳省、server2->2迎吵,當(dāng)server0執(zhí)行時(shí),可以只查詢id%3==0的用戶针贬,server1可以只查詢id%3==1的用戶击费,server2可以只查詢id%3==2的用戶。

在以上的基礎(chǔ)上再增加一個(gè)server3桦他,此時(shí)蔫巩,server3分不到任何的分片,沒有分到任務(wù)分片的程序?qū)⒉粓?zhí)行。如果此時(shí)server2掛了圆仔,那么server2被分到的任務(wù)分片將會(huì)分配給server3垃瞧,所以server3就會(huì)代替server2執(zhí)行。如果此時(shí)server3也掛了荧缘,那么框架也會(huì)自動(dòng)的將server3的任務(wù)分片隨機(jī)分配到server0或者server1皆警,那么就可能成:server0->0拦宣、server1->1,2截粗。

這樣就沒有基于數(shù)據(jù)庫(kù)的鎖沖突問題,也可以實(shí)現(xiàn)水平擴(kuò)展

不過也是有問題的
1鸵隧、分片數(shù)是由業(yè)務(wù)代碼層決定绸罗,調(diào)度執(zhí)行協(xié)調(diào)時(shí)沒法進(jìn)一步優(yōu)化,比較靜態(tài)豆瘫,機(jī)器擴(kuò)容后其實(shí)沒法直接用到擴(kuò)容后的性能
2珊蟀、缺乏統(tǒng)一調(diào)度,每個(gè)調(diào)度任務(wù)有重復(fù)的調(diào)度開銷(檢測(cè)任務(wù)trigger)外驱,并且在實(shí)現(xiàn)復(fù)雜的dag調(diào)度時(shí)育灸,只能把所有業(yè)務(wù)調(diào)度寫在一個(gè)實(shí)現(xiàn)中,不夠靈活昵宇。

阿里的定時(shí)任務(wù)框架

1磅崭、早期是:TBSchedule

也是基于Zk做注冊(cè)中心
優(yōu)點(diǎn):是支持集群、分布式瓦哎,靈活的任務(wù)分片砸喻,并且有動(dòng)態(tài)的服務(wù)擴(kuò)容和資源回收
缺點(diǎn):使用的是Timer而不是線程池執(zhí)行任務(wù)調(diào)度。TBSchedule的作業(yè)類型比較單一蒋譬,只能是獲取/處理數(shù)據(jù)一種模式割岛,而且目前文檔偏少

2、目前推出了基于Akka架構(gòu)的Schedulerx2.0

新一代定時(shí)任務(wù)犯助,提供分布式執(zhí)行癣漆、多種任務(wù)類型、統(tǒng)一日志等框架剂买,用戶只要依賴schedulerx-worker這個(gè)jar包惠爽,通過schedulerx2.0提供的編程模型,簡(jiǎn)單幾行代碼就能實(shí)現(xiàn)一套高可靠可運(yùn)維的分布式執(zhí)行引擎雷恃。在海量數(shù)據(jù)并行任務(wù)疆股、復(fù)雜dag調(diào)度

可擴(kuò)展的執(zhí)行引擎

Worker總體架構(gòu)參考Yarn的架構(gòu),分為TaskMaster, Container, Processor三層:

image
  • TaskMaster:類似于yarn的AppMaster倒槐,支持可擴(kuò)展的分布式執(zhí)行框架旬痹,進(jìn)行整個(gè)jobInstance的生命周期管理、container的資源管理,同時(shí)還有failover等能力两残。默認(rèn)實(shí)現(xiàn)StandaloneTaskMaster(單機(jī)執(zhí)行)永毅,BroadcastTaskMaster(廣播執(zhí)行),MapTaskMaster(并行計(jì)算人弓、內(nèi)存網(wǎng)格沼死、網(wǎng)格計(jì)算),MapReduceTaskMaster(并行計(jì)算崔赌、內(nèi)存網(wǎng)格意蛀、網(wǎng)格計(jì)算)。
  • Container:執(zhí)行業(yè)務(wù)邏輯的容器框架健芭,支持線程/進(jìn)程/docker/actor等县钥。
  • Processor:業(yè)務(wù)邏輯框架,不同的processor表示不同的任務(wù)類型慈迈。

以MapTaskMaster為例若贮,大概的原理如下圖所示:

image

其借鑒了MapReduce的模式,支持Map痒留、MapReduce模型谴麦,在海量數(shù)據(jù)分發(fā)多臺(tái)機(jī)器的效率上非常方便,支持分布跑批伸头,針對(duì)不同的跑批場(chǎng)景匾效,map模型作業(yè)還提供了并行計(jì)算、內(nèi)存網(wǎng)格熊锭、網(wǎng)格計(jì)算三種執(zhí)行方式:

并行計(jì)算:子任務(wù)300以下弧轧,有子任務(wù)列表。
內(nèi)存網(wǎng)格:子任務(wù)5W以下碗殷,無(wú)子任務(wù)列表精绎,速度快。
網(wǎng)格計(jì)算:子任務(wù)100W以下锌妻,無(wú)子任務(wù)列表代乃。

并行計(jì)算實(shí)例

考拉的kSchedule

這里再說一個(gè)考拉的分布式定時(shí)任務(wù)框架kSchedule,大體與elastic-job類似仿粹,


kschedule的部署架構(gòu)

這里說一點(diǎn)搁吓,kSchedule的無(wú)侵入性做的更好,對(duì)于簡(jiǎn)單任務(wù)不需要事先Job接口吭历,只需要把任務(wù)bean注冊(cè)成容器的Service的public方法即可堕仔,然后再配置界面配置調(diào)度任務(wù)的方法和參數(shù)即可,大大的方便的簡(jiǎn)單任務(wù)的開發(fā)和配置工作晌区;(其實(shí)就是實(shí)現(xiàn)了普通類的方法級(jí)別的定時(shí)任務(wù)配置摩骨,而一般的定時(shí)任務(wù)都是類繼承Job類通贞,重寫execute方法)

這點(diǎn)在其他框架中實(shí)現(xiàn)時(shí)需要寫個(gè)簡(jiǎn)單任務(wù)的調(diào)度分配任務(wù),然后把普通類的方法和入?yún)⒆鳛閯?dòng)態(tài)參數(shù)傳到調(diào)度分配任務(wù)恼五,然后利用反射昌罩,進(jìn)行動(dòng)態(tài)執(zhí)行。

綜合比較選型

簡(jiǎn)單幾條原則
1灾馒、業(yè)務(wù)起步階段:沒有自主研發(fā)運(yùn)維能力茎用,選擇業(yè)界使用最多最成熟的,最好是直接買睬罗,比如阿里云的Schedulerx2.0轨功,把技術(shù)、運(yùn)維都交給阿里云傅物,只開發(fā)業(yè)務(wù)邏輯即可夯辖;或者Elastic-job-cloud版本,在私有云上部署董饰,功能支持也比較完善,花錢都能解決
2圆米、業(yè)務(wù)發(fā)展階段:數(shù)據(jù)規(guī)模和任務(wù)規(guī)模都在擴(kuò)大卒暂,有一定的研發(fā)能力,可以考慮接入成熟開源框架娄帖,比如quartz或者Elastic-job-lite都是開源的也祠,幾臺(tái)機(jī)器搭建起來就可以跑,出問題了開源用解答的也比較多近速。每秒幾千個(gè)任務(wù)沒問題
3诈嘿、業(yè)務(wù)成熟階段:每秒任務(wù)擴(kuò)大到幾萬(wàn)、幾十萬(wàn)個(gè)削葱,而且業(yè)務(wù)個(gè)性化需要越來越多奖亚,比如各種調(diào)度策略,批處理任務(wù)的個(gè)性化支持析砸,這時(shí)候要選擇一個(gè)開源框架的基礎(chǔ)上進(jìn)行二次開發(fā)昔字,目前quartz或者Elastic-job-lite都是不錯(cuò)的選擇

具體的對(duì)比表格
各個(gè)框架對(duì)比文檔---轉(zhuǎn)自:分布式調(diào)度框架大集合

參考文章

分布式調(diào)度框架大集合
詳解應(yīng)對(duì)平臺(tái)高并發(fā)的分布式調(diào)度框架TBSchedule
Quartz架構(gòu)整理
開源的作業(yè)調(diào)度框架Quartz
考拉定時(shí)任務(wù)框架kSchedule
Schedulerx2.0分布式計(jì)算原理&最佳實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市首繁,隨后出現(xiàn)的幾起案子作郭,更是在濱河造成了極大的恐慌,老刑警劉巖弦疮,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夹攒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡胁塞,警方通過查閱死者的電腦和手機(jī)咏尝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門堂湖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人状土,你說我怎么就攤上這事无蜂。” “怎么了蒙谓?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵斥季,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我累驮,道長(zhǎng)酣倾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任谤专,我火速辦了婚禮躁锡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘置侍。我一直安慰自己映之,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布蜡坊。 她就那樣靜靜地躺著杠输,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秕衙。 梳的紋絲不亂的頭發(fā)上蠢甲,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音据忘,去河邊找鬼鹦牛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛勇吊,可吹牛的內(nèi)容都是我干的曼追。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼萧福,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼拉鹃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鲫忍,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤膏燕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后悟民,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坝辫,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年射亏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了近忙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竭业。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖及舍,靈堂內(nèi)的尸體忽然破棺而出未辆,到底是詐尸還是另有隱情,我是刑警寧澤锯玛,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布咐柜,位于F島的核電站,受9級(jí)特大地震影響攘残,放射性物質(zhì)發(fā)生泄漏拙友。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一歼郭、第九天 我趴在偏房一處隱蔽的房頂上張望遗契。 院中可真熱鬧,春花似錦病曾、人聲如沸牍蜂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捷兰。三九已至,卻和暖如春负敏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秘蛇。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工其做, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赁还。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓妖泄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親艘策。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹈胡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349