天天看點

mysql redis es對比/梳理

資料存儲方式

. mysql:

行存儲, 存儲結構分為聚簇索引(innodb)和非聚簇索引(myisam),均是采用b+樹結構。

聚簇索引:

必有主鍵索引,主鍵索引的葉子節點存儲了表的資料。非葉子節點都是索引關鍵字,但是不是記錄資料或者資料位址。

可能會有二級索引,二級索引的葉子節點存儲的是主鍵值(而不是行指針)。

(這樣可以減少目前行移動時,二級索引的維護,但會讓二級索引占用更多的空間)。

非聚簇索引:

主鍵索引和二級索引存儲上沒有任何差別,所有的節點都是索引,葉子節點存儲的是索引+索引對應的記錄的資料。

差別:

  1. 聚簇索引讀一定範圍的資料比較快。
  2. 聚簇索引主鍵和行資料會緩存到buffer中,用主鍵查資料更快
  3. 聚簇索引資料變更減少二級索引的維護工作。
  4. 插入速度嚴重依賴于插入順序,聚簇索引更新主鍵代價高。
  5. 聚簇索引二級索引占用一些空間

redis

redis整個資料庫統統加載在記憶體當中進行操作,定期通過異步操作把資料庫資料flush到硬碟上進行儲存。

持久化分為AOF和RDB兩種,RDB生成快照檔案,AOF日志記錄指令。

提供了write和fsync兩種方式寫入記憶體。

es

https://zhuanlan.zhihu.com/p/33671444

反向索引的方式存儲。

主要是通過建立一個term index(trie樹),這棵樹不會包含所有的term,它包含的是term的一些字首。通過term index可以快速地定位到term dictionary的某個offset,然後從這個位置再往後順序查找(二分法查找term dictionary)。再加上一些壓縮技術(搜尋 Lucene Finite State Transducers) term index 的尺寸可以隻有所有term的尺寸的幾十分之一,使得用記憶體緩存整個term index變成可能。

mysql redis es對比/梳理
  • 為什麼比mysql快?

    因為比mysql多了term index(存在記憶體中,以FST(finite state transducers)的形式儲存)加快檢索,從term index查到對應的term dictionary的block位置之後,再去磁盤上找term,大大減少了磁盤的random access次數。

對于mysql來說,如果你給age和gender兩個字段都建立了索引,查詢的時候隻會選擇其中最selective的來用,然後另外一個條件是在周遊行的過程中在記憶體中計算之後過濾掉。

  • es聯合索引利用Skip List / bitset 合并。
每一行叫document,每個單詞叫term,單詞清單叫dictionary。存儲的doc-id list叫posting-list(int的數組,存儲了所有符合某個term的文檔id)。

讀寫

mysql

  1. 二級索引查找到主鍵索引-查找到相關資料

  2. 如果主鍵連續,innodb順序寫io。如果亂序需要取出每條記錄對應的實體block,會引起大量的随機io。(innodb提供了insert buffer,合并插入操作,改亂序為順序)

Redis

  1. 讀記憶體
  2. 寫入到記憶體中,如果開了aof,aof會以日志的形式記錄每個寫操作。

    觸發方式:有寫操作就寫、每秒定時寫(也會丢資料)。

ES

  1. 查詢反向索引
  2. 先寫入buffer,在buffer裡的時候資料是搜尋不到的;同時将資料寫入translog日志檔案。

    2)如果buffer快滿了,或者到一定時間,就會将buffer資料refresh到一個新的segment file中,但是此時資料不是直接進入segment file的磁盤檔案的,而是先進入os cache的。這個過程就是refresh。

    每隔1秒鐘,es将buffer中的資料寫入一個新的segment file,每秒鐘會産生一個新的磁盤檔案,segment file,這個segment file中就存儲最近1秒内buffer中寫入的資料。

    但是如果buffer裡面此時沒有資料,那當然不會執行refresh操作咯,每秒建立換一個空的segment file,如果buffer裡面有資料,預設1秒鐘執行一次refresh操作,刷入一個新的segment file中。

    作業系統裡面,磁盤檔案其實都有一個東西,叫做os cache,作業系統緩存,就是說資料寫入磁盤檔案之前,會先進入os cache,先進入作業系統級别的一個記憶體緩存中去。

    隻要buffer中的資料被refresh操作,刷入os cache中,就代表這個資料就可以被搜尋到了

  3. 資料寫入 --> 進入ES記憶體 buffer (同時記錄到translog)--> 生成反向索引分片(segment)

    2、将 buffer 中的 segment 先同步到檔案系統緩存中,然後再刷寫到磁盤

資料一緻性保證/容災

單節點:

https://sq.163yun.com/blog/article/172546631668785152

mysql存在redo日志和undo日志。通過redo日志和checkpoint保證單機資料不丢失。

redo log記錄了對實際資料檔案的實體變更(資料檔案的什麼位置資料做了如何的變更)。

InnoDB也是采用了WAL(日志優先落盤)。

資料庫down機回放log檔案恢複。

多節點:

MySQL提供了master-slave和group replication 叢集級别的容災方案。

  • Master-Slave架構主要思路是:master負責業務的讀寫請求,然後通過binlog複制到slave節點.
  • 主從架構存在資料不一緻的問題,是以MySQL5.7出現了Mysql Group Replication方案,mgr采用paxos協定實作了資料節點的強同步,保證了所有節點都可以寫資料,并且所有節點讀到的也是最新的資料。

單節點也是通過translog的方式恢複,多節點通過增加replica shard解決。

primary shard首先接收client端發送過來的資料,然後将資料同步到replica shard中,當replica shard也寫入成功後,才會告知client資料已正确寫入,這樣就防止資料還沒寫入replica shard時,primary挂掉導緻的資料丢失。

分布式

master-slave和group replication

  1. 主從同步,讀寫分離。

    Master會将資料同步到slave,而slave不會将資料同步到master。Slave啟動時會連接配接master來同步資料。缺點是資料量很大的情況下,叢集的擴充能力還是受限于單個節點的存儲能力

  2. 資料分片模型

    可以将每個節點看成都是獨立的master,然後通過業務實作資料分片。

    結合上面兩種模型,可以将每個master設計成由一個master和多個slave組成的模型。

  • RedisCluster,存儲單元化

    将所有存儲區域劃分為16384個slots(槽位),每個節點負責一部分槽位,槽位的資訊存儲于每個節點中。當用戶端請求進來時候會拉去一份槽位資訊清單緩存在本地,RedisCluster的每個節點會将叢集的配置資訊持久化到自己的配置檔案中,是以需要引入一套可維護的配置檔案管理方案,盡量做到自動化。

    槽位算法:

    RedisCluster 預設會根據key使用crc32算法進行hash得到一個整數,然後用這個整數對16384取模定位key所在的槽位。它還運作使用者在key字元串裡面嵌入tag将key強制寫入指定的槽位。

    遷移:

  • 首先使用CLUSTER GETKEYSINSLOT 指令擷取該slot中所有的key, 然後每個key依次用MIGRATE指令轉移資料。
  • 資料轉移完畢之後,正式将slot指派給新的節點

當有新的節點加入或者斷開節點時,就會觸發Redis槽位遷移。

當一個槽位正在遷移時候在原節點的狀态為migrating,在目标節點的狀态為importing。

原節點的單個key執行dump指令得到序列化内容,再向目标節點發送restore攜帶序列化内容作為參數的指令,目标節點接收到内容後反序列化複制到記憶體中,響應給原節點成功。原節點收到成功響應後把目前節點的key删掉就完成了節點資料遷移。

mysql redis es對比/梳理
mysql redis es對比/梳理
  1. Redis主庫的災備模式(Redis Sentinel)

    主節點down機的時候隻能手動切換機器。是以redis引入了自動切換機器的哨兵架構模式。

    前提:

    首先哨兵服務單獨部署,需要保證高可用。然後引入zookeeper等分布式協調元件,保證哨兵可以感覺redis叢集的狀态。

    作用:

    哨兵負責監控主節點的監控狀态,當主節點不可用時,自動選一個從節點切換為主節點。

    觸發:

    用戶端在請求主節點時通路失敗,會通過Redis哨兵查詢主節點的位址。

    成功後再将新的主節點清單緩存到用戶端中。

    等故障主節點恢複後會作為一個新的隻讀從節點加入叢集。

自己實作的分布式算法,類似raft。

提供分片功能,并且每個分片都有replica。寫入時,replica shard會同步資料。

一台機器down機,replica shard會變成primary shard。

如果master down機,重新選主。