Redis線程模型的前世今生

前言

眾所周知震糖,Redis是一個(gè)高性能的數(shù)據(jù)存儲(chǔ)框架总珠,在高并發(fā)的系統(tǒng)設(shè)計(jì)中,Redis也是一個(gè)比較關(guān)鍵的組件溉仑,是我們提升系統(tǒng)性能的一大利器熄攘。深入去理解Redis高性能的原理顯得越發(fā)重要,當(dāng)然Redis的高性能設(shè)計(jì)是一個(gè)系統(tǒng)性的工程彼念,涉及到很多內(nèi)容挪圾,本文重點(diǎn)關(guān)注Redis的IO模型,以及基于IO模型的線程模型逐沙。

我們從IO的起源開(kāi)始哲思,講述了阻塞IO、非阻塞IO吩案、多路復(fù)用IO棚赔。基于多路復(fù)用IO徘郭,我們也梳理了幾種不同的Reactor模型靠益,并分析了幾種Reactor模型的優(yōu)缺點(diǎn)〔腥啵基于Reactor模型我們開(kāi)始了Redis的IO模型和線程模型的分析胧后,并總結(jié)出Redis線程模型的優(yōu)點(diǎn)、缺點(diǎn)抱环,以及后續(xù)的Redis多線程模型方案壳快。本文的重點(diǎn)是對(duì)Redis線程模型設(shè)計(jì)思想的梳理纸巷,捋順了設(shè)計(jì)思想,就是一通百通的事了眶痰。

注:本文的代碼都是偽代碼瘤旨,主要是為了示意,不可用于生產(chǎn)環(huán)境竖伯。

我們常說(shuō)的網(wǎng)絡(luò)IO模型存哲,主要包含阻塞IO、非阻塞IO七婴、多路復(fù)用IO宏胯、信號(hào)驅(qū)動(dòng)IO、異步IO本姥,本文重點(diǎn)關(guān)注跟Redis相關(guān)的內(nèi)容肩袍,所以我們重點(diǎn)分析阻塞IO、非阻塞IO婚惫、多路復(fù)用IO氛赐,幫助大家后續(xù)更好的理解Redis網(wǎng)絡(luò)模型。

我們先看下面這張圖先舷;

我們經(jīng)常說(shuō)的阻塞IO其實(shí)分為兩種艰管,一種是單線程阻塞,一種是多線程阻塞蒋川。這里面其實(shí)有兩個(gè)概念牲芋,阻塞和線程。

阻塞:指調(diào)用結(jié)果返回之前捺球,當(dāng)前線程會(huì)被掛起缸浦,調(diào)用線程只有在得到結(jié)果之后才會(huì)返回;

線程:系統(tǒng)調(diào)用的線程個(gè)數(shù)氮兵。

像建立連接裂逐、讀、寫(xiě)都涉及到系統(tǒng)調(diào)用泣栈,本身是一個(gè)阻塞的操作卜高。

服務(wù)端單線程來(lái)處理,當(dāng)客戶(hù)端請(qǐng)求來(lái)臨時(shí)南片,服務(wù)端用主線程來(lái)處理連接掺涛、讀取、寫(xiě)入等操作疼进。

以下用代碼模擬了單線程的阻塞模式薪缆;

我們準(zhǔn)備用兩個(gè)客戶(hù)端同時(shí)發(fā)起連接請(qǐng)求、來(lái)模擬單線程阻塞模式的現(xiàn)象颠悬。同時(shí)發(fā)起連接,通過(guò)服務(wù)端日志,我們發(fā)現(xiàn)此時(shí)服務(wù)端只接受了其中一個(gè)連接恢筝,主線程被阻塞在上一個(gè)連接的read方法上鲸伴。

我們嘗試關(guān)閉第一個(gè)連接,看第二個(gè)連接的情況灾票,我們希望看到的現(xiàn)象是峡谊,主線程返回,新的客戶(hù)端連接被接受刊苍。

從日志中發(fā)現(xiàn)既们,在第一個(gè)連接被關(guān)閉后,第二個(gè)連接的請(qǐng)求被處理了正什,也就是說(shuō)第二個(gè)連接請(qǐng)求在排隊(duì)啥纸,直到主線程被喚醒,才能接收下一個(gè)請(qǐng)求婴氮,符合我們的預(yù)期斯棒。

此時(shí)不僅要問(wèn),為什么呢主经?

主要原因在于accept荣暮、read、write三個(gè)函數(shù)都是阻塞的罩驻,主線程在系統(tǒng)調(diào)用的時(shí)候穗酥,線程是被阻塞的,其他客戶(hù)端的連接無(wú)法被響應(yīng)惠遏。

通過(guò)以上流程砾跃,我們很容易發(fā)現(xiàn)這個(gè)過(guò)程的缺陷,服務(wù)器每次只能處理一個(gè)連接請(qǐng)求节吮,CPU沒(méi)有得到充分利用蜓席,性能比較低。如何充分利用CPU的多核特性呢课锌?自然而然的想到了——多線程邏輯厨内。

對(duì)工程師而言,代碼解釋一切渺贤,直接上代碼雏胃。

BIO多線程

同樣,我們并行發(fā)起兩個(gè)請(qǐng)求志鞍;

兩個(gè)請(qǐng)求瞭亮,都被接受,服務(wù)端新增兩個(gè)線程來(lái)處理客戶(hù)端的連接和后續(xù)請(qǐng)求固棚。

我們用多線程解決了统翩,服務(wù)器同時(shí)只能處理一個(gè)請(qǐng)求的問(wèn)題仙蚜,但同時(shí)又帶來(lái)了一個(gè)問(wèn)題,如果客戶(hù)端連接比較多時(shí)厂汗,服務(wù)端會(huì)創(chuàng)建大量的線程來(lái)處理請(qǐng)求委粉,但線程本身是比較耗資源的,創(chuàng)建娶桦、上下文切換都比較耗資源贾节,又如何去解決呢?

如果我們把所有的Socket(文件句柄衷畦,后續(xù)用Socket來(lái)代替fd的概念栗涂,盡量減少概念,減輕閱讀負(fù)擔(dān))都放到隊(duì)列里祈争,只用一個(gè)線程來(lái)輪訓(xùn)所有的Socket的狀態(tài)斤程,如果準(zhǔn)備好了就把它拿出來(lái),是不是就減少了服務(wù)端的線程數(shù)呢菩混?

一起看下代碼忿墅,單純非阻塞模式,我們基本上不用墨吓,為了演示邏輯球匕,我們模擬了相關(guān)代碼如下;

系統(tǒng)初始化帖烘,等待連接亮曹;

發(fā)起兩個(gè)客戶(hù)端連接,線程開(kāi)始輪詢(xún)兩個(gè)連接中是否有數(shù)據(jù)秘症。

兩個(gè)連接分別輸入數(shù)據(jù)后照卦,輪詢(xún)線程發(fā)現(xiàn)有數(shù)據(jù)準(zhǔn)備好了,開(kāi)始相關(guān)的邏輯處理(單線程乡摹、多線程都可)役耕。

再用一張流程圖輔助解釋下(系統(tǒng)實(shí)際采用文件句柄,此時(shí)用Socket來(lái)代替聪廉,方便大家理解)瞬痘。

服務(wù)端專(zhuān)門(mén)有一個(gè)線程來(lái)負(fù)責(zé)輪詢(xún)所有的Socket,來(lái)確認(rèn)操作系統(tǒng)是否完成了相關(guān)事件板熊,如果有則返回處理框全,如果無(wú)繼續(xù)輪詢(xún),大家一起來(lái)思考下干签?此時(shí)又帶來(lái)了什么問(wèn)題呢津辩。

CPU的空轉(zhuǎn)、系統(tǒng)調(diào)用(每次輪詢(xún)到涉及到一次系統(tǒng)調(diào)用,通過(guò)內(nèi)核命令來(lái)確認(rèn)數(shù)據(jù)是否準(zhǔn)備好)喘沿,造成資源的浪費(fèi)闸度,那有沒(méi)有一種機(jī)制,來(lái)解決這個(gè)問(wèn)題呢蚜印?

server端有沒(méi)專(zhuān)門(mén)的線程來(lái)做輪詢(xún)操作(應(yīng)用程序端非內(nèi)核)莺禁,而是由事件來(lái)觸發(fā),當(dāng)有相關(guān)讀晒哄、寫(xiě)睁宰、連接事件到來(lái)時(shí)肪获,主動(dòng)喚起服務(wù)端線程來(lái)進(jìn)行相關(guān)邏輯處理寝凌。模擬了相關(guān)代碼如下;

IO多路復(fù)用

同時(shí)創(chuàng)建兩個(gè)連接孝赫;

兩個(gè)連接無(wú)阻塞的被創(chuàng)建较木;

無(wú)阻塞的接收讀寫(xiě);

再用一張流程圖輔助解釋下(系統(tǒng)實(shí)際采用文件句柄青柄,此時(shí)用Socket來(lái)代替伐债,方便大家理解)。

當(dāng)然操作系統(tǒng)的多路復(fù)用有好幾種實(shí)現(xiàn)方式致开,我們經(jīng)常使用的select()峰锁,epoll模式這里不做過(guò)多的解釋?zhuān)信d趣的可以查看相關(guān)文檔,IO的發(fā)展后面還有異步双戳、事件等模式虹蒋,我們?cè)谶@里不過(guò)多的贅述,我們更多的是為了解釋Redis線程模式的發(fā)展飒货。

我們一起來(lái)聊了阻塞魄衅、非阻塞、IO多路復(fù)用模式塘辅,那Redis采用的是哪種呢晃虫?

Redis采用的是IO多路復(fù)用模式,所以我們重點(diǎn)來(lái)了解下多路復(fù)用這種模式扣墩,如何在更好的落地到我們系統(tǒng)中哲银,不可避免的我們要聊下Reactor模式。

首先我們做下相關(guān)的名詞解釋?zhuān)?/p>

Reactor:類(lèi)似NIO編程中的Selector呻惕,負(fù)責(zé)I/O事件的派發(fā)荆责;

Acceptor:NIO中接收到事件后,處理連接的那個(gè)分支邏輯蟆融;

Handler:消息讀寫(xiě)處理等操作類(lèi)草巡。

處理流程

優(yōu)點(diǎn)

模型比較簡(jiǎn)單,所有的處理過(guò)程都在一個(gè)連接里;

實(shí)現(xiàn)上比較容易山憨,模塊功能也比較解耦查乒,Reactor負(fù)責(zé)多路復(fù)用和事件分發(fā)處理,Acceptor負(fù)責(zé)連接事件處理郁竟,Handler負(fù)責(zé)Scoket讀寫(xiě)事件處理玛迄。

缺點(diǎn)

只有一個(gè)線程,連接處理和業(yè)務(wù)處理共用一個(gè)線程棚亩,無(wú)法充分利用CPU多核的優(yōu)勢(shì)蓖议。

在流量不是特別大、業(yè)務(wù)處理比較快的時(shí)候系統(tǒng)可以有很好的表現(xiàn)讥蟆,當(dāng)流量比較大勒虾、讀寫(xiě)事件比較耗時(shí)情況下,容易導(dǎo)致系統(tǒng)出現(xiàn)性能瓶頸瘸彤。

怎么去解決上述問(wèn)題呢修然?既然業(yè)務(wù)處理邏輯可能會(huì)影響系統(tǒng)瓶頸,那我們是不是可以把業(yè)務(wù)處理邏輯單拎出來(lái)质况,交給線程池來(lái)處理愕宋,一方面減小對(duì)主線程的影響,另一方面利用CPU多核的優(yōu)勢(shì)结榄。這一點(diǎn)希望大家要理解透徹中贝,方便我們后續(xù)理解Redis由單線程模型到多線程模型的設(shè)計(jì)的思路。

這種模型相對(duì)單Reactor單線程模型臼朗,只是將業(yè)務(wù)邏輯的處理邏輯交給了一個(gè)線程池來(lái)處理邻寿。

處理流程

Reactor監(jiān)聽(tīng)連接事件、Socket事件依溯,當(dāng)有連接事件過(guò)來(lái)時(shí)交給Acceptor處理老厌,當(dāng)有Socket事件過(guò)來(lái)時(shí)交個(gè)對(duì)應(yīng)的Handler處理。

Handler完成讀事件后黎炉,包裝成一個(gè)任務(wù)對(duì)象枝秤,交給線程池來(lái)處理,把業(yè)務(wù)處理邏輯交給其他線程來(lái)處理慷嗜。

優(yōu)點(diǎn)

讓主線程專(zhuān)注于通用事件的處理(連接淀弹、讀、寫(xiě))庆械,從設(shè)計(jì)上進(jìn)一步解耦薇溃;

利用CPU多核的優(yōu)勢(shì)。

缺點(diǎn)

有沒(méi)有什么好的辦法來(lái)解決上述問(wèn)題呢缭乘?通過(guò)以上的分析沐序,大家有沒(méi)有發(fā)現(xiàn)一個(gè)現(xiàn)象,當(dāng)某一個(gè)點(diǎn)成為系統(tǒng)瓶頸點(diǎn)時(shí),想辦法把他拿出來(lái)策幼,交個(gè)其他線程來(lái)處理邑时,那這種場(chǎng)景是否適用呢?

這種模型相對(duì)單Reactor多線程模型特姐,只是將Scoket的讀寫(xiě)處理從mainReactor中拎出來(lái)晶丘,交給subReactor線程來(lái)處理。

處理流程

mainReactor主線程負(fù)責(zé)連接事件的監(jiān)聽(tīng)和處理唐含,當(dāng)Acceptor處理完連接過(guò)程后浅浮,主線程將連接分配給subReactor;

subReactor負(fù)責(zé)mainReactor分配過(guò)來(lái)的Socket的監(jiān)聽(tīng)和處理捷枯,當(dāng)有Socket事件過(guò)來(lái)時(shí)交個(gè)對(duì)應(yīng)的Handler處理滚秩;

Handler完成讀事件后,包裝成一個(gè)任務(wù)對(duì)象铜靶,交給線程池來(lái)處理叔遂,把業(yè)務(wù)處理邏輯交給其他線程來(lái)處理他炊。

優(yōu)點(diǎn)

讓主線程專(zhuān)注于連接事件的處理争剿,子線程專(zhuān)注于讀寫(xiě)事件吹,從設(shè)計(jì)上進(jìn)一步解耦痊末;

利用CPU多核的優(yōu)勢(shì)蚕苇。

缺點(diǎn)

以上我們聊了,IO網(wǎng)路模型的發(fā)展歷史凿叠,也聊了IO多路復(fù)用的reactor模式涩笤。那Redis采用的是哪種reactor模式呢?在回答這個(gè)問(wèn)題前盒件,我們先梳理幾個(gè)概念性的問(wèn)題蹬碧。

Redis服務(wù)器中有兩類(lèi)事件,文件事件和時(shí)間事件炒刁。

文件事件:在這里可以把文件理解為Socket相關(guān)的事件恩沽,比如連接、讀翔始、寫(xiě)等罗心;

時(shí)間時(shí)間:可以理解為定時(shí)任務(wù)事件,比如一些定期的RDB持久化操作城瞎。

本文重點(diǎn)聊下Socket相關(guān)的事件渤闷。

首先我們來(lái)看下Redis服務(wù)的線程模型圖;

IO多路復(fù)用負(fù)責(zé)各事件的監(jiān)聽(tīng)(連接脖镀、讀飒箭、寫(xiě)等),當(dāng)有事件發(fā)生時(shí),將對(duì)應(yīng)事件放入隊(duì)列中弦蹂,由事件分發(fā)器根據(jù)事件類(lèi)型來(lái)進(jìn)行分發(fā)漫萄;

如果是連接事件,則分發(fā)至連接應(yīng)答處理器盈匾;GET腾务、SET等redis命令分發(fā)至命令請(qǐng)求處理器。

命令處理完后產(chǎn)生命令回復(fù)事件削饵,再由事件隊(duì)列岩瘦,到事件分發(fā)器,到命令回復(fù)處理器窿撬,回復(fù)客戶(hù)端響應(yīng)启昧。

連接過(guò)程

Redis服務(wù)端主線程監(jiān)聽(tīng)固定端口,并將連接事件綁定連接應(yīng)答處理器劈伴。

客戶(hù)端發(fā)起連接后密末,連接事件被觸發(fā),IO多路復(fù)用程序?qū)⑦B接事件包裝好后丟人事件隊(duì)列跛璧,然后由事件分發(fā)處理器分發(fā)給連接應(yīng)答處理器严里。

連接應(yīng)答處理器創(chuàng)建client對(duì)象以及Socket對(duì)象,我們這里關(guān)注Socket對(duì)象追城,并產(chǎn)生ae_readable事件刹碾,和命令處理器關(guān)聯(lián),標(biāo)識(shí)后續(xù)該Socket對(duì)可讀事件感興趣座柱,也就是開(kāi)始接收客戶(hù)端的命令操作迷帜。

當(dāng)前過(guò)程都是由一個(gè)主線程負(fù)責(zé)處理。

SET命令執(zhí)行過(guò)程

客戶(hù)端發(fā)起SET命令色洞,IO多路復(fù)用程序監(jiān)聽(tīng)到該事件后(讀事件)戏锹,將數(shù)據(jù)包裝成事件丟到事件隊(duì)列中(事件在上個(gè)流程中綁定了命令請(qǐng)求處理器);

事件分發(fā)處理器根據(jù)事件類(lèi)型火诸,將事件分發(fā)給對(duì)應(yīng)的命令請(qǐng)求處理器锦针;

命令請(qǐng)求處理器,讀取Socket中的數(shù)據(jù)惭蹂,執(zhí)行命令伞插,然后產(chǎn)生ae_writable事件,并綁定命令回復(fù)處理器盾碗;

IO多路復(fù)用程序監(jiān)聽(tīng)到寫(xiě)事件后媚污,將數(shù)據(jù)包裝成事件丟到事件隊(duì)列中,事件分發(fā)處理器根據(jù)事件類(lèi)型分發(fā)至命令回復(fù)處理器廷雅;

命令回復(fù)處理器耗美,將數(shù)據(jù)寫(xiě)入Socket中返回給客戶(hù)端京髓。

以上流程分析我們可以看出Redis采用的是單線程Reactor模型,我們也分析了這種模式的優(yōu)缺點(diǎn)商架,那Redis為什么還要采用這種模式呢堰怨?

Redis本身的特性

命令執(zhí)行基于內(nèi)存操作,業(yè)務(wù)處理邏輯比較快蛇摸,所以命令處理這一塊單線程來(lái)做也能維持一個(gè)很高的性能备图。

優(yōu)點(diǎn)

缺點(diǎn)

Reactor單線程模型的缺點(diǎn)也同樣在Redis中來(lái)體現(xiàn),唯一不同的地方就在于業(yè)務(wù)邏輯處理(命令執(zhí)行)這塊不是系統(tǒng)瓶頸點(diǎn)赶袄。

隨著流量的上漲揽涮,IO操作的的耗時(shí)會(huì)越來(lái)越明顯(read操作,內(nèi)核中讀數(shù)據(jù)到應(yīng)用程序饿肺。write操作蒋困,應(yīng)用程序中的數(shù)據(jù)到內(nèi)核),當(dāng)達(dá)到一定閥值時(shí)系統(tǒng)的瓶頸就體現(xiàn)出來(lái)了敬辣。

Redis又是如何去解的呢雪标?

哈哈~將耗時(shí)的點(diǎn)從主線程拎出來(lái)唄?那Redis的新版本是這么做的嗎溉跃?我們一起來(lái)看下村刨。

Redis的多線程模型跟”多Reactor多線程模型“、“單Reactor多線程模型有點(diǎn)區(qū)別”喊积,但同時(shí)用了兩種Reactor模型的思想烹困,具體如下;

Redis的多線程模型是將IO操作多線程化乾吻,本身邏輯處理過(guò)程(命令執(zhí)行過(guò)程)依舊是單線程,借助了單Reactor思想拟蜻,實(shí)現(xiàn)上又有所區(qū)分绎签。

將IO操作多線程化,又跟單Reactor衍生出多Reactor的思想一致酝锅,都是將IO操作從主線程中拎出來(lái)诡必。

命令執(zhí)行大致流程

客戶(hù)端發(fā)送請(qǐng)求命令,觸發(fā)讀就緒事件搔扁,服務(wù)端主線程將Socket(為了簡(jiǎn)化理解成本爸舒,統(tǒng)一用Socket來(lái)代表連接)放入一個(gè)隊(duì)列,主線程不負(fù)責(zé)讀稿蹲;

IO 線程通過(guò)Socket讀取客戶(hù)端的請(qǐng)求命令扭勉,主線程忙輪詢(xún),等待所有 I/O 線程完成讀取任務(wù)苛聘,IO線程只負(fù)責(zé)讀不負(fù)責(zé)執(zhí)行命令涂炎;

主線程一次性執(zhí)行所有命令忠聚,執(zhí)行過(guò)程和單線程一樣,然后需要返回的連接放入另外一個(gè)隊(duì)列中唱捣,有IO線程來(lái)負(fù)責(zé)寫(xiě)出(主線程也會(huì)寫(xiě))两蟀;

主線程忙輪詢(xún),等待所有 I/O 線程完成寫(xiě)出任務(wù)震缭。

了解一個(gè)組件赂毯,更多的是要去了解他的設(shè)計(jì)思路,要去思考為什么要這么設(shè)計(jì)拣宰,做這種技術(shù)選型的背景是啥欢瞪,對(duì)后續(xù)做系統(tǒng)架構(gòu)設(shè)計(jì)有什么參考意義等等。一通百通徐裸,希望對(duì)大家有參考意義遣鼓。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市重贺,隨后出現(xiàn)的幾起案子骑祟,更是在濱河造成了極大的恐慌,老刑警劉巖气笙,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件次企,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡潜圃,警方通過(guò)查閱死者的電腦和手機(jī)缸棵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谭期,“玉大人堵第,你說(shuō)我怎么就攤上這事∷沓觯” “怎么了踏志?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)胀瞪。 經(jīng)常有香客問(wèn)我针余,道長(zhǎng),這世上最難降的妖魔是什么凄诞? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任圆雁,我火速辦了婚禮,結(jié)果婚禮上帆谍,老公的妹妹穿的比我還像新娘伪朽。我一直安慰自己,他們只是感情好既忆,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布驱负。 她就那樣靜靜地躺著嗦玖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪跃脊。 梳的紋絲不亂的頭發(fā)上宇挫,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音酪术,去河邊找鬼器瘪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绘雁,可吹牛的內(nèi)容都是我干的橡疼。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼庐舟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欣除!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起挪略,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤历帚,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后杠娱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體挽牢,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年摊求,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禽拔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡室叉,死狀恐怖睹栖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情太惠,我是刑警寧澤磨淌,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站凿渊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缚柳。R本人自食惡果不足惜埃脏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秋忙。 院中可真熱鬧彩掐,春花似錦、人聲如沸灰追。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朴下,卻和暖如春努咐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背殴胧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工渗稍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人团滥。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓竿屹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親灸姊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拱燃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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