MySQL - InnoDB Buffer Pool

簡(jiǎn)介

MySQL InnoDB 緩沖池,里面緩存著大量數(shù)據(jù)(數(shù)據(jù)頁),使 CPU 讀取或?qū)懭霐?shù)據(jù)時(shí)坡锡,MySQL 不會(huì)直接去修改磁盤的數(shù)據(jù),因?yàn)檫@樣做太慢了窒所,MySQL 會(huì)先改內(nèi)存鹉勒,然后記錄 redo log,等有空了再刷磁盤吵取,如果內(nèi)存里沒有數(shù)據(jù)禽额,就去磁盤 load,從而解決了因?yàn)榇疟P性能慢導(dǎo)致的數(shù)據(jù)庫(kù)性能差的問題皮官。而這些數(shù)據(jù)存放的地方脯倒,就是 Buffer Pool。

功能

buffer pool 最主要的功能便是加速讀和加速寫捺氢。

  • 加速讀:當(dāng)需要訪問一個(gè)數(shù)據(jù)頁的時(shí)候藻丢,如果這個(gè)頁已經(jīng)在緩存池中,那么就不再需要訪問磁盤摄乒,直接從緩沖池中就能獲取這個(gè)頁面的內(nèi)容悠反。

  • 加速寫:當(dāng)需要修改一個(gè)數(shù)據(jù)頁的時(shí)候板甘,先將這個(gè)頁在緩沖池中進(jìn)行修改撇吞,記下相關(guān)的 redo log,這個(gè)頁的修改就算已經(jīng)完成了老客。至于這個(gè)被修改的頁什么時(shí)候真正刷新到磁盤拭荤,這個(gè)是 buffer pool 后臺(tái)刷新線程來完成的茵臭。

內(nèi)存淘汰

因?yàn)闄C(jī)器的內(nèi)存大小是有限的。當(dāng)數(shù)據(jù)庫(kù)的數(shù)據(jù)量比較大的時(shí)候舅世,緩存池并不能緩存所有的數(shù)據(jù)頁笼恰,所以也就可能會(huì)出現(xiàn),當(dāng)需要訪問的某個(gè)頁時(shí)歇终,該頁卻不在緩存池中的情況,這個(gè)時(shí)候就需要從磁盤中將這個(gè)頁讀出來逼龟,加載到緩存池评凝,然后再去訪問。這樣就涉及到隨機(jī)的物理 IO腺律,也就增加了操作頁所消耗的時(shí)間奕短。

這樣的情況是一個(gè) bad case宜肉,是需要盡量避免的——因此需要想辦法來提高緩存的命中率。

innodb buffer pool 采用經(jīng)典的 LRU 算法來進(jìn)行頁面淘汰翎碑,以提高緩存命中率谬返。

與傳統(tǒng)的 LRU 算法相比,buffer pool 中的 LRU 列表其中間位置被打了一個(gè) old 標(biāo)識(shí)日杈,可以簡(jiǎn)單的理解為將 LRU 列表分為兩個(gè)部分遣铝,這個(gè)標(biāo)記到 LRU 列表頭部的數(shù)據(jù)頁稱為 young 數(shù)據(jù)頁池,這個(gè)標(biāo)志到 LRU 列表尾部的數(shù)據(jù)頁稱之為 old 數(shù)據(jù)頁池莉擒。

當(dāng)一個(gè)頁從磁盤上加載到緩存池的時(shí)候酿炸,會(huì)將它放在 old 標(biāo)識(shí)之后的第一個(gè)位置,也就是說放在了 old 池子中(“中點(diǎn)插入策略”)涨冀。這個(gè)機(jī)制保證了在做大表的一次性全表掃描時(shí)填硕,即使有大量新進(jìn)來的數(shù)據(jù)頁,也會(huì)被存放在 old 池中鹿鳖,當(dāng) old 池的大小不夠緩存新進(jìn)來頁面的時(shí)候扁眯,也只是在 old 池子中進(jìn)行循環(huán)沖洗,這樣就不會(huì)沖洗 young 池子中的熱點(diǎn)頁翅帜,從而保護(hù)了熱點(diǎn)頁姻檀。這就是 buffer pool LRU 算法的簡(jiǎn)單機(jī)制。

Buffer Pool Instance 和 Buffer Pool幾個(gè)鏈表

Buffer Pool Instance

Buffer Pool 實(shí)例藕甩,大小等于

innodb_buffer_pool_size / innodb_buffer_pool_instances

innodb_buffer_pool_instances 的大小可配置施敢。

每個(gè) Buffer Pool Instance 都有自己的鎖,信號(hào)量狭莱,物理塊僵娃,各個(gè) instance 之間沒有競(jìng)爭(zhēng)關(guān)系,可以并發(fā)讀取與寫入腋妙。如果 innodb_buffer_pool_size 大小小于 1G默怨,將只有一個(gè) instance。

Buffer Pool Chunk

Buffer Pool Instance 由若干個(gè) chunk 組成骤素,一個(gè) chunk 就是一片連續(xù)的空間匙睹,每個(gè) chunk 的大小默認(rèn)為 128MB,最小為 1MB济竹,且這個(gè)值在 8.0 中是可以動(dòng)態(tài)調(diào)整生效的痕檬。Buffer Chunk 是最底層的物理塊,在啟動(dòng)階段由操作系統(tǒng)申請(qǐng)送浊,直到數(shù)據(jù)庫(kù)關(guān)閉才釋放梦谜。Buffer chunk 主要存儲(chǔ)數(shù)據(jù)頁和數(shù)據(jù)頁控制體。如下圖:


設(shè)計(jì)數(shù)據(jù)頁控制體的主要目的是為了方便管理數(shù)據(jù)頁,控制體中有指針指向數(shù)據(jù)頁唁桩。InnoDB 為每一個(gè)數(shù)據(jù)頁都創(chuàng)建了一些所謂的控制信息闭树,數(shù)據(jù)頁控制體和數(shù)據(jù)頁是一一對(duì)應(yīng)的。這些控制信息包括該頁所屬的表空間編號(hào)荒澡、頁號(hào)报辱、頁在 Buffer Pool 中的地址等。每個(gè)數(shù)據(jù)頁對(duì)應(yīng)的控制信息占用的內(nèi)存大小是相同的单山。

Free List

當(dāng)最初啟動(dòng) MySQL 服務(wù)器的時(shí)候碍现,需要完成對(duì) Buffer Pool 的初始化(分配 Buffer Pool 的內(nèi)存空間),把它劃分成若干對(duì)控制塊和緩存頁饥侵。此時(shí)并沒有真實(shí)的磁盤頁被緩存到 Buffer Pool 中(因?yàn)檫€沒有用到)鸵赫,之后隨著程序的運(yùn)行,會(huì)不斷的有磁盤上的頁被緩存到 Buffer Pool 中躏升。
因?yàn)閯倓偼瓿沙跏蓟?Buffer Pool 中所有的數(shù)據(jù)頁都是空閑的辩棒,所以每一個(gè)數(shù)據(jù)頁都會(huì)被加入到 Free List 中,假設(shè)該 Buffer Pool 中可容納的數(shù)據(jù)頁數(shù)量為 n膨疏,那增加了 Free List 的效果圖就是這樣的:

如果需要從數(shù)據(jù)庫(kù)中分配新的數(shù)據(jù)頁一睁,直接從上獲取即可。InnoDB 需要保證 Free List 有足夠的節(jié)點(diǎn)佃却,提供給用戶使用者吁,否則需要從 FLU List 或者 LRU List 淘汰一定的節(jié)點(diǎn)。

Lru List

既然 buffer pool 的目的是加速寫和加速讀饲帅,因此必須想辦法提高內(nèi)存數(shù)據(jù)頁的緩存命中率复凳。InnoDB 基于經(jīng)典的 LRU 算法管理 buffer pool 中的數(shù)據(jù)頁。一般情況下 list 頭部存放的是熱數(shù)據(jù)灶泵,就是所謂的 young page(最近經(jīng)常訪問的數(shù)據(jù))育八,list 尾部存放的就是 old page(最近不被訪問的數(shù)據(jù)),
入緩沖池的頁赦邻,優(yōu)先進(jìn)入老生代髓棋,頁被訪問,才進(jìn)入新生代惶洲,以解決預(yù)讀失效的問題按声。

Lru 有以下算法:

  • 3/8 的 list 信息是作為 old list,這些信息是被驅(qū)逐的對(duì)象恬吕;
  • list 的中點(diǎn)就是我們所謂的 old list 頭部和 young list 尾部的連接點(diǎn)签则,相當(dāng)于一個(gè)界限;
  • 新數(shù)據(jù)首先會(huì)插入到 old list 的頭部铐料;
  • 如果是 old list 的數(shù)據(jù)被訪問到了怀愧,且在老生代停留時(shí)間超過配置閾值的(默認(rèn)是1000ms)侨颈,這個(gè)頁信息才會(huì)被移動(dòng)到 young list 的頭部變成 young page,以解決批量數(shù)據(jù)訪問芯义,大量熱數(shù)據(jù)淘汰的問題;
  • 在 InnoDB buffer pool 里面妻柒,不管是 young list 還是 old list 的數(shù)據(jù)扛拨,如果不會(huì)被訪問到,最后都會(huì)被移動(dòng)到 list 的尾部被淘汰举塔。

為了進(jìn)一步提高讀寫性能绑警,避免掃描 Lru List,實(shí)際上每個(gè) Buffer Pool Instance 都有一個(gè) page hash央渣,通過它计盒,使用 space_id 和 page_no 就能快速找到已經(jīng)被讀入內(nèi)存的數(shù)據(jù)頁,而不用線性遍歷 LRU List 去查找芽丹。關(guān)于 page hash 的數(shù)據(jù)結(jié)構(gòu)見總結(jié)模塊中 InnoDB Buffer Pool 的架構(gòu)圖北启。

Flush List

在了解 Flush List 之前,首先需要了解臟頁的概念拔第。

臟頁:內(nèi)存數(shù)據(jù)頁和磁盤數(shù)據(jù)頁內(nèi)容不一致的時(shí)候咕村,這個(gè)數(shù)據(jù)頁被稱為“臟頁”。內(nèi)存數(shù)據(jù)寫入磁盤后蚊俺,內(nèi)存和磁盤的數(shù)據(jù)頁內(nèi)容就一致了懈涛,稱為“干凈頁”。不論臟頁還是干凈頁泳猬,都存在內(nèi)存里批钠。

臟頁最終肯定需要被刷回磁盤而變成干凈頁,但如果每次產(chǎn)生臟頁后就立即同步到磁盤勢(shì)必將嚴(yán)重影響程序的性能(畢竟磁盤慢的像烏龜一樣)得封。所以每次修改緩存頁后埋心,我們并不著急立即把修改同步到磁盤上,而是在未來的某個(gè)時(shí)間點(diǎn)進(jìn)行同步呛每,由后臺(tái)刷新線程依次刷新到磁盤踩窖,實(shí)現(xiàn)修改落地到磁盤。

由于不是立即同步刷新臟頁晨横,所以我們不得不再創(chuàng)建一個(gè)鏈表洋腮,將臟頁保存起來。凡是在 LRU List 中被修改過的頁都需要加入這個(gè)鏈表中手形,這個(gè)鏈表中的所有節(jié)點(diǎn)都是臟頁啥供,所以也叫 Flush List,一般被簡(jiǎn)寫為 FLU List库糠。

這里的臟頁修改指的此頁被加載進(jìn) Buffer Pool 后第一次被修改伙狐,只有第一次被修改時(shí)才需要加入 FLU List(代碼中是根據(jù) page 頭部的 oldest_modification == 0 來判斷是否是第一次修改)涮毫,如果這個(gè)頁被再次修改就不會(huì)再放到 FLU List 了,因?yàn)橐呀?jīng)存在贷屎。需要注意的是罢防,臟頁數(shù)據(jù)實(shí)際還在 LRU List 中,而 FLU List 中的臟頁記錄只是通過指針指向 LRU List 中的臟頁(即在 FLU List 上的頁一定在 LRU List 上唉侄,反之不成立)咒吐。

一個(gè)數(shù)據(jù)頁可能會(huì)在不同的時(shí)刻被修改多次,在數(shù)據(jù)頁上記錄了最早一次也就是第一次修改的 LSN属划,即 oldest_modification恬叹。不同數(shù)據(jù)頁有不同的 oldest_modification,F(xiàn)LU List 中的節(jié)點(diǎn)按照 oldest_modification 排序同眯,鏈表尾是最小的绽昼,也就是最早被修改的數(shù)據(jù)頁。當(dāng)需要從 FLU List 中淘汰頁的時(shí)候须蜗,從鏈表尾部開始淘汰硅确。加入 FLU List,需要使用 flush_list_mutex 保護(hù)唠粥,所以能保證 FLU List 中節(jié)點(diǎn)的順序疏魏。

雖然臟頁既存在于 LRU List 中,也存在與 FLU List 中晤愧,但 LRU List 用來管理緩沖池中頁的可用性大莫,F(xiàn)LU List 用來管理將臟頁刷新回磁盤,二者互不影響官份。

Buffer Pool預(yù)熱

在 MySQL 重啟后只厘,由于 Buffer Pool 里面沒有什么數(shù)據(jù),因此這個(gè)時(shí)候業(yè)務(wù)上對(duì)數(shù)據(jù)庫(kù)的操作舅巷,MySQL 就只能從磁盤中讀取數(shù)據(jù)到內(nèi)存羔味,而這個(gè)過程可能需要很久才能恢復(fù)到 MySQL 重啟前內(nèi)存中保留的業(yè)務(wù)頻繁使用的熱數(shù)據(jù)。Buffer Pool 從無到重新緩存業(yè)務(wù)頻繁使用熱數(shù)據(jù)的過程稱之為預(yù)熱钠右。在預(yù)熱這個(gè)過程中赋元,MySQL 數(shù)據(jù)庫(kù)的性能不會(huì)特別好,并且 Buffer Pool 越大飒房,預(yù)熱過程越長(zhǎng)搁凸。

為了減短這個(gè)預(yù)熱過程,在 MySQL 關(guān)閉前狠毯,把 Buffer Pool 中的頁信息保存到磁盤护糖,等到 MySQL 啟動(dòng)時(shí),再根據(jù)之前保存的信息把磁盤中的數(shù)據(jù)加載到 Buffer Pool 即可嚼松。

總結(jié)

這三個(gè)重要鏈表(Free List, LRU List, FLU List)的關(guān)系可以用下圖表示:


Free List 跟 LRU List 的關(guān)系是相互流通的嫡良,頁在這兩個(gè)鏈表間來回置換锰扶。而 FLUSH List 中記錄了臟頁數(shù)據(jù),即通過指針指向了 LRU List寝受,所以圖中 FLU List 被 LRU List 包裹坷牛。
三個(gè)鏈表的元素都是控制塊指針,實(shí)際指向內(nèi)存page很澄。

數(shù)據(jù)頁訪問機(jī)制

下面梳理一下數(shù)據(jù)頁的訪問流程漓帅。

當(dāng)訪問的頁在緩存池中命中,則直接從緩沖池中訪問該頁痴怨。如果沒有命中,則需要將這個(gè) page 從磁盤上加載到緩存池器予,因此需要在 Free List 中找一個(gè)空閑的內(nèi)存頁來緩存這個(gè)從磁盤讀入的 page浪藻。

但存在空閑內(nèi)存頁被使用完的情況,不保證一定有空閑的內(nèi)存頁乾翔。假如 Free List 為空爱葵,則需要想辦法盡快產(chǎn)生空閑的內(nèi)存頁。

首先去 LRU List 中找可以替換的內(nèi)存頁(干凈頁)反浓,查找方向是從鏈表的尾部開始找萌丈,只要找到可以替換的頁,就將其從 LRU List 中移除雷则,加入空閑列表辆雾,然后再去空閑列表中找空閑的內(nèi)存頁。第一次查找最多只掃描 100 個(gè)頁月劈,循環(huán)進(jìn)行到第二次時(shí)度迂,查找深度就是整個(gè) LRU List。

如果在 LRU List 中沒有找到可以替換的頁猜揪,則進(jìn)行單頁刷新(從 FLU List 中炔涯埂),將臟頁刷新到磁盤之后而姐,再將其加入到空閑列表腊凶。這便是 InnoDB 中的 LRU 頁面淘汰機(jī)制。為什么只做單頁刷新呢拴念?因?yàn)樗哪康氖菫榱吮M快獲取空閑內(nèi)存頁钧萍,進(jìn)行臟頁刷新是不得已而為之,所以只會(huì)進(jìn)行一個(gè)頁的刷新丈莺。

Free List 是一個(gè)公共的鏈表划煮,所有的用戶線程都可以使用,存在爭(zhēng)用的情況缔俄。因此自己產(chǎn)生的空閑內(nèi)存頁有可能會(huì)剛好被其它線程所使用弛秋,用戶線程可能會(huì)重復(fù)執(zhí)行上面的查找流程器躏,直到找到空閑的內(nèi)存頁為止。

在執(zhí)行一條 SQL 語句的時(shí)候蟹略,如果恰好需要進(jìn)行單頁刷臟登失,這條 SQL 語句的執(zhí)行便會(huì)比預(yù)期更加耗時(shí),有時(shí)候看起來就像是數(shù)據(jù)庫(kù)“抖了一下”挖炬,這也是一個(gè) bad case揽浙,需要盡量避免。

通過數(shù)據(jù)頁訪問機(jī)制意敛,可以知道當(dāng)無空閑頁時(shí)產(chǎn)生空閑頁就成為了一個(gè)必須要做的事情馅巷。如果需要通過刷新臟頁來產(chǎn)生空閑頁,查找空閑頁的時(shí)間就會(huì)延長(zhǎng)草姻。因此钓猬,innodb buffer pool 中存在大量可以替換的頁,或者 Free List 中一直存在著空閑內(nèi)存頁撩独,對(duì)快速獲取空閑內(nèi)存頁就起到了決定性的作用敞曹。

重要參數(shù)配置

參數(shù):innodb_buffer_pool_size
介紹:配置緩沖池的大小,在內(nèi)存允許的情況下综膀,DBA往往會(huì)建議調(diào)大這個(gè)參數(shù)澳迫,越多數(shù)據(jù)和索引放到內(nèi)存里,數(shù)據(jù)庫(kù)的性能會(huì)越好剧劝。

參數(shù):innodb_old_blocks_pct
介紹:老生代占整個(gè)LRU鏈長(zhǎng)度的比例橄登,默認(rèn)是37,即整個(gè)LRU中新生代與老生代長(zhǎng)度比例是63:37担平。
畫外音:如果把這個(gè)參數(shù)設(shè)為100示绊,就退化為普通LRU了。

參數(shù):innodb_old_blocks_time
介紹:老生代停留時(shí)間窗口暂论,單位是毫秒面褐,默認(rèn)是1000,即同時(shí)滿足“被訪問”與“在老生代停留時(shí)間超過1秒”兩個(gè)條件取胎,才會(huì)被插入到新生代頭部展哭。

針對(duì)數(shù)據(jù)寫的優(yōu)化 - change buffer寫緩沖

當(dāng)需要更新一個(gè)數(shù)據(jù)頁時(shí),如果數(shù)據(jù)頁在內(nèi)存中就直接更新闻蛀。
而如果這個(gè)數(shù)據(jù)頁還沒有在內(nèi)存中的話匪傍,在不影響數(shù)據(jù)一致性的前提下,InnoDB 會(huì)將這些更新操作緩存在 change buffer 中觉痛,這樣就不需要從磁盤中讀入這個(gè)數(shù)據(jù)頁了役衡,減少一次IO。在下次查詢需要訪問這個(gè)數(shù)據(jù)頁的時(shí)候薪棒,將數(shù)據(jù)頁讀入內(nèi)存手蝎,然后執(zhí)行 change buffer 中與這個(gè)頁有關(guān)的操作榕莺,例如將數(shù)據(jù)合并(merge)恢復(fù)到緩沖池中。
寫緩沖的目的是降低寫操作的磁盤IO棵介,提升數(shù)據(jù)庫(kù)性能钉鸯。

加入寫緩沖優(yōu)化后,修改不在內(nèi)存中的數(shù)據(jù)頁流程優(yōu)化為:

  1. 在寫緩沖中記錄這個(gè)操作邮辽,一次內(nèi)存操作唠雕;
  2. 寫入redo log,一次磁盤順序?qū)懖僮鳌?br> 其性能與這個(gè)索引頁在緩沖池中吨述,相近岩睁。
為什么寫緩沖優(yōu)化,僅適用于非唯一普通索引頁

對(duì)于唯一索引來說揣云,所有的更新操作都要先判斷這個(gè)操作是否違反唯一性約束笙僚,InnoDB必須進(jìn)行唯一性檢查。也就是說灵再,索引頁即使不在緩沖池,磁盤上的頁讀取無法避免亿笤,否則怎么校驗(yàn)是否唯一翎迁,此時(shí)就應(yīng)該直接把相應(yīng)的頁放入緩沖池再進(jìn)行修改,而不應(yīng)該再整寫緩沖净薛。 當(dāng)數(shù)據(jù)不在內(nèi)存頁汪榔,就至少會(huì)產(chǎn)生一次IO。

除了數(shù)據(jù)頁被訪問肃拜,還有哪些場(chǎng)景會(huì)觸發(fā)刷寫緩沖中的數(shù)據(jù)呢.
還有這么幾種情況痴腌,會(huì)刷寫緩沖中的數(shù)據(jù):

  • 有一個(gè)后臺(tái)線程,會(huì)認(rèn)為數(shù)據(jù)庫(kù)空閑時(shí)燃领;
  • 數(shù)據(jù)庫(kù)緩沖池不夠用時(shí)士聪;
  • 數(shù)據(jù)庫(kù)正常關(guān)閉時(shí);
  • redo log寫滿時(shí)猛蔽;

幾乎不會(huì)出現(xiàn)redo log寫滿剥悟,此時(shí)整個(gè)數(shù)據(jù)庫(kù)處于無法寫入的不可用狀態(tài)。

什么業(yè)務(wù)場(chǎng)景曼库,適合開啟InnoDB的寫緩沖機(jī)制区岗?

先說什么時(shí)候不適合,如上文分析毁枯,當(dāng):

  • 數(shù)據(jù)庫(kù)都是唯一索引慈缔;
  • 或者,寫入一個(gè)數(shù)據(jù)后种玛,會(huì)立刻讀取它藐鹤;

這兩類場(chǎng)景瓤檐,在寫操作進(jìn)行時(shí)(進(jìn)行后),本來就要進(jìn)行進(jìn)行頁讀取教藻,本來相應(yīng)頁面就要入緩沖池距帅,此時(shí)寫緩存反倒成了負(fù)擔(dān),增加了復(fù)雜度括堤。

什么時(shí)候適合使用寫緩沖碌秸,如果:

  1. 數(shù)據(jù)庫(kù)大部分是非唯一索引;
  2. 業(yè)務(wù)是寫多讀少悄窃,或者不是寫后立刻讀燃サ纭;

可以使用寫緩沖轧抗,將原本每次寫入都需要進(jìn)行磁盤IO的SQL恩敌,優(yōu)化定期批量寫磁盤。
例如横媚,賬單流水業(yè)務(wù)纠炮。

重要參數(shù)設(shè)置

參數(shù):innodb_change_buffer_max_size
介紹:配置寫緩沖的大小,占整個(gè)緩沖池的比例灯蝴,默認(rèn)值是25%恢口,最大值是50%。
寫多讀少的業(yè)務(wù)穷躁,才需要調(diào)大這個(gè)值耕肩,讀多寫少的業(yè)務(wù),25%其實(shí)也多了问潭。

參數(shù):innodb_change_buffering
介紹:配置哪些寫操作啟用寫緩沖猿诸,可以設(shè)置成all/none/inserts/deletes等。

轉(zhuǎn)載自

https://juejin.cn/post/6845166890470342670

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狡忙,一起剝皮案震驚了整個(gè)濱河市梳虽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灾茁,老刑警劉巖怖辆,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異删顶,居然都是意外死亡竖螃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門逗余,熙熙樓的掌柜王于貴愁眉苦臉地迎上來特咆,“玉大人,你說我怎么就攤上這事∧甯瘢” “怎么了画拾?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)菜职。 經(jīng)常有香客問我青抛,道長(zhǎng),這世上最難降的妖魔是什么酬核? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任蜜另,我火速辦了婚禮,結(jié)果婚禮上嫡意,老公的妹妹穿的比我還像新娘举瑰。我一直安慰自己,他們只是感情好蔬螟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布此迅。 她就那樣靜靜地躺著,像睡著了一般旧巾。 火紅的嫁衣襯著肌膚如雪耸序。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天鲁猩,我揣著相機(jī)與錄音佑吝,去河邊找鬼。 笑死绳匀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炸客。 我是一名探鬼主播疾棵,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼痹仙!你這毒婦竟也來了是尔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤开仰,失蹤者是張志新(化名)和其女友劉穎拟枚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體众弓,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恩溅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谓娃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脚乡。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滨达,靈堂內(nèi)的尸體忽然破棺而出奶稠,到底是詐尸還是另有隱情俯艰,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布锌订,位于F島的核電站竹握,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏辆飘。R本人自食惡果不足惜啦辐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望劈猪。 院中可真熱鬧昧甘,春花似錦、人聲如沸战得。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽常侦。三九已至浇冰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間聋亡,已是汗流浹背肘习。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坡倔,地道東北人漂佩。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像罪塔,于是被迫代替她去往敵國(guó)和親投蝉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

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