分布式系統(tǒng)一致性高可用的解決方案總結

本文基于對redis麦箍、zookpeer、rocketmq陶珠、elasticsearch學習總結挟裂,對于分布式系統(tǒng)學習,一定繞不開一個點揍诽,那就是CAP定理诀蓉。什么是CAP定理,我這里簡單的復制摘抄一下百度上的文案暑脆。

CAP原則又稱CAP定理渠啤,指的是在一個分布式系統(tǒng)中,一致性(Consistency)饵筑、可用性(Availability)埃篓、分區(qū)容錯性(Partition tolerance)。CAP 原則指的是根资,這三個要素最多只能同時實現(xiàn)兩點,不可能三者兼顧同窘。

說明一下上面的三個要素各代表的含義:

  • 一致性:在一個分布式集群中玄帕,集群中的各個節(jié)點保持數(shù)據(jù)上的一致。
  • 強一致性:對于系統(tǒng)中數(shù)據(jù)的變動想邦,應該被其后所有對該數(shù)據(jù)的訪問都可見
  • 弱一致性:對于系統(tǒng)中數(shù)據(jù)的變動裤纹,允許部分請求對該數(shù)據(jù)的訪問可以不用返回最新的變動
  • 最終一致性:對于系統(tǒng)中數(shù)據(jù)的變動,保證在經(jīng)過一定時間后丧没,對所有對該數(shù)據(jù)的訪問都可見
  • 可用性:在規(guī)定的響應時間內鹰椒,系統(tǒng)能夠正常響應用戶的請求,不會影響用戶體驗
  • 分區(qū)容錯性:當集群中出現(xiàn)一個或多個節(jié)點不可用時(數(shù)量一般小于集群數(shù)量的1/2)呕童,集群依然能夠正常提供服務

CAP定理說明上述的三個要素不能兼顧漆际,最多只能滿足其中的兩個要素,在分布式系統(tǒng)中夺饲,一般都是保證分區(qū)容錯性奸汇,而在一致性和可用性之間做取舍施符。因此存在CP、AP兩種分布式集群的實現(xiàn)擂找。

CP集群戳吝,即滿足一致性和分區(qū)容錯性,如zookpeer

AP集群贯涎,即滿足可用性和分區(qū)容錯性听哭,如redis-cluster

下面,針對與上述的CP和AP問題塘雳,我們展開話題欢唾。

對于分布式系統(tǒng),學習了解多了之后粉捻,發(fā)現(xiàn)其內在的解決方案基本上都是一樣的礁遣,所謂萬變不離其中〖缛校總結一下大體在于以下幾步:

  • 1.數(shù)據(jù)分片
  • 2.數(shù)據(jù)備份/數(shù)據(jù)復制
  • 3.讀寫分離
  • 4.主從切換

數(shù)據(jù)分片

數(shù)據(jù)分片祟霍,很多分布式系統(tǒng)尤其是中間件服務,一般都會涉及高并發(fā)盈包,數(shù)據(jù)量大的問題沸呐,如redis-cluster、recketmq呢燥,以及被大家熟知的Elasticsearch崭添。針對于大數(shù)據(jù)量高并發(fā)的問題,若不做處理叛氨,服務器的性能將會成為服務的瓶頸呼渣,解決的方案之一便是數(shù)據(jù)分片,將大數(shù)據(jù)量在集群中按照一定的規(guī)則分片寞埠,使數(shù)據(jù)按照一定的規(guī)則分布集群的不同服務器上屁置,以減輕單個服務器的壓力,保證服務集群的可用性仁连。

redis-cluster的數(shù)據(jù)分片是通過redis-cluster的哈希槽來實現(xiàn)的蓝角,redis-cluster有16384個哈希槽,這個數(shù)量是固定的饭冬,根據(jù)集群中服務器的數(shù)量可以手動的調配每個服務上存放的hash槽的數(shù)量使鹅,哈希槽之間是相互獨立的,因此對集群的擴展提供了便利昌抠。

rocketmq的分片和topic緊密相關患朱,在使用rocketmq中,無論是消息的生產(chǎn)者還是消費者都需要注冊訂閱一個topic扰魂。在rocketmq集群中麦乞,集群中的broker保存這個topic下數(shù)據(jù)的一部分蕴茴,也就是topic的其中一個數(shù)據(jù)分片。當然姐直,rocketmq不僅將一個topic下的數(shù)據(jù)分片到多個broker上倦淀,而且,一個broker上的topic數(shù)據(jù)還可以被分為多個queue声畏,這是因為rocketmq中撞叽,一個queue只能被一個consumer消費,若是consumer的數(shù)量多于queue的數(shù)量插龄,沒有綁定queue的consumer將不能消費數(shù)據(jù)愿棋。

elasticsearch的數(shù)據(jù)分片在我看來和mysql的分庫分表原理是一樣的,elasticsearch中均牢,每一個索引都相當于mysql的一個表糠雨,將一個索引分成多個shard放在不同的節(jié)點上,每個shard存儲一部分數(shù)據(jù)徘跪。elasticsearch將數(shù)據(jù)進行分片甘邀,這樣可以支持集群的橫向擴展,同時垮庐,多個節(jié)點提供服務可以提高系統(tǒng)的效率和吞吐量松邪。

綜上所述,數(shù)據(jù)分片的一般都有兩個好處哨查,一個是支持集群的橫向擴展逗抑,而是提升服務的吞吐量和性能。數(shù)據(jù)分片解決了以上兩個問題寒亥,但是若是集群中一個節(jié)點發(fā)生宕機邮府,或者因為網(wǎng)絡原因和集群斷開鏈接,那么這部分的數(shù)據(jù)分片甚至整個集群都會不可用护盈,如何解決這個問題挟纱,就需要用到數(shù)據(jù)備份和主備切換。

數(shù)據(jù)分片的策略 了解了數(shù)據(jù)分片之后腐宋,需要了解以下數(shù)據(jù)分片的策略,根據(jù)集群提供服務的性質不同檀轨,可以采用的數(shù)據(jù)分片策略也各有不同胸竞,下面是我學習后的總結:

  • 對于提供條件查詢的數(shù)據(jù)服務,數(shù)據(jù)分片的策略需要在查詢條件的基礎上進行一定的規(guī)則運算参萄,從而得到分片的結果卫枝。采用這種方式的如:redis-cluster和elasticsearch。redis-cluster的分片規(guī)則就是對key進行哈希運算讹挎,得到一個哈希槽的結果校赤。elasticsearch默認是對docid進行運算得到一個sharded的結果吆玖。相同的key和docid其運算結果必定是相同的,因此可以支持數(shù)據(jù)的存取马篮。
  • 對于不必在乎查詢條件的數(shù)據(jù)服務沾乘,數(shù)據(jù)分片的策略就比較多樣,既可以采用上面的分片方案浑测;也可以采用輪詢翅阵、隨機等策略。rocketmq的分片策略就是采用了一種根據(jù)當前topic下的queue數(shù)量按照一定規(guī)則取余的策略迁央,同時rocketmq也提供了MessageQueueSelector接口掷匠,用戶可以自己拓展分片策略,比如根據(jù)某一參數(shù)hash取余等等岖圈。

說到這里讹语,會發(fā)現(xiàn)其實這種分片策略和負載均衡的策略還是挺相似的。

數(shù)據(jù)備份/數(shù)據(jù)復制

數(shù)據(jù)備份蜂科,舉個例子來說顽决,我有兩臺電腦A、電腦B崇摄,A用于工作擎值,B用于游戲,我寫了一篇文章逐抑,保存在電腦上電腦上鸠儿,若是某一天我的電腦A磁盤壞了,那我這篇文章就找不到了厕氨,即便我現(xiàn)在還有電腦B进每,我也沒有辦法在對文章進行編輯。但是若是我在之前命斧,就將文章拷貝了一份放在電腦B上田晚,那么現(xiàn)在,我用電腦B就可以對文件進行編輯修改国葬。

舉這個例子贤徒,我的目的就是為了說明數(shù)據(jù)備份對于集群可用性的意義,例子中汇四,我的兩臺電腦可以認為是集群中兩臺服務器接奈,兩臺服務器一開始提供的服務可能不相同,A電腦提供的就是編輯文章的服務通孽,數(shù)據(jù)備份的意義就在于序宦,當原本提供服務的服務器宕機損壞,集群中另外的服務器仍然可以根據(jù)已經(jīng)備份的數(shù)據(jù)提供相同的服務背苦,而不會影響到用戶的工作互捌。

數(shù)據(jù)備份的目的就是不發(fā)生單點問題的措施之一潘明,但是若是數(shù)據(jù)備份的策略不合適,備份的時機不對秕噪,那么備份的數(shù)據(jù)時效性也是問題钳降。還是從例子出發(fā),這里的文章每次都是我手動從A電腦拷貝到B電腦巢价,這是我的備份策略牲阁,若是我選擇每天晚上才拷貝一次,那么若是A電腦在我拷貝之前壞了壤躲,當天的文章編輯數(shù)據(jù)就丟失了城菊,采用手動的方式備份,這種備份方式耗時耗力且不可控碉克,而在分布式集群中凌唬,不同的系統(tǒng)采用了不同的備份策略,下面一一來說明漏麦。

首先明確一點客税,在分布式集群中,不可能采用人工手動備份撕贞,一定是系統(tǒng)程序按照一定的規(guī)則自動備份更耻,就好像我將AB連在一起,寫個程序捏膨,讓A電腦自動把文章同步到B電腦秧均。數(shù)據(jù)備份的方式分為兩種:

  • 新增slave節(jié)點時的數(shù)據(jù)同步(全量同步/增量同步)

這里以redis-cluster和zookeeper舉例。

在redis-cluster中号涯,當一臺新的slave節(jié)點加入時目胡,會出發(fā)數(shù)據(jù)同步,需要將主節(jié)點的數(shù)據(jù)同步到從節(jié)點链快。這時根據(jù)從節(jié)點的狀態(tài)有兩種同步方案:完整重同步 和 部分重同步

完整重同步既是將主節(jié)點的全部數(shù)據(jù)都復制給新的slave節(jié)點誉己。大致流程為,當一個新的節(jié)點加入進來時域蜗,發(fā)送PSYNC命令給主節(jié)點并攜帶slave節(jié)點自身的信息(重點是復制偏移量)巨双,主節(jié)點會根據(jù)slave傳過來的信息判斷是完整重同步還是部分重同步,如何判斷與數(shù)據(jù)同步時的復制緩沖區(qū)有關霉祸,更細節(jié)不展開介紹炉峰。

  • 完整重同步是指將主服務器的全部數(shù)據(jù)同步到從服務器
  • 部分重同步說明從服務器在完整重同步時斷開連接,只要將還未同步的數(shù)據(jù)同步到服務器即可

相對于redis-cluster脉执,zookeeper中的數(shù)據(jù)同步有四種方式,和redis-cluster完整重同步和部分重同步相似的SNAP(全量同步)和DIFF(增量同步)戒劫,以及zk事務處理相關的TRUNC(僅回滾同步)半夷、TRUNC+DIFF(回滾+增量同步)

  • 集群中主從節(jié)點的數(shù)據(jù)同步(增量同步)

當節(jié)點已經(jīng)加入集群婆廊,成為集群中的從節(jié)點,只要不斷開連接巫橄,一般都只需要進行增量同步淘邻,不過系統(tǒng)同步的范圍和方式有所差異,大致分為下面六種:

  • 同步備份:及主節(jié)點更新數(shù)據(jù)時湘换,立刻將數(shù)據(jù)同步給從節(jié)點宾舅,當從節(jié)點同步完成才返回成功
  • 異步備份:主節(jié)點更新完數(shù)據(jù)即為成功,后開啟異步線程同步數(shù)據(jù)給從節(jié)點
  • 強一致性備份:集群中所有節(jié)點都要同步到數(shù)據(jù)才算數(shù)據(jù)同步
  • 最終一致性備份:集群中部分節(jié)點同步完成即可彩倚,經(jīng)過一段時間筹我,最終達到全局的備份
  • push:由主節(jié)點將數(shù)據(jù)變更推送給從節(jié)點
  • pull:由從節(jié)點主動獲取差異數(shù)據(jù)

下面還是以具體服務來舉例: redis-cluster中,主從復制采用的是異步復制的方式帆离,master節(jié)點在做數(shù)據(jù)變更之后蔬蕊,會由一個異步線程將數(shù)據(jù)變更同步給slave節(jié)點,這是通過push的方式哥谷。當redis2.8之后岸夯,slave會周期的獲取最新的數(shù)據(jù),加入了pull方式们妥。無論是master還是slave猜扮,在進行數(shù)據(jù)同步時,不會阻塞正常的應用請求监婶。所以redis-cluster的主從復制旅赢,是異步備份+最終一致性的備份。

elasticsearch的主從復制可以手動設置同步備份或者異步備份压储,數(shù)據(jù)備份時不要求強一致性鲜漩,而是主分片(primary shard)會維護一份需要同步的(replica shard)分片列表,這個分片列表同步完成集惋,則認為數(shù)據(jù)備份完成孕似,需要注意的是,這里的主從復制不是節(jié)點的更新數(shù)據(jù)刮刑,而是分片的更新數(shù)據(jù)喉祭。

rocketmq的主從復制和elasticsearch類似,也可以分為同步備份和異步備份雷绢,不同的是rocketetmq的數(shù)據(jù)備份采用的是pull的方式泛烙,從節(jié)點會通過HAConnection鏈接主動向主節(jié)點發(fā)送待拉取數(shù)據(jù)偏移量,待主節(jié)點返回節(jié)點更新數(shù)據(jù)信息翘紊,更新從節(jié)點數(shù)據(jù)偏移量蔽氨,如此重復。

zookeeper的數(shù)據(jù)備份則是通過ZAB協(xié)議,通過消息廣播的方式同步數(shù)據(jù)到從節(jié)點鹉究。

讀寫分離

當數(shù)據(jù)備份后宇立,主從節(jié)點上就有了相同的數(shù)據(jù),為了提升服務的性能自赔,那么可以采用讀寫分離的方式妈嘹。主節(jié)點提供數(shù)據(jù)寫服務,從節(jié)點提供讀服務绍妨,可以有效的分擔主節(jié)點的服務器壓力润脸。可以進行數(shù)據(jù)分片的系統(tǒng)他去,如:redis毙驯、rocketmq、elasticsearch孤页,一般都可以配置一主多從尔苦、多主多從的集群架構。

主從切換

讀寫分離之后行施,主節(jié)點提供寫服務允坚,從節(jié)點只提供讀服務,因此若是主節(jié)點發(fā)生宕機蛾号,從節(jié)點依然可以提供讀服務稠项,但是服務無法更新數(shù)據(jù),這時候就要進行主從切換鲜结。早起展运,主從切換可以由人工手動完成,不過隨著技術發(fā)展精刷,主從切換已經(jīng)成為集群的必備功能拗胜。想要實現(xiàn)主從切換,必須要解決兩個問題:

  • 故障檢測
  • 故障轉移

故障檢測

解決這個問題怒允,需要額外再引入一個角色埂软,相當于是一個監(jiān)視者的角色,能夠長期的對主節(jié)點進行監(jiān)視纫事,若是只有一個監(jiān)視者勘畔,可能會發(fā)生誤判,所以還需要一套機制去保證當監(jiān)視者說主節(jié)點宕機丽惶,那么主節(jié)點是真的宕機炫七,否則集群會出現(xiàn)腦裂問題。

以redis為例钾唬,在redis的哨兵模式中万哪,這個監(jiān)視者的角色是一個個哨兵實例侠驯,而在redis-cluster架構中,這個監(jiān)視者的角色是redis實例自己壤圃。

在redis哨兵模式中陵霉,哨兵集群中的哨兵實例會定期和redis實例進行通信(ping),監(jiān)視redis實例的在線情況伍绳,若是其中一臺哨兵發(fā)現(xiàn)redis實例master故障,那么該哨兵會將該master狀態(tài)改為主觀下線乍桂,并通知其他哨兵冲杀,當哨兵集群中達到配置數(shù)量的哨兵實例認為該master都為主觀下線狀態(tài),這時會將master修改為客觀下線狀態(tài)睹酌,并開始觸發(fā)后續(xù)的故障轉移权谁。

在redis-cluster模式中,集群中的每一個節(jié)點都可以和其他節(jié)點通訊(ping)憋沿,當某一個節(jié)點A發(fā)現(xiàn)主節(jié)點B下線了旺芽,A會將該主節(jié)點B設為疑似下線狀態(tài)。集群中的節(jié)點會通過互發(fā)消息維護信息辐啄,當另一個節(jié)點C收到A的消息時采章,會將A對B節(jié)點的判斷記錄在C節(jié)點的維護信息下,這個信息可以理解為A說C疑似下線了壶辜。若是有其他節(jié)點發(fā)送C的狀態(tài)信息悯舟,A同樣也會記錄。當某一個節(jié)點如C發(fā)現(xiàn)記錄的B節(jié)點信息中砸民,超過半數(shù)的主節(jié)點都認為B下線了抵怎,那么C就會將B節(jié)點狀態(tài)修改為已下線狀態(tài),并廣播消息給集群的其他節(jié)點岭参,開始后續(xù)的故障轉移反惕。

上面就是redis的兩種分布式模式故障檢測的方案。大致可以歸結為演侯,監(jiān)視節(jié)點會和被監(jiān)視節(jié)點進行通訊姿染,感知被監(jiān)視節(jié)點的狀態(tài);監(jiān)視節(jié)點之間也會進行通訊蚌本,同步信息盔粹。為了防止集群出現(xiàn)腦裂,對于某個主節(jié)點的故障判斷會十分的謹慎程癌,需要達到一定數(shù)量的監(jiān)視節(jié)點都認為主節(jié)點故障時舷嗡,才會認為主節(jié)點真的故障,從而觸發(fā)故障轉移嵌莉。

在rocketmq集群模式中进萄,nameserver扮演著監(jiān)視者的角色(不同于其他系統(tǒng),nameserver并不負責集群的主從切換,rocketmq 4.5之前不支持自動主從切換中鼠,4.5之后可婶,通過dledger實現(xiàn)自動的故障轉移)。在elasticsearch集群中援雇,elasticsearch實例本身在扮演監(jiān)視者角色矛渴。zookeeper也是實例本身扮演監(jiān)視者的角色。

故障轉移

故障轉移就是當集群發(fā)現(xiàn)集群中的主節(jié)點/從節(jié)點發(fā)生故障之后的處理惫搏,從節(jié)點比較簡單具温,直接將從節(jié)點下線即可,主節(jié)點的故障轉移流程比較復雜筐赔,各個系統(tǒng)根據(jù)系統(tǒng)的功能和架構有不同的實現(xiàn)方式铣猩,共同點是選舉出的主節(jié)點一定是集群中數(shù)據(jù)最新的最完善的節(jié)點。

  • 最簡單的故障轉移方式:人工切換(當發(fā)現(xiàn)集群發(fā)生故障之后茴丰,人工處理达皿,rocketmq4.5之前就是采用此辦法)
  • 基于Raft算法的領頭選舉:redis的哨兵模式和redis-cluster在故障轉移時,都采用了raft算法贿肩。關于raft算法具體我也不做描述峦椰,網(wǎng)上有很多解釋,大致說一下redis中這兩個選舉用法的區(qū)別:
  • 在哨兵模式中尸曼,選舉算法選出的并不是master節(jié)點们何,而是在哨兵節(jié)點中選舉出一個負責將從節(jié)點提升為主節(jié)點,并維護其他從節(jié)點和主節(jié)點關系的哨兵領頭控轿,哨兵leader根據(jù)一定規(guī)則選出一個數(shù)據(jù)是集群中最新的從節(jié)點成為主節(jié)點冤竹。這里進行選舉時,集群中所有正常工作的哨兵都有機會成為哨兵的leader茬射。
  • 在redis-cluster模式中鹦蠕,選舉算法直接選舉從節(jié)點成為主節(jié)點。在這里進行選舉時在抛,能夠進行投票的是集群中的各個主節(jié)點钟病。能夠參與選舉的從節(jié)點必須滿足一定的條件,以保證從節(jié)點數(shù)據(jù)是最新的數(shù)據(jù)刚梭。

選舉過程大致如下:

首先選舉成功的條件時集群中具有投票權限的超過半數(shù)的節(jié)點投票一致肠阱,通過某一個節(jié)點成為主節(jié)點。

開始一輪選舉時朴读,定義為一個紀元屹徘,用一個自增的id表示。

候選節(jié)點將帶著紀元id衅金,以及自身信息作為投票申請廣播給集群給可投票的節(jié)點噪伊。

具有投票權限的節(jié)點投票只要滿足兩個條件:1.自身在最新紀元沒有給投過票 2.節(jié)點發(fā)送過來的投票申請時最新紀元的(如何判斷時最新紀元簿煌,則是判斷一下節(jié)點之前通過申請的紀元id是否小于當前申請的紀元id)。

半數(shù)以上的投票節(jié)點通過某一個候選節(jié)點成為leader節(jié)點鉴吹,則leader產(chǎn)生姨伟。

若是一個紀元沒有產(chǎn)生主節(jié)點,則候選節(jié)點進入隨機的休眠豆励,并且開啟下一個紀元夺荒,知道產(chǎn)生leader節(jié)點。

  • ZAB協(xié)議的選舉——崩潰恢復模式肆糕。ZAB即zookeeper原子廣播協(xié)議般堆,是為zookeeper的分布式數(shù)據(jù)一致性和協(xié)調而設計的協(xié)議,它有兩種模式:保證主節(jié)點和從節(jié)點數(shù)據(jù)一致性的消息廣播模式诚啃,選舉產(chǎn)生leader節(jié)點的崩潰恢復模式。

在zk集群經(jīng)過崩潰恢復模式之后私沮,需要保證:1.已經(jīng)提交的事務不能丟失 2.未被提交的事務不能出現(xiàn)始赎。如何保證以上兩點,zk服務集群中維護了zxid仔燕,zxid也可以看作是一個自增的id造垛,集群中每產(chǎn)生一個新事物,zxid就會增加晰搀。zxid有64位五辽,前32位維護了集群主節(jié)點變更情況,每重新選舉出一個新的主節(jié)點則增加外恕,后32位維護在新的主節(jié)點集群下事務的id杆逗,產(chǎn)生一個新事物則增加。

ZAB的選舉模式有很多種鳞疲,我主要了解了默認罪郊,也是推薦的FastLeaderElection模式,在這個模式下尚洽,我會以集群中一臺參與選舉的服務器的視角來模擬選主的過程悔橄;

我是一臺zk服務器,我現(xiàn)在很慌腺毫,因為我的leader服務器不見了癣疟,作為一個有夢想的follower,我也要參加leader的選舉潮酒,為了這次選舉我要準備:myid(在集群中標識是這臺服務器的id)睛挚,zxid(本臺服務器保存的最新事務id),logicClock(本臺服務器發(fā)起的第幾輪投票)

首先我會自己選自己澈灼,這得自信竞川。于是我將自身的選舉信息[myid, zxid]放到自己的收票箱店溢,然后將我的選舉信息還有我的選舉輪次logicClock廣播給其他服務器進行PK

作為一個有原則的服務器,我們的選舉也是有原則的委乌,當我收到別人的選舉信息時床牧,我也會將他和我自己的選舉信息進行PK,PK的原則如下:

  • 比較logicClock遭贸,比我信箱保存的logicClock大戈咳,說明我信箱里的已經(jīng)過期了,得用接收到的代替
  • 若是同一個選舉周期壕吹,logicClick相同著蛙,再比較zxid,zxid比我信箱大耳贬,說明數(shù)據(jù)比我信息里的服務器保存的數(shù)據(jù)更新踏堡,得用接收的代替
  • 若是zxid一樣,比較myid咒劲,若是myid比我信箱里的大顷蟆,說明資歷更老,得用接收的代替

經(jīng)過這一系列的PK腐魂,終于選出了我心中的leader服務器帐偎,要廣播給其他服務器。

超過半數(shù)的服務器都同意某一臺服務器成為leader蛔屹,選舉結束了削樊。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兔毒,隨后出現(xiàn)的幾起案子漫贞,更是在濱河造成了極大的恐慌,老刑警劉巖眼刃,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绕辖,死亡現(xiàn)場離奇詭異,居然都是意外死亡擂红,警方通過查閱死者的電腦和手機仪际,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昵骤,“玉大人树碱,你說我怎么就攤上這事”淝兀” “怎么了成榜?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹦玫。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么摄欲? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮纬凤,結果婚禮上,老公的妹妹穿的比我還像新娘撩嚼。我一直安慰自己停士,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布完丽。 她就那樣靜靜地躺著恋技,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逻族。 梳的紋絲不亂的頭發(fā)上蜻底,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音聘鳞,去河邊找鬼朱躺。 笑死,一個胖子當著我的面吹牛搁痛,可吹牛的內容都是我干的。 我是一名探鬼主播宇弛,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鸡典,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了枪芒?” 一聲冷哼從身側響起彻况,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舅踪,沒想到半個月后纽甘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡抽碌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年悍赢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片货徙。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡左权,死狀恐怖,靈堂內的尸體忽然破棺而出痴颊,到底是詐尸還是另有隱情赏迟,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布蠢棱,位于F島的核電站锌杀,受9級特大地震影響甩栈,放射性物質發(fā)生泄漏。R本人自食惡果不足惜糕再,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一量没、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亿鲜,春花似錦允蜈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垒探,卻和暖如春妓蛮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背圾叼。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工蛤克, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夷蚊。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓构挤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惕鼓。 傳聞我的和親對象是個殘疾皇子筋现,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容