實(shí)戰(zhàn)18種接口優(yōu)化方案的總結(jié)

之前工作中枚驻,遇到一個(gè)504超時(shí)問題。原因是因?yàn)榻涌诤臅r(shí)過長纫谅,超過nginx配置的10秒炫贤。然后 真槍實(shí)彈搞了一次接口性能優(yōu)化,最后接口從11.3s降為170ms付秕。本文將跟小伙伴們分享接口優(yōu)化的一些通用方案兰珍。

image.png

1. 批量思想:批量操作數(shù)據(jù)庫

優(yōu)化前:

//for循環(huán)單筆入庫
for(TransDetail detail:transDetailList){
  insert(detail);  
}

優(yōu)化后:

batchInsert(transDetailList);

打個(gè)比喻:

打個(gè)比喻:假如你需要搬一萬塊磚到樓頂,你有一個(gè)電梯,電梯一次可以放適量的磚(最多放500), 你可以選擇一次運(yùn)送一塊磚,也可以一次運(yùn)送500,你覺得哪種方式更方便,時(shí)間消耗更少?

2. 異步思想:耗時(shí)操作询吴,考慮放到異步執(zhí)行

耗時(shí)操作掠河,考慮用異步處理,這樣可以降低接口耗時(shí)猛计。

假設(shè)一個(gè)轉(zhuǎn)賬接口唠摹,匹配聯(lián)行號(hào),是同步執(zhí)行的奉瘤,但是它的操作耗時(shí)有點(diǎn)長勾拉,優(yōu)化前的流程:

image.png

為了降低接口耗時(shí),更快返回盗温,你可以把匹配聯(lián)行號(hào)移到異步處理藕赞,優(yōu)化后:

image.png
  • 除了轉(zhuǎn)賬這個(gè)例子,日常工作中還有很多這種例子卖局。比如:用戶注冊(cè)成功后斧蜕,短信郵件通知,也是可以異步處理的~
  • 至于異步的實(shí)現(xiàn)方式砚偶,你可以用線程池批销,也可以用消息隊(duì)列實(shí)現(xiàn)

3. 空間換時(shí)間思想:恰當(dāng)使用緩存蟹演。

在適當(dāng)?shù)臉I(yè)務(wù)場景风钻,恰當(dāng)?shù)厥褂镁彺妫强梢源蟠筇岣呓涌谛阅艿木魄搿>彺嫫鋵?shí)就是一種空間換時(shí)間的思想骡技,就是你把要查的數(shù)據(jù),提前放好到緩存里面,需要時(shí)布朦,直接查緩存囤萤,而避免去查數(shù)據(jù)庫或者計(jì)算的過程

這里的緩存包括:Redis緩存是趴,JVM本地緩存涛舍,memcached,或者Map等等唆途。我舉個(gè)我工作中富雅,一次使用緩存優(yōu)化的設(shè)計(jì)吧,比較簡單肛搬,但是思路很有借鑒的意義没佑。

那是一次轉(zhuǎn)賬接口的優(yōu)化,老代碼温赔,每次轉(zhuǎn)賬蛤奢,都會(huì)根據(jù)客戶賬號(hào),查詢數(shù)據(jù)庫陶贼,計(jì)算匹配聯(lián)行號(hào)啤贩。

image.png

因?yàn)槊看?strong>都查數(shù)據(jù)庫,都計(jì)算匹配拜秧,比較耗時(shí)痹屹,所以使用緩存,優(yōu)化后流程如下:

image.png

4. 預(yù)取思想:提前初始化到緩存

預(yù)取思想很容易理解腹纳,就是提前把要計(jì)算查詢的數(shù)據(jù)痢掠,初始化到緩存。如果你在未來某個(gè)時(shí)間需要用到某個(gè)經(jīng)過復(fù)雜計(jì)算的數(shù)據(jù)嘲恍,才實(shí)時(shí)去計(jì)算的話,可能耗時(shí)比較大雄驹。這時(shí)候佃牛,我們可以采取預(yù)取思想,提前把將來可能需要的數(shù)據(jù)計(jì)算好医舆,放到緩存中俘侠,等需要的時(shí)候,去緩存取就行蔬将。這將大幅度提高接口性能爷速。

我記得以前在第一個(gè)公司做視頻直播的時(shí)候,看到我們的直播列表就是用到這種優(yōu)化方案霞怀。就是啟動(dòng)個(gè)任務(wù)惫东,提前把直播用戶、積分等相關(guān)信息,初始化到緩存廉沮。

5. 池化思想:預(yù)分配與循環(huán)使用

大家應(yīng)該都記得颓遏,我們?yōu)槭裁葱枰褂镁€程池

線程池可以幫我們管理線程滞时,避免增加創(chuàng)建線程和銷毀線程的資源損耗叁幢。

如果你每次需要用到線程,都去創(chuàng)建坪稽,就會(huì)有增加一定的耗時(shí)曼玩,而線程池可以重復(fù)利用線程,避免不必要的耗時(shí)窒百。 池化技術(shù)不僅僅指線程池黍判,很多場景都有池化思想的體現(xiàn),它的本質(zhì)就是預(yù)分配與循環(huán)使用贝咙。

比如TCP三次握手样悟,大家都很熟悉吧,它為了減少性能損耗庭猩,引入了Keep-Alive長連接窟她,避免頻繁的創(chuàng)建和銷毀連接。當(dāng)然蔼水,類似的例子還有很多震糖,如數(shù)據(jù)庫連接池、HttpClient連接池趴腋。

我們寫代碼的過程中吊说,學(xué)會(huì)池化思想,最直接相關(guān)的就是使用線程池而不是去new一個(gè)線程优炬。

6. 事件回調(diào)思想:拒絕阻塞等待颁井。

如果你調(diào)用一個(gè)系統(tǒng)B的接口,但是它處理業(yè)務(wù)邏輯蠢护,耗時(shí)需要10s甚至更多雅宾。然后你是一直阻塞等待,直到系統(tǒng)B的下游接口返回葵硕,再繼續(xù)你的下一步操作嗎眉抬?這樣顯然不合理

我們參考IO多路復(fù)用模型懈凹。即我們不用阻塞等待系統(tǒng)B的接口蜀变,而是先去做別的操作。等系統(tǒng)B的接口處理完介评,通過事件回調(diào)通知库北,我們接口收到通知再進(jìn)行對(duì)應(yīng)的業(yè)務(wù)操作即可。

如果大家忘記了IO模型,可以復(fù)習(xí)一下我的文章:看一遍就理解:IO模型詳解

7. 遠(yuǎn)程調(diào)用由串行改為并行

假設(shè)我們?cè)O(shè)計(jì)一個(gè)APP首頁的接口贤惯,它需要查用戶信息洼专、需要查banner信息、需要查彈窗信息等等孵构。如果是串行一個(gè)一個(gè)查屁商,比如查用戶信息200ms,查banner信息100ms颈墅、查彈窗信息50ms蜡镶,那一共就耗時(shí)350ms了,如果還查其他信息恤筛,那耗時(shí)就更大了官还。

image.png

其實(shí)我們可以改為并行調(diào)用,即查用戶信息毒坛、查banner信息望伦、查彈窗信息,可以同時(shí)并行發(fā)起煎殷。

image.png

最后接口耗時(shí)將大大降低屯伞。有些小伙伴說,不知道如何使用并行優(yōu)化接口?

我之前寫過一篇文章并行優(yōu)化接口的文章豪直,保姆級(jí)別的劣摇!大家可以看一下,看完會(huì)有用的:后端思維篇弓乙,手把手教你寫一個(gè)并行調(diào)用模板

8. 鎖粒度避免過粗

在高并發(fā)場景末融,為了防止超賣等情況,我們經(jīng)常需要加鎖來保護(hù)共享資源暇韧。但是勾习,如果加鎖的粒度過粗,是很影響接口性能的懈玻。

什么是加鎖粒度呢语卤?

其實(shí)就是就是你要鎖住的范圍是多大。比如你在家上衛(wèi)生間酪刀,你只要鎖住衛(wèi)生間就可以了吧,不需要將整個(gè)家都鎖起來不讓家人進(jìn)門吧钮孵,衛(wèi)生間就是你的加鎖粒度骂倘。

不管你是synchronized加鎖還是redis分布式鎖,只需要在共享臨界資源加鎖即可巴席,不涉及共享資源的历涝,就不必要加鎖。這就好像你上衛(wèi)生間,不用把整個(gè)家都鎖住荧库,鎖住衛(wèi)生間門就可以了堰塌。

比如,在業(yè)務(wù)代碼中分衫,有一個(gè)ArrayList因?yàn)樯婕暗蕉嗑€程操作场刑,所以需要加鎖操作,假設(shè)剛好又有一段比較耗時(shí)的操作(代碼中的slowNotShare方法)不涉及線程安全問題蚪战。反例加鎖牵现,就是一鍋端,全鎖住:

//不涉及共享資源的慢方法
private void slowNotShare() {
    try {
        TimeUnit.MILLISECONDS.sleep(100);
    } catch (InterruptedException e) {
    }
}

//錯(cuò)誤的加鎖方法
public int wrong() {
    long beginTime = System.currentTimeMillis();
    IntStream.rangeClosed(1, 10000).parallel().forEach(i -> {
        //加鎖粒度太粗了邀桑,slowNotShare其實(shí)不涉及共享資源
        synchronized (this) {
            slowNotShare();
            data.add(i);
        }
    });
    log.info("cosume time:{}", System.currentTimeMillis() - beginTime);
    return data.size();
}

正例:

public int right() {
    long beginTime = System.currentTimeMillis();
    IntStream.rangeClosed(1, 10000).parallel().forEach(i -> {
        slowNotShare();//可以不加鎖
        //只對(duì)List這部分加鎖
        synchronized (data) {
            data.add(i);
        }
    });
    log.info("cosume time:{}", System.currentTimeMillis() - beginTime);
    return data.size();
}

9. 切換存儲(chǔ)方式:文件中轉(zhuǎn)暫存數(shù)據(jù)

如果數(shù)據(jù)太大瞎疼,落地?cái)?shù)據(jù)庫實(shí)在是慢的話,就可以考慮先用文件的方式暫存壁畸。先保存文件贼急,再異步下載文件,慢慢保存到數(shù)據(jù)庫捏萍。

這里可能會(huì)有點(diǎn)抽象太抓,給大家分享一個(gè),我之前的一個(gè)真實(shí)的優(yōu)化案例吧照弥。

之前開發(fā)了一個(gè)轉(zhuǎn)賬接口腻异。如果是并發(fā)開啟,10個(gè)并發(fā)度这揣,每個(gè)批次1000筆轉(zhuǎn)賬明細(xì)數(shù)據(jù)悔常,數(shù)據(jù)庫插入會(huì)特別耗時(shí),大概6秒左右给赞;這個(gè)跟我們公司的數(shù)據(jù)庫同步機(jī)制有關(guān)机打,并發(fā)情況下,因?yàn)閮?yōu)先保證同步片迅,所以并行的插入變成串行啦残邀,就很耗時(shí)。

優(yōu)化前柑蛇,1000筆明細(xì)轉(zhuǎn)賬數(shù)據(jù)芥挣,先落地DB數(shù)據(jù)庫,返回處理中給用戶耻台,再異步轉(zhuǎn)賬空免。如圖:

image.png

記得當(dāng)時(shí)壓測的時(shí)候,高并發(fā)情況盆耽,這1000筆明細(xì)入庫蹋砚,耗時(shí)都比較大扼菠。所以我轉(zhuǎn)換了一下思路,把批量的明細(xì)轉(zhuǎn)賬記錄保存的文件服務(wù)器坝咐,然后記錄一筆轉(zhuǎn)賬總記錄到數(shù)據(jù)庫即可循榆。接著異步再把明細(xì)下載下來,進(jìn)行轉(zhuǎn)賬和明細(xì)入庫墨坚。最后優(yōu)化后秧饮,性能提升了十幾倍

優(yōu)化后框杜,流程圖如下:

image.png

如果你的接口耗時(shí)瓶頸就在數(shù)據(jù)庫插入操作這里浦楣,用來批量操作等,還是效果還不理想咪辱,就可以考慮用文件或者MQ等暫存振劳。有時(shí)候批量數(shù)據(jù)放到文件,會(huì)比插入數(shù)據(jù)庫效率更高油狂。

10. 索引

提到接口優(yōu)化历恐,很多小伙伴都會(huì)想到添加索引。沒錯(cuò)专筷,添加索引是成本最小的優(yōu)化弱贼,而且一般優(yōu)化效果都很不錯(cuò)。

索引優(yōu)化這塊的話磷蛹,一般從這幾個(gè)維度去思考:

  • 你的SQL加索引了沒吮旅?
  • 你的索引是否真的生效?
  • 你的索引建立是否合理味咳?

10.1 SQL沒加索引

我們開發(fā)的時(shí)候庇勃,容易疏忽而忘記給SQL添加索引。所以我們?cè)趯懲?code>SQL的時(shí)候槽驶,就順手查看一下 explain執(zhí)行計(jì)劃责嚷。

explain select * from user_info where userId like '%123';

你也可以通過命令show create table,整張表的索引情況掂铐。

show create table user_info;

如果某個(gè)表忘記添加某個(gè)索引罕拂,可以通過alter table add index命令添加索引

alter table user_info add index idx_name (name);

一般就是:SQLwhere條件的字段,或者是order by 全陨、group by后面的字段需需要添加索引爆班。

10.2 索引不生效

有時(shí)候,即使你添加了索引辱姨,但是索引會(huì)失效的蛋济。田螺哥整理了索引失效的常見原因

image.png

10.3 索引設(shè)計(jì)不合理

我們的索引不是越多越好,需要合理設(shè)計(jì)炮叶。比如:

  • 刪除冗余和重復(fù)索引碗旅。
  • 索引一般不能超過5個(gè)
  • 索引不適合建在有大量重復(fù)數(shù)據(jù)的字段上、如性別字段
  • 適當(dāng)使用覆蓋索引
  • 如果需要使用force index強(qiáng)制走某個(gè)索引镜悉,那就需要思考你的索引設(shè)計(jì)是否真的合理了

11. 優(yōu)化SQL

處了索引優(yōu)化祟辟,其實(shí)SQL還有很多其他有優(yōu)化的空間。比如這些:

image.png

更詳細(xì)的內(nèi)容侣肄,大家可以看我之前的這兩篇文章哈:

12.避免大事務(wù)問題

為了保證數(shù)據(jù)庫數(shù)據(jù)的一致性旧困,在涉及到多個(gè)數(shù)據(jù)庫修改操作時(shí),我們經(jīng)常需要用到事務(wù)稼锅。而使用spring聲明式事務(wù)吼具,又非常簡單,只需要用一個(gè)注解就行@Transactional矩距,如下面的例子:

@Transactional
public int createUser(User user){
    //保存用戶信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    return user.getUserId();
}

這塊代碼主要邏輯就是創(chuàng)建個(gè)用戶拗盒,然后更新一個(gè)通行證pass的標(biāo)記。如果現(xiàn)在新增一個(gè)需求锥债,創(chuàng)建完用戶陡蝇,調(diào)用遠(yuǎn)程接口發(fā)送一個(gè)email消息通知,很多小伙伴會(huì)這么寫:

@Transactional
public int createUser(User user){
    //保存用戶信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    sendEmailRpc(user.getEmail());
    return user.getUserId();
}

這樣實(shí)現(xiàn)可能會(huì)有坑哮肚,事務(wù)中嵌套RPC遠(yuǎn)程調(diào)用登夫,即事務(wù)嵌套了一些非DB操作。如果這些非DB操作耗時(shí)比較大的話允趟,可能會(huì)出現(xiàn)大事務(wù)問題恼策。

所謂大事務(wù)問題就是,就是運(yùn)行時(shí)間長的事務(wù)潮剪。由于事務(wù)一致不提交涣楷,就會(huì)導(dǎo)致數(shù)據(jù)庫連接被占用,即并發(fā)場景下鲁纠,數(shù)據(jù)庫連接池被占滿总棵,影響到別的請(qǐng)求訪問數(shù)據(jù)庫,影響別的接口性能改含。

大事務(wù)引發(fā)的問題主要有:接口超時(shí)情龄、死鎖、主從延遲等等捍壤。因此骤视,為了優(yōu)化接口,我們要規(guī)避大事務(wù)問題鹃觉。我們可以通過這些方案來規(guī)避大事務(wù):

  • RPC遠(yuǎn)程調(diào)用不要放到事務(wù)里面
  • 一些查詢相關(guān)的操作专酗,盡量放到事務(wù)之外
  • 事務(wù)中避免處理太多數(shù)據(jù)

13. 深分頁問題

在以前公司分析過幾個(gè)接口耗時(shí)長的問題,最終結(jié)論都是因?yàn)?strong>深分頁問題。

深分頁問題桐绒,為什么會(huì)慢?我們看下這個(gè)SQL

select id,name,balance from account where create_time> '2020-09-19' limit 100000,10;

limit 100000,10意味著會(huì)掃描100010行霞扬,丟棄掉前100000行佑笋,最后返回10行翼闹。即使create_time,也會(huì)回表很多次蒋纬。

我們可以通過標(biāo)簽記錄法和延遲關(guān)聯(lián)法來優(yōu)化深分頁問題猎荠。

13.1 標(biāo)簽記錄法

就是標(biāo)記一下上次查詢到哪一條了,下次再來查的時(shí)候蜀备,從該條開始往下掃描关摇。就好像看書一樣,上次看到哪里了碾阁,你就折疊一下或者夾個(gè)書簽输虱,下次來看的時(shí)候,直接就翻到啦瓷蛙。

假設(shè)上一次記錄到100000悼瓮,則SQL可以修改為:

select  id,name,balance FROM account where id > 100000 limit 10;

這樣的話,后面無論翻多少頁艰猬,性能都會(huì)不錯(cuò)的横堡,因?yàn)槊辛?code>id主鍵索引。但是這種方式有局限性:需要一種類似連續(xù)自增的字段冠桃。

13.2 延遲關(guān)聯(lián)法

延遲關(guān)聯(lián)法命贴,就是把條件轉(zhuǎn)移到主鍵索引樹,然后減少回表食听。優(yōu)化后的SQL如下:

select  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.create_time > '2020-09-19' limit 100000, 10) AS acct2 on acct1.id= acct2.id;

優(yōu)化思路就是胸蛛,先通過idx_create_time二級(jí)索引樹查詢到滿足條件的主鍵ID,再與原表通過主鍵ID內(nèi)連接樱报,這樣后面直接走了主鍵索引了葬项,同時(shí)也減少了回表。

14. 優(yōu)化程序結(jié)構(gòu)

優(yōu)化程序邏輯迹蛤、程序代碼民珍,是可以節(jié)省耗時(shí)的。比如盗飒,你的程序創(chuàng)建多不必要的對(duì)象嚷量、或者程序邏輯混亂,多次重復(fù)查數(shù)據(jù)庫逆趣、又或者你的實(shí)現(xiàn)邏輯算法不是最高效的蝶溶,等等。

我舉個(gè)簡單的例子:復(fù)雜的邏輯條件宣渗,有時(shí)候調(diào)整一下順序抖所,就能讓你的程序更加高效梨州。

假設(shè)業(yè)務(wù)需求是這樣:如果用戶是會(huì)員,第一次登陸時(shí)部蛇,需要發(fā)一條感謝短信摊唇。如果沒有經(jīng)過思考,代碼直接這樣寫了

if(isUserVip && isFirstLogin){
    sendSmsMsg();
}

假設(shè)有5個(gè)請(qǐng)求過來涯鲁,isUserVip判斷通過的有3個(gè)請(qǐng)求,isFirstLogin通過的只有1個(gè)請(qǐng)求有序。那么以上代碼抹腿,isUserVip執(zhí)行的次數(shù)為5次,isFirstLogin執(zhí)行的次數(shù)也是3次旭寿,

如果調(diào)整一下isUserVipisFirstLogin的順序:

if(isFirstLogin && isUserVip ){
    sendMsg();
}

isFirstLogin執(zhí)行的次數(shù)是5次警绩,isUserVip執(zhí)行的次數(shù)是1次:

醬紫程序是不是變得更高效了呢?

15. 壓縮傳輸內(nèi)容

壓縮傳輸內(nèi)容盅称,傳輸報(bào)文變得更小肩祥,因此傳輸會(huì)更快啦。10M帶寬缩膝,傳輸10k的報(bào)文混狠,一般比傳輸1M的會(huì)快呀。

打個(gè)比喻疾层,一匹千里馬将饺,它馱著100斤的貨跑得快,還是馱著10斤的貨物跑得快呢痛黎?

再舉個(gè)視頻網(wǎng)站的例子:

如果不對(duì)視頻做任何壓縮編碼予弧,因?yàn)閹捰质怯邢薜摹?strong>巨大的數(shù)據(jù)量在網(wǎng)絡(luò)傳輸?shù)暮臅r(shí)會(huì)比編碼壓縮后,慢好多倍湖饱。

16. 海量數(shù)據(jù)處理掖蛤,考慮NoSQL

之前看過幾個(gè)慢SQL,都是跟深分頁問題有關(guān)的井厌。發(fā)現(xiàn)用來標(biāo)簽記錄法和延遲關(guān)聯(lián)法蚓庭,效果不是很明顯,原因是要統(tǒng)計(jì)和模糊搜索旗笔,并且統(tǒng)計(jì)的數(shù)據(jù)是真的大彪置。最后跟組長對(duì)齊方案,就把數(shù)據(jù)同步到Elasticsearch蝇恶,然后這些模糊搜索需求拳魁,都走Elasticsearch去查詢了。

我想表達(dá)的就是撮弧,如果數(shù)據(jù)量過大潘懊,一定要用關(guān)系型數(shù)據(jù)庫存儲(chǔ)的話姚糊,就可以分庫分表。但是有時(shí)候授舟,我們也可以使用NoSQL救恨,如Elasticsearch、Hbase等释树。

17. 線程池設(shè)計(jì)要合理

我們使用線程池肠槽,就是讓任務(wù)并行處理,更高效地完成任務(wù)奢啥。但是有時(shí)候秸仙,如果線程池設(shè)計(jì)不合理,接口執(zhí)行效率則不太理想桩盲。

一般我們需要關(guān)注線程池的這幾個(gè)參數(shù):核心線程寂纪、最大線程數(shù)量、阻塞隊(duì)列赌结。

  • 如果核心線程過小捞蛋,則達(dá)不到很好的并行效果。
  • 如果阻塞隊(duì)列不合理柬姚,不僅僅是阻塞的問題拟杉,甚至可能會(huì)OOM
  • 如果線程池不區(qū)分業(yè)務(wù)隔離,有可能核心業(yè)務(wù)被邊緣業(yè)務(wù)拖垮伤靠。

大家可以看下我之前兩篇有關(guān)于線程池的文章:

18.機(jī)器問題 (fullGC捣域、線程打滿、太多IO資源沒關(guān)閉等等)宴合。

有時(shí)候焕梅,我們的接口慢,就是機(jī)器處理問題卦洽。主要有fullGC贞言、線程打滿、太多IO資源沒關(guān)閉等等阀蒂。

  • 之前排查過一個(gè)fullGC問題:運(yùn)營小姐姐導(dǎo)出60多萬excel的時(shí)候该窗,說卡死了,接著我們就收到監(jiān)控告警蚤霞。后面排查得出酗失,我們老代碼是Apache POI生成的excel,導(dǎo)出excel數(shù)據(jù)量很大時(shí)昧绣,當(dāng)時(shí)JVM內(nèi)存吃緊會(huì)直接Full GC了规肴。
  • 如果線程打滿了,也會(huì)導(dǎo)致接口都在等待了。所以拖刃。如果是高并發(fā)場景删壮,我們需要接入限流,把多余的請(qǐng)求拒絕掉兑牡。
  • 如果IO資源沒關(guān)閉央碟,也會(huì)導(dǎo)致耗時(shí)增加。這個(gè)大家可以看下均函,平時(shí)你的電腦一直打開很多很多文件亿虽,是不是會(huì)覺得很卡。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末苞也,一起剝皮案震驚了整個(gè)濱河市经柴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌墩朦,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翻擒,死亡現(xiàn)場離奇詭異氓涣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)陋气,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門劳吠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巩趁,你說我怎么就攤上這事痒玩。” “怎么了议慰?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵蠢古,是天一觀的道長。 經(jīng)常有香客問我别凹,道長草讶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任炉菲,我火速辦了婚禮堕战,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拍霜。我一直安慰自己嘱丢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布祠饺。 她就那樣靜靜地躺著越驻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伐谈,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天烂完,我揣著相機(jī)與錄音,去河邊找鬼诵棵。 笑死抠蚣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的履澳。 我是一名探鬼主播嘶窄,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼距贷!你這毒婦竟也來了柄冲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤忠蝗,失蹤者是張志新(化名)和其女友劉穎现横,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阁最,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡戒祠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了速种。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姜盈。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖配阵,靈堂內(nèi)的尸體忽然破棺而出馏颂,到底是詐尸還是另有隱情,我是刑警寧澤棋傍,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布救拉,位于F島的核電站,受9級(jí)特大地震影響舍沙,放射性物質(zhì)發(fā)生泄漏近上。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一拂铡、第九天 我趴在偏房一處隱蔽的房頂上張望壹无。 院中可真熱鬧,春花似錦感帅、人聲如沸斗锭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岖是。三九已至帮毁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間豺撑,已是汗流浹背烈疚。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聪轿,地道東北人爷肝。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像陆错,于是被迫代替她去往敵國和親灯抛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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