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快?
    因為比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 先同步到文件系統緩存中,然后再刷寫到磁盤

數據一致性保證/容災

mysql

單節點:
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協議實現了數據節點的強同步,保證了所有節點都可以寫數據,並且所有節點讀到的也是最新的數據。

ES

單節點也是通過translog的方式恢復,多節點通過增加replica shard解決。
primary shard首先接收client端發送過來的數據,然后將數據同步到replica shard中,當replica shard也寫入成功后,才會告知client數據已正確寫入,這樣就防止數據還沒寫入replica shard時,primary掛掉導致的數據丟失。

分布式

mysql

master-slave和group replication

Redis

  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刪掉就完成了節點數據遷移。

  1. Redis主庫的災備模式(Redis Sentinel)
    主節點down機的時候只能手動切換機器。所以redis引入了自動切換機器的哨兵架構模式。
    前提:
    首先哨兵服務單獨部署,需要保證高可用。然后引入zookeeper等分布式協調組件,保證哨兵可以感知redis集群的狀態。
    作用:
    哨兵負責監控主節點的監控狀態,當主節點不可用時,自動選一個從節點切換為主節點。
    觸發:
    客戶端在請求主節點時訪問失敗,會通過Redis哨兵查詢主節點的地址。
    成功后再將新的主節點列表緩存到客戶端中。
    等故障主節點恢復后會作為一個新的只讀從節點加入集群。

ES

自己實現的分布式算法,類似raft。
提供分片功能,並且每個分片都有replica。寫入時,replica shard會同步數據。
一台機器down機,replica shard會變成primary shard。
如果master down機,重新選主。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM