【秒殺購物商城業務服務】「分散式架構服務」盤點中介軟體服務的高可用模式及叢集技術的方案分析

2022-12-12 15:00:15

秒殺購物商城業務服務-分散式架構介紹

  • 基於MySQL資料庫叢集技術實現服務的高可用
  • 基於Tomcat的叢集負載機制實現Tomcat伺服器的高可用
  • 基於Nginx負載均衡機制實現負載均衡(介紹和設定)
  • 基於Redis快取服務實現資料快取控制相關介紹和技術點分析
  • 對未來的分散式技術架構擴充套件和延伸介紹(包含雲原生部分)

基於MySQL資料庫叢集技術實現服務的高可用

高可用架構對於網際網路服務基本是標配,無論是應用服務還是資料庫服務都需要做到高可用。對於一個系統而言,可能包含很多模組,比如前端應用,快取,資料庫,搜尋,訊息佇列等,每個模組都需要做到高可用,才能保證整個系統的高可用。對於資料庫服務而言,高可用可能更復雜,對使用者的服務可用,不僅僅是能存取,還需要有正確性保證,因此資料庫的高可用需要更加認證對待。

MySQL高可用架構分類

  • MySQL實現高可用之MMM
  • MySQL實現高可用之MHA
  • MySQL實現高可用之主從架構
  • MySQL實現高可用之Cluster模式
MMM的技術分析

MMM(Master-Master replication manager for MySQL)是一套支援雙主故障切換和雙主日常管理的指令碼程式。

MMM的基礎元件分析
  • mmm_mond:監控程序,負責所有的監控工作,決定和處理所有節點角色活動。因此,指令碼需要在監管上執行。
  • mmm_agentd:執行在每個msql伺服器上的代理程序,完成監控的探針工作和執行簡單的遠端服務設定。此指令碼需要在被監管機上執行。
  • mmm_control:一個簡單的指令碼,提供管理mmm_mond進行的命令。
MMM實現基本實現原理

MMM提供了自動和手動兩種方式移除一組伺服器中複製延遲較高的伺服器的虛擬ip,同時它還可以備份資料,實現兩節點之間的資料同步等。

MySQL本身沒有提供replication failover的解決方案,通過MMM方案能實現伺服器的故障轉移,從而實現mysql的高可用。

MHA簡介

MHA(Master High Availability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本DeNA公司的youshimaton(現就職於Facebook公司)開發,是一套優秀的作為MySQL高可用性環境下故障切換和主從提升的高可用軟體。

MHA的基礎元件

MHA由兩部分組成:MHA Manager(管理節點)和MHA Node(資料節點)。

MHA Manager可以單獨部署在獨立的機器上管理多個master-slave叢集,也可以部署在一臺slave節點上。

MHA的實現原理
  • MHA Node執行在每臺MySQL伺服器上,MHA Manager會定時探測叢集中的master節點,當master出現故障時,它可以自動將最新資料的slave提升為新的master,然後將所有其他的slave重新指向新的master。整個故障轉移過程對應用程式完全透明。

MySQL主從架構

此種架構,一般初創企業比較常用,也便於後面步步的擴充套件

此架構特點
  1. 成本低,佈署快速、方便
  2. 讀寫分離
  3. 還能通過及時增加從庫來減少讀庫壓力
  4. 主庫單點故障
  5. 資料一致性問題(同步延遲造成)
MySQL Cluster基本概念

MySQL Cluster簡單地講是一種MySQL叢集的技術,是由一組計算機構成,每臺計算機可以存放一個或者多個節點,其中包括MySQL伺服器,DNB Cluster的資料節點,管理其他節點,以及專門的資料存取程式,這些節點組合在一起,就可以為應用提高可高效能、高可用性和可縮放性的Cluster資料管理;

基於Tomcat的叢集負載機制實現Tomcat伺服器的高可用

Tomcat叢集原理

通過Nginx負載均衡進行請求轉發

Tomcat叢集能帶來什麼

  • 提高服務的效能, 並行能力, 以及高可用性
  • 提供專案架構的橫向擴充套件能力

Tomcat叢集產生什麼問題

  • Session登入資訊儲存以及讀取的問題
  • 伺服器定時任務並行的問題

Tomcat 單服務體系架構

在這個架構圖中,一層Nginx,首先Nginx主要職責給Tomcat一層反向代理。

此外,Nginx還可以FTPServer指定的目錄再做一層目錄轉發,保證上傳上去的圖片實時可以通過http協定存取到。單服務架構先不用考慮叢集碰到的各種問題

Tomcat叢集"簡單版"

比如,我們的登入的時候登入了A伺服器,session資訊儲存到A伺服器上了,假設我們使用的負載均衡策略是ip hash,那麼登入資訊還可以從A伺服器上存取,但是這個有可能造成某些伺服器壓力過大,某些伺服器又沒有什麼壓力,這個時候壓力過大的機器(包括網路卡頻寬)有可能成為瓶頸,並且請求不夠分散。

首先要解決Session共用的問題

這時候我們使用輪詢或者最小連線負載均衡策略,就導致了,第一次存取A伺服器,第二次可能存取到B伺服器,這個時候儲存在A伺服器上的session資訊在B伺服器上讀取不到。

典型負載均衡策略分析

打個比方,我們有輪詢,權重,地址雜湊,地址雜湊又分為原ip地址雜湊hash,目標ip地址雜湊hash,最少連線,加權最少連線,還有繼續升級的很多種策略

  • 輪詢:優點:實現簡單,缺點:不考慮每臺伺服器處理能力
  • 權重:優點:考慮了伺服器處理能力的不同
  • 地址雜湊:優點:能實現同一個使用者存取同一個伺服器
  • 最少連線:優點:使叢集中各個伺服器負載更加均勻
  • 加權最少連線:在最少連線的基礎上,為每臺伺服器加上權值。演演算法為(活動連線數*256+非活動連線數)/權重,計算出來的值小的伺服器優先被選擇。
Session管理-Session Sticky粘滯對談:

對於同一個連線中的封包,負載均衡會將其轉發至後端固定的伺服器進行處理。

解決了我們session共用的問題,但是它有什麼缺點呢?

  • 一臺伺服器執行的服務掛掉,或者重啟,上面的 session 都沒了
  • 負載均衡器成了有狀態的機器,為以後實現容災造成了羈絆
Session管理-Session 複製

就是每一個Tomcat都儲存我們的Session,不同的tomcat之間進行拷貝複製。

解決了我們session共用的問題,但是它有什麼缺點呢?

  • 應用伺服器間頻寬問題,因為需要不斷同步session資料
  • 大量使用者線上時,伺服器佔用記憶體過多
Session管理-基於Cookie

主要用於我們將session對談如同token一般儲存在我們的前端

解決了我們session共用的問題,但是它有什麼缺點呢?

  • cookie 的長度限制
  • cookie存於瀏覽器,安全性是一個問題
Session管理-Session 伺服器

就是通過一個專門管理session對談的管理器服務,進行集中化儲存和管理session

解決了我們session共用的問題,這種方案需要思考哪些問題呢?保證 session 伺服器的可用性,session伺服器單點如何解決?

  • 我們在寫應用時需要做調整儲存session的業務邏輯
  • 打個比方,我們為了提高session server的可用性,可以繼續給session server做叢集

Tomcat單機部署多應用

  1. 解壓2個tomcat, 分別命名為tomcatA和tomcatB

  2. 分別設定2個tomcat的URIEncoding, 將tomcat的conf/server.xml裡的port修改為兩個不同埠。

設定tomcat的環境變數

tomcatA的環境變數和以往一樣, 不做改變

設定tomcat的環境變數

sudo vim /ect/profile

在profile檔案裡新增
export CATALINA_BASE=/Users/tomcat/apache-tomcat-9.0.21
export CATALINA_HOME=/Users/tomcat/apache-tomcat-9.0.21
export TOMCAT_HOME=/Users/tomcat/apache-tomcat-9.0.21
export CATALINA_2_BASE=/Users/tomcat/tomcat2
export CATALINA_2_HOME=/Users/tomcat/tomcat2
export TOMCAT_2_HOME=/Users/tomcat/tomcat2
強制儲存退出

繼續設定tomcatB下的catalina.sh裡的內容,

cd tomcat目錄,在# OS specific support. $var must be set to either true or false.下加入。

sudo vi catalina.sh
export CATALINA_BASE=$CATALINA_2_BASE
export CATALINA_HOME=$CATALINA_2_HOME
執行重新整理環境變數

source /etc/profile

使環境變數生效, 執行

echo $CATALINA_2_BASE

如果有輸出, 即環境變數已經生效

/Users/tomcat/tomcat2

分別進入兩個tomcat下的bin目錄啟動tomcat, 正常即可

設定nginx

修改host

sudo vim /etc/hosts

所謂tomcat叢集,就是可以向外提供並行服務的多臺機器,任何一臺伺服器宕機,其它伺服器可以替代它向外提供服務,而不影響使用者存取。

nginx是一個常用的反向代理服務,可自定義模組,實現請求轉發及負載均衡(根具體採用策略有關)。為了tomcat叢集的高可用性,還需要實現nginx的雙機熱備。

一,如果僅是對外提供一個頁面存取,不用區分單一使用者(不區分每個存取session,不涉及使用者許可權,使用者資料等內容),僅僅設定nginx負載均衡策略即可。

nginx負載均衡策略主要分一下四種:
1)、輪詢(預設)每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器宕機,能自動剔除。
2)、ip_hash 每個請求按存取ip的hash結果分配,這樣每個訪客固定存取一個後端伺服器。
3)、fair 按後端伺服器的響應時間來分配請求,響應時間短的優先分配。
4)、url_hash 按存取url的hash結果來分配請求,使每個url定向到同一個後端伺服器,後端伺服器為快取時比較有效。

二,如果涉及到使用者session,做一些鑑權快取、存放臨時資訊時,就必須做tomcat的session共用。

目前可參考到的session共用方式主要分為兩種。

1)利用tomcat自帶的組播機制,實現session複製。

對tomcat及應用的若干組態檔進行設定即可實現,網上有很多資料可參考。但這種方式些弊端,看過一些資料,不建議用session複製的方式。在實際使用過程中,也發現有存在session莫名失蹤的現象。

2)利用第三方機制儲存session。

比較常見的是tomcat整合memcached伺服器來儲存session。實際專案中,我們採用過利用redis實現session儲存,redis高效的存取效能為高效的存取提供了保障,但是目前redis的叢集功能似乎沒有釋出,如何解決redis的單點故障需要研究。

小結:是否實現session共用與nginx的負載策略有很大關係。比如採用輪詢策略,就必須實現session共用,因為使用者端會存取到每臺伺服器;而如果採用ip_hash策略,就可以不用考慮session共用的問題了,但是ip_hash有些缺陷使它不能隨便使用(如多臺pc使用同一個外網ip)。

最近發現一個nginx的粘連模組(類似session粘連),可以看做nginx的第5種均衡策略。它利用使用者端cookie,對其寫入一個route引數,每次存取可以根據route的值,固定的存取一臺伺服器,解決的session共用的問題。

Nginx是什麼?

Nginx(發音同 engine x)是一款輕量級的Web 伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,並在一個BSD-like 協定下發行。由俄羅斯的程式設計師Igor Sysoev(伊戈爾·西索夫)所開發,供俄國大型的入口網站及搜尋引擎Rambler(漫步者)(俄文:Рамблер)使用。其特點是佔有記憶體少,並行能力強,事實上nginx的並行能力確實在同型別的網頁伺服器中表現較好,中國大陸使用nginx網站使用者有:新浪、網易、 騰訊等。

優點

  1. 可執行linux,並有 Windows移植版。
  2. 在高連線並行的情況下,Nginx是Apache伺服器不錯的替代品Nginx在美國是做虛擬主機生意的老闆們經常選擇的軟體平臺之一。能夠支援高達50,000個並行連線數的響應

負載均衡的功能

  • 轉發
  • 故障移除
  • 恢復新增
  • 高可用 Ha

我們想要使用Nginx那麼就必須滿足上面的四個條件.
我們設定負載均衡的目的是在於當用戶存取我們的伺服器的時候, 首先會通過 Nginx伺服器來決定轉發到哪個Tomcat伺服器上去給使用者提供服務, 當然這個概率是我們通過權重來設定的. 經過Nginx指派之後, 我們就可以處理高並行的存取了, 這裡就能達到負載均衡的目的.

Nginx如何實現負載均衡

Nginx的負載均衡是通過upstream來實現的,在upstream中指定若干個 server,格式如下:

myserver就是通過 upstream 定義的一組負載均衡模板,其中:

在設定完upstream後,還要讓使用者端過來的請求反向代理到myserver,格式如下:

完成了負載均衡的設定,但是在實際需求中除了上面的設定外,還會增加一些額外設定:

負載均衡策略設定請求上游伺服器攜帶請求頭資訊upstream模組中其他引數設定

Nginx的負載均衡策略有5種方式:

除以上5種,還有一種:least-connected — 下一個請求被分配到擁有最少活動連線數的伺服器。

編輯nginx組態檔(例中為/usr/local/ngnix/conf/nginx.conf),找到http結點,

設定案例
http {
    upstream myapp1 {
        server 192.168.1.103:8080;
        server 192.168.1.104:8080;
   }
   server {
        listen 80;
        server_name  localhost;
        location /webautotest/ {
            proxy_buffering off;
            proxy_pass http://myapp1;
        }
    }
}
重新載入組態檔
[root@localhost nginx-1.10.0]# /usr/local/ngnix/sbin/nginx -s reload
預設的負載均衡設定
http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }
    server {
        listen 80;
        location / {
            proxy_pass http://myapp1;
        }
    }
}
最少連線負載均衡
  • 另一個負載均衡原則為least-connected。當一些請求花費較長時間來完成時,least-connected更「公平」的控制應用程式範例上的負載。
  • 設定了least-connected的負載均衡機制的情況下,nginx會盡量不讓負載繁忙的應用伺服器上負載過多的請求,相反的,會把新的請求傳送到比較不繁忙的伺服器。
設定範例:
upstream myapp1 {
        least_conn;
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
}
對談永續性

注意,round-robin或least-connected負載均衡下,每個後續的使用者端可能被分發至不同伺服器,不保證相同使用者端的請求總是被傳送到相同的伺服器。

如果有必要把使用者端繫結至特定伺服器,則可使用ip-hash負載均衡機制。

ip-hash機制

ip-hash機制下,使用者端ip地址被用作hash key來判斷使用者端請求應該傳送到哪個伺服器,這種方法保證了來自相同使用者端的請求總是傳送到相同伺服器(如果伺服器可用的話)

upstream myapp1 {
    ip_hash;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

負載均衡權重

可通過設定伺服器權重來影響負載均衡機制。上面的例子中,都未設定伺服器權重,這意味著所有伺服器都擁有相同的權重。
針對round-robin負載機制,權重意味著更多或更少的請求傳送至伺服器---假設有足夠的請求,且按統一方式處理請求,且足夠快完成請求處理。

設定範例:
  upstream myapp1 {
        server srv1.example.com weight=3;
        server srv2.example.com;
        server srv3.example.com;
}

上例設定中,每傳送至伺服器範例的5個新的請求中,有3個傳送到srv1,1個傳送到srv2,另1個傳送到srv3。

注:當前版本似乎只實現了round-robin機制下的權重設定

健康檢測

  • nginx反向代理實現包含伺服器健康檢查。如果來自特定伺服器的響應失敗,報錯,nginx將標記該伺服器為failed,一段時間內儘量避免選擇此伺服器作為隨後請求的分發伺服器。

  • max_fails機制設定fail_timeout期間,和伺服器溝通失敗的連續重試次數,預設為1.當設定為0時,不做伺服器健康檢測。fail_timeout定義了伺服器被標記為failed的時長。fail_timeout時間間隔過後,nginx將開始使用活動使用者端請求來探測伺服器,如果探測成功則標記伺服器為活動伺服器。

Nginx負載均衡設定項介紹

下面我們將介紹一下proxy模組的引數:

各個引數介紹:

設定proxy_connect_timeout 為2秒,縮短超時時間,使其不至於太慢。