Soul即時通訊之數(shù)據(jù)庫優(yōu)化

背景

在Soul的IM上線后故俐,初始時用戶本地消息量不大的情況下疮蹦,數(shù)據(jù)庫讀寫良好窖剑,不容易發(fā)現(xiàn)問題辕宏。

但隨著產(chǎn)品用的時間越來越近痊远,有些用戶本地聊天數(shù)據(jù)達到500萬條以上時,數(shù)據(jù)庫性能瓶頸逐漸體現(xiàn)出來刚陡。

1.讀寫數(shù)據(jù)較慢惩妇。

2.讀寫在同一線程里,當大量數(shù)據(jù)寫入時筐乳,遲遲讀不出數(shù)據(jù)歌殃,體驗較差

所以數(shù)據(jù)庫這塊急需優(yōu)化

優(yōu)化之前的方案

之前im用的是著名三方數(shù)據(jù)庫FMDB,它只是簡單的對sqlite進行了封裝蝙云,線程安全方案是把所有的數(shù)據(jù)庫操作放到了一個串行隊列里去同步執(zhí)行氓皱。

因為sqlite是不能多個操作同時訪問一個連接,不然會crash。

這樣做的好處是確保了數(shù)據(jù)庫連接數(shù)據(jù)讀寫安全波材,缺點是無法進行線程并發(fā)操作股淡。

對于IM這種對海量數(shù)據(jù)存儲性能要求較高的項目,F(xiàn)MDB不能滿足需求廷区。

優(yōu)化思考

我們所要做的是支持多線程讀寫的數(shù)據(jù)庫唯灵。

這里介紹下WAL模式:SQLite引入了 WAL 模式,即 Write-Ahead Log隙轻。在這種模式下埠帕,所有的修改會寫入一個單獨的 WAL 文件內(nèi)。這種模式下玖绿,寫操作甚至可以不去操作數(shù)據(jù)庫敛瓷,這使得所有的讀操作可以在 "寫的同時" 直接對數(shù)據(jù)庫文件進行操作,得到更好的并發(fā)性能斑匪。
這樣實現(xiàn)了讀和寫的并發(fā)呐籽。

同時sqlite支持三種線程模式:
單線程模型 這種模型下,所有互斥鎖都被禁用蚀瘸,同一時間只能由一個線程訪問狡蝶。
多線程模型 這種模型下,一個連接在同一時間內(nèi)只有一個線程使用就是安全的苍姜。
串行模型 開啟所有鎖,可以隨意訪問悬包。

優(yōu)化嘗試

前提條件:首先串行模式pass掉衙猪,只考慮單線程和多線程模式。

1.建表:


create table if not exists ChatModelDB (localId INTEGER primary key AUTOINCREMENT, 
CommonId varchar(256),
  text1 varchar(256), 
  text2 varchar(256),
  text3 varchar(256),
  text4 varchar(256), 
  text5 Long Long, 
  text6 INTEGER), 

CommonId建立索引

2.已在數(shù)據(jù)庫里插入100萬條數(shù)據(jù)布近,每一列都是隨機字符垫释。

1.單線程模式 +無wal,也是FMDB模式

插入1萬條根據(jù)CommonId讀取20條

- (void)insert {
dispatch_async(queue, ^{
      [db beginTransaction];
for (int j = 0;j<10000;j++) {
       NString *insertSql = @"insert *****;
       BOOL result = [db executeUpdate:insertSql];
            }
        [db commit];
        }];
     });
}
- (void)select{
     dispatch_async(queue, ^{
            NSArray *array = [db getRowsForQuery:selectSql];
     });
}
混合讀寫
for (i = 0;i<100;i++) {
[self insert];
[self select];
}

寫消耗:1237ms,

讀消耗:10-20ms

混合讀寫:72185

2.單線程模式+wal

 if (sqlite3_exec(_wdb, "PRAGMA journal_mode=WAL;", NULL, NULL, &error) != SQLITE_OK) {
        NSLog(@"Failed to set WAL mode: %s", error);
    }

寫消耗:480ms

讀消耗:10-15ms

混合讀寫:76205ms

會發(fā)現(xiàn)撑瞧,打開wal模式后棵譬,寫性能近乎提示了3倍,讀性能差別不大预伺。

3.多線程模式+多線程連接+wal

    dispatch_async(globlequeue, ^{
       sqlite3_open(db);
           [self insert];
       sqlite3_close(db);
     });
    dispatch_async(globlequeue, ^{
       sqlite3_open(db);
           [self select];
       sqlite3_close(db);
     });

混合讀寫:157301ms

會發(fā)現(xiàn)混合性能很差订咸,真正開啟所謂的多線程操作時,實際上是每個線程持有一個數(shù)據(jù)庫句柄酬诀,每做一個操作前脏嚷,要重新打開一個db句柄,執(zhí)行完后再close db句柄瞒御,這樣頻繁的打開數(shù)據(jù)是很消耗性能的父叙,一味地追求多線程并不會達到很好的性能,并且操作不好還容易crash。

在移動端這種微操作系統(tǒng)對數(shù)據(jù)庫的依賴遠沒有后端那般沉重趾唱,所以接下來考慮用單句柄+隊列的方式進行測試涌乳。

4.多線程模式+wal+異步單隊列

queue = dispatch_queue_create([[self queueName] UTF8String], DISPATCH_QUEUE_SERIAL);

    dispatch_async(queue, ^{
           [self insert];
     });

    dispatch_asyncqueue, ^{
           [self select];
     });

讀寫性能和2相差不大
混合讀寫:68300ms
混合讀寫性能優(yōu)于2,在大型app場景下性能尤為明顯甜癞,本次測試是在無其他業(yè)務(wù)線程影響下夕晓,等于測試示例獨自cpu資源,和線上場景誤差交大带欢。

5.多線程模式+wal+同步單隊列

queue = dispatch_queue_create([[selfqueueName] UTF8String], DISPATCH_QUEUE_SERIAL);

    dispatch_sync(queue, ^{
           [self insert];
     });
    dispatch_syncqueue, ^{
           [self select];
     });

混合讀寫:66454ms
性能略遜于4运授,相差微乎其微,考慮切線程影響

考慮乔煞,多線程模式+wal模式下吁朦,讀和讀并發(fā),讀和寫并發(fā)渡贾,寫和寫不并發(fā)逗宜,
而讀速度遠大于寫速度,因為經(jīng)檢驗空骚,在500萬數(shù)據(jù)量下纺讲,讀速度在20ms以內(nèi)速度較快,所以讀并發(fā)暫不考慮囤屹,只給數(shù)據(jù)庫開啟兩條連接熬甚,讀連接和寫連接, 只做讀和寫之間的并發(fā)肋坚,為此乡括,設(shè)置兩條隊列:讀隊列和寫隊列,彼此異步執(zhí)行智厌,測試示例6诲泌。

6.多線程模式+wal+讀寫隊列分離

readqueue = dispatch_queue_create([[self queueName] UTF8String], DISPATCH_QUEUE_SERIAL);
writequeue = dispatch_queue_create([[self queueName] UTF8String], DISPATCH_QUEUE_SERIAL);

    dispatch_async(writequeue, ^{
           [self insert];
     });
    dispatch_async(readqueue, ^{
           [self select];
     });

混合讀寫:73112ms

這里會發(fā)現(xiàn),雙隊列的讀寫速度居然略慢于單隊列讀寫铣鹏。

分析敷扫,因為數(shù)據(jù)是在demo上跑,demo上無其他任務(wù)在執(zhí)行诚卸,等于cpu滿負荷只為測試調(diào)用葵第,而理論上頻繁的線程切換也需要資源開銷,單隊列模式下的線程切換減少合溺,性能略優(yōu)于雙隊列羹幸。

但在實際的項目中,app場景復雜辫愉,cpu無時不在執(zhí)行做一些復雜的功能栅受,所以在demo上播放一個長視頻進行測試,并且同時異步執(zhí)行一個while循環(huán)空轉(zhuǎn),測試cpu調(diào)度頻繁被其他業(yè)務(wù)影響時數(shù)據(jù)庫操作的性能屏镊。

經(jīng)測試混合讀寫:1.多線程模式+wal+異步單隊列 7800ms左右
2.多線程模式+wal+同步單隊列 73960ms左右
3. 多線程模式+wal+讀寫隊列分離 60471ms左右

在cpu調(diào)度頻繁的場景下依疼,多線程的優(yōu)勢體現(xiàn)了出來,在wal模式下而芥,寫性能提升幾倍律罢,讀和寫并發(fā),讀和讀并發(fā)棍丐,寫和寫串行误辑,達到效率最大化。

所以決定選用模式多線程模式+wal+讀寫隊列分離模式歌逢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巾钉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子秘案,更是在濱河造成了極大的恐慌砰苍,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阱高,死亡現(xiàn)場離奇詭異赚导,居然都是意外死亡,警方通過查閱死者的電腦和手機赤惊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門吼旧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人未舟,你說我怎么就攤上這事圈暗。” “怎么了处面?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵厂置,是天一觀的道長菩掏。 經(jīng)常有香客問我魂角,道長,這世上最難降的妖魔是什么智绸? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任野揪,我火速辦了婚禮,結(jié)果婚禮上瞧栗,老公的妹妹穿的比我還像新娘斯稳。我一直安慰自己,他們只是感情好迹恐,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布挣惰。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪憎茂。 梳的紋絲不亂的頭發(fā)上珍语,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音竖幔,去河邊找鬼板乙。 笑死,一個胖子當著我的面吹牛拳氢,可吹牛的內(nèi)容都是我干的募逞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼馋评,長吁一口氣:“原來是場噩夢啊……” “哼放接!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起栗恩,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤透乾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后磕秤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乳乌,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年市咆,在試婚紗的時候發(fā)現(xiàn)自己被綠了汉操。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒙兰,死狀恐怖磷瘤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搜变,我是刑警寧澤采缚,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站挠他,受9級特大地震影響扳抽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殖侵,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一贸呢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拢军,春花似錦楞陷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽结执。三九已至,卻和暖如春艾凯,著一層夾襖步出監(jiān)牢的瞬間昌犹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工览芳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斜姥,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓沧竟,卻偏偏與公主長得像铸敏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子悟泵,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348