天天看點

MySQL 5.7 高可用性分析

mysql 高可用性

沒有放之四海而皆準的方案,具體使用哪種高可用性解決方案依賴于以下幾點:

1.可用性需求級别

2.部署的應用的種類

3.你的環境所接受的最佳實踐

mysql的高可用性可以歸結為三個範疇:

1.資料備援 --99.9%

2.叢集&虛拟系統 --99.99%

3.無共享的,實體備份叢集 --99.999%

3個範疇成本遞增,可靠性也遞增

Table 16.1 Feature Comparison of MySQL HA Solutions

Requirement MySQL Replication MySQL Cluster
Availability
Platform Support All Supported by MySQL Server (http://www.mysql.com/support/supportedplatforms/database.html) All Supported by MySQL Cluster (http://www.mysql.com/support/supportedplatforms/cluster.html)
Automated IP Failover No Depends on Connector and Configuration
Automated Database Failover No Yes
Automatic Data Resynchronization No Yes
Typical Failover Time User / Script Dependent 1 Second and Less
Synchronous Replication No, Asynchronous and Semisynchronous Yes
Shared Storage No, Distributed No, Distributed
Geographic redundancy support Yes Yes, via MySQL Replication
Update Schema On-Line No Yes
Scalability
Number of Nodes One Master, Multiple Slaves 255
Built-in Load Balancing Reads, via MySQL Replication Yes, Reads and Writes
Supports Read-Intensive Workloads Yes Yes
Supports Write-Intensive Workloads Yes, via Application-Level Sharding Yes, via Auto-Sharding
Scale On-Line (add nodes, repartition, etc.) No Yes

使用zfs複制

1.通過zfs指令可以建立傳輸復原快照。通過不斷的建立傳輸復原,可以實作類似drdb的同步機制

2.重用指令有zfs snapshot,zfs list, zfs send, zfs recv, zfs restore, zfs set readonly=on

3.zfs send [email protected] |ssh [email protected] pfexec zfs recv -F slavepool 指令建立快照并将快照結果作為pipe的輸入,輸出到另一台機器并在令一台機器執行recv操作恢複快照。這樣就實作了同步功能

4.使用腳本決定你的同步時間,failover時間

使用memcached

Figure 16.2 memcached Architecture Overview

MySQL 5.7 高可用性分析

Figure 16.3 memcached Hash Selection

MySQL 5.7 高可用性分析

Figure 16.4 memcached Hash Selection with New memcached instance

MySQL 5.7 高可用性分析

Figure 16.5 Memory Allocation in memcached

MySQL 5.7 高可用性分析

memcached線程優化:

0.編譯時打開thread implementation

1.封裝了線程處理函數,這個封裝提供了基礎保護,保護相同的全局變量不需要再次更新,即子線程繼承了父線程中的全局變量

2.每個線程使用自己的libevent執行個體

3.單線程監聽tcp端口,rr算法派遣到處理線程,之後此連接配接的都由該處理線程處理,即實作了連接配接和線程的綁定,防止線程切換影響性能

4.對于udp,所有線程采用搶占方式,沒有搶到的線程ignore掉該請求

5.7版本新增:

1. 增加了一個線程池來減小開銷增加性能

2. 線程池解決了每個連接配接一個線程模型的幾個問題:

    在高并發模型下,太多線程堆棧導緻cpu緩存的是最沒有用的資料,線程池保證線程棧适用于最小cpu緩存記步

    太多的并發線程導緻線程上下文切換開銷高,也會給作業系統作業排程帶來挑戰,線程池在mysql内部級别控制活動的線程總數,對mysql運作的host也更加恰當

    并發數太多增大線程間的資源傳輸,在innodb這種線程太多增大擷取mutex的時間,線程池控制了并發環境下同時開始傳輸的線程數

3. 線程池隻在mysql企業版才有,社群版是沒有的

4. 需要核心版本2.6.9及以上

線程池的實作:

1. 一個庫檔案包含了線程池的核心和INFORMATION_SCHEMA 資料庫中的幾個表

2. INFORMATION_SCHEMA 中的表命名為TP_THREAD_STATE, TP_THREAD_GROUP_STATE, 以及TP_THREAD_GROUP_STATS,這些表提供線程池所有的操作

3. 和線程池相關的有一些系統變量,線程處理器變量在成功加載線城池插件時動态加載,其他線城池插件相關變量隻有主動enable後才生效的有:

  • thread_pool_algorithm: 目前線程排程算法
  • thread_pool_high_priority_connection: 優先級,涉及如何排程會話執行
  • thread_pool_prio_kickup_timer: 線程池把一個低優先級任務移動到高優先級隊列的等待時間
  • thread_pool_max_unused_threads: 允許的最大睡眠線程的個數
  • thread_pool_size: 線程池中線程的數量,這是線程池性能的最重要參數
  • thread_pool_stall_limit: 線程被認為已經stalled的時間

線程池安裝:

    插件庫檔案需要放置在mysql plugin目錄下(該目錄由名為plugin_dir的系統變量指定),如果有需要可以在伺服器啟動時添加這個環境變量

    資料庫插件名為thread _pool(linux e.g. thread_pool.so)

    在啟動資料庫服務時加參數--plugin-load使能,也可以加入配置檔案:

[mysqld] plugin-load=thread_pool.so

    等效于:

[mysqld] plugin-load=thread_pool=thread_pool.so;tp_thread_state=thread_pool.so;tp_thread_group_state=thread_pool.so;tp_thread_group_stats=thread_pool.so

    為了更詳細還可以:

[mysqld] plugin-load-add=thread_pool=thread_pool.so plugin-load-add=tp_thread_state=thread_pool.so plugin-load-add=tp_thread_group_state=thread_pool.so plugin-load-add=tp_thread_group_stats=thread_pool.so

    如果需要可以隻加載插件而不包含表:

[mysqld] plugin-load=thread_pool=thread_pool.so

    檢查安裝成功:

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS -> WHERE PLUGIN_NAME LIKE 'thread%' OR PLUGIN_NAME LIKE 'tp%'; +-----------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +-----------------------+---------------+ | thread_pool | ACTIVE | | TP_THREAD_STATE | ACTIVE | | TP_THREAD_GROUP_STATE | ACTIVE | | TP_THREAD_GROUP_STATS | ACTIVE | +-----------------------+---------------+

    如果這些插件狀态都是active,那麼thread_pool已經生效了

線程池操作:

1. 線程池包含多個線程組,每個線程組管理一組用戶端連接配接。每當連接配接建立時,線程池把他們按照rr算法配置設定給線程組

2. 一個組的最大線程數是4K(有些系統上是4095,那個1被内部使用了)

3. 線程池分離開線程和連接配接,是以線程和連接配接之間不再有固定聯系。這個和預設的線程處理模型不通,預設的線程處理模型在連接配接建立時為每個連接配接配置設定一個線程,兩者一一對應

4. 線程池盡力去保證同一時間一個組裡隻有一個線程在運作,但是有時臨時的允許多個線程同時運作以便達到最大性能。它工作算法按照一下的行為模式:

    每個組有一個監聽線程監聽從配置設定給這個組的連接配接發來的聲明。當聲明到達,線程組或者立即執行或者将其排隊:

        如果目前聲明是唯一聲明且沒有其他排隊的聲明且沒有正在運作的聲明則立即執行

        隻要不能呢個立即執行就将其排隊

    如果立即執行發生,則執行被監聽線程執行(這以為着此時組裡沒有線程在監聽)。如果該聲明執行的快,執行線程轉為監聽線程。否則,線程池認為該執行已經穩定了并且啟動另一個線程進行監聽。為了保證沒有線程因長期執行的聲明足賽,線程池有一個背景線程監測線程組的狀态

    通過使用監聽線程執行,聲明可以立即執行,是以如果執行動作很快結束,沒有必要建立額外線程。這就保證了最少的并發線程最高效執行任務

    當線程池插件啟動時,它為沒有個組建立一個監聽線程,插入背景線程。額外線程按需建立

    thread_pool_stall_limit系統變量界定了“很快結束”的含義。預設時間是60ms,最大可以設定為6s。這個參數可配置以保證你在伺服器負載上獲得一個平衡。這個值越短線程啟動的越快,并且對解決死鎖問題更好。這個值越長對需要長時間運作的、負載比較大的聲明越好,這樣做避免一個聲明在執行時有太多的新聲明與它競争

    線程池聚焦于限制運作時間短的聲明的并發。這聲明執行達到stall time前,它阻止其他聲明與其競争。如果執行時間超過了stall time,它允許繼續啟動其他聲明。這樣,線程池盡力保證每個線程組不會超過一個短時間運作的聲明,盡管長時間執行的有很多。設計者不希望讓長時間運作的聲明阻止其他聲明的執行,因為長時間執行的執行時間是不可預知的。例如在複制的主節點上,有一個發送binarylog event的線程會一直跑

    一個聲明遇到I/O操作或使用者級别的鎖(row lock或table lock)時變為阻塞态。這種阻塞可能引發線程池不可用,是以線程池提供了一個回調,執行線程通過回調通知線程池可以立即啟動一個新線程處理其他聲明了。當阻塞線程傳回時,線程池允許它立即重新執行

    線程池包含兩個隊列,一個高優先級隊列和一個低優先級隊列。傳輸過程的第一個聲明進到低優先級隊列。任何接下來的聲明進入高優先級。通過thread_pool_high_priority_connection系統變量可以設定為所有聲明都進入高優先級隊列

繼續閱讀