天天看點

系統架構設計論文:論大規模分布式系統緩存設計政策

作者:網際網路雜談A

【摘要】

2019 年 3 月,我機關聯合某高校研發了《程式線上評測比賽考試系統》。系統以程式代碼線上送出自動評測功能為核心,分為題庫子產品、評測機子產品、實驗作業子產品、考試子產品、比賽子產品、抄襲判定子產品、使用者管理子產品等,支援對接教務平台。在項目中我擔任系統架構師,負責架構設計工作。本文以該系統為例,主要論述了大規模分布式系統緩存設計政策在項目中的具體應用。系統緩存基于 Redis 記憶體資料庫實作,工作模式的選擇上根據不同資料類型,采用了主從模式與叢集模式結合的設計;通過資料持久化、資料備份計劃、備援機制和監控平台等方法實作高可用性;通過資料通路層封裝同步操作實作緩存一緻性,通過哈希環實作分布式算法。最終系統順利上線,獲得使用者一緻好評。

【正文】

筆者在一個專為高校建設計算機專業智能教學一體化平台的機關任職,過往成果有《計算機組成原理仿真實驗系統》等。2019 年 3 月,我機關聯合某大學研發了《程式線上評測比賽考試系統》項目(以下簡稱為“OJ 系統”),以取代原有傳統的程式設計上機考試平台。系統以程式代碼的線上送出自動評測功能為核心,主要分為題庫子產品、評測機子產品、實驗作業子產品、考試子產品、比賽子產品、抄襲判定子產品、使用者管理子產品等。題庫子產品主要負責試題和測試用例的管理,使用者根據試題要求編寫程式代碼送出到系統,系統将測試用例與程式代碼發送給評測機子產品,由評測機自動編譯、執行、判分,并将結果發送給其他相關子產品進行統計;實驗作業子產品用于線上布置作業,從題庫中選取試題,設定截止日期等要求;考試子產品用于學生線上考試,按教師預先設定的參數自動從題庫随機抽題生成試卷,以及向教務平台上傳考試成績;比賽子產品主要用于 ACM 競賽的教育訓練;抄襲判定子產品用于鑒定代碼與他人代碼雷同率;使用者管理子產品負責使用者資訊的管理。在這個項目中,我擔任了系統架構師的職務,主要負責系統的架構設計相關工作。系統需要支撐全校學生程式設計課程的學習考試,以及大量校外使用者的使用,為保證系統的性能和使用者體驗,以緩存技術進行優化尤為重要。常見的緩存分為三種工作模式:單點模式、主從模式和叢集模式。單點模式各個應用服務共享同一個緩存執行個體,主要瓶頸在于緩存伺服器的記憶體大小、處理能力和網絡帶寬,适合緩存要求簡單、資料量和吞吐量小、性能要求低的場景;主從模式将緩存的資料複制到多台機器上,資料彼此同步,可分散壓力、獲得更高的吞吐能力,适合資料量不大、改動頻率不大、性能要求高的場景;叢集模式節點間共享資料,部分備援保證一定程度的可用性,可存儲超過單個服務記憶體容量資料,通過增加伺服器緩解資料增長和壓力增加,适合總體資料量大、可伸縮性需求高、用戶端數量龐大的場景。

OJ 系統使用 Spring Cloud 微服務架構開發,基于 Redis 記憶體資料庫實作緩存,運用了多種緩存設計政策,本文着重從工作模式的選擇、高可用性的設計、緩存一緻性與分布式算法三個方面的問題展開論述。

1. 工作模式的選擇

OJ 系統需要支撐全校學生程式設計課程的學習考試,以及大量校外使用者的使用,對可靠性和性能要求高,是以單點模式不予考慮。經過對 OJ 系統業務需求的分析,我們歸納了三種需要緩存的資料類型。第一種是系統配置項、角色權限配置設定等中繼資料資訊。這部分資訊使用頻率很高但資料量小,不會經常改動,我們采用 主從模式來緩存,主緩存節點供系統配置子產品寫入資料,從緩存節點分别供具體業務服務調用。在系統啟動時,自動将相關資料裝入緩存。資訊修改時,先寫入主緩存節點,再同步更新至從緩存節點。第二種是使用者登入的會話狀态,這部分資訊使用頻率高、更新頻繁,且幾乎所有的業務服務都需要依賴此類資料,為保證性能與可靠性,我們采用叢集方式來緩存,集中管理使用者會話,各個業務服務通過資料通路層來調用具體的緩存節點。第三種是業務邏輯中一定時間内不會變化,但資料量大的資訊,如試題資訊、實驗作業資訊等,以及統計機制自動識别的高頻通路資訊,也采用叢集方式緩存。

2. 高可用性的設計

為實作 OJ 系統緩存的高可用性,一方面我們開啟了 Redis 資料持久化功能,并配置了相應的備份政策,能夠有效地解決資料誤操作和資料異常丢失的問題,另一方面,我們設計了一些備援機制。在主從模式中,采用多機主備架構實作備援,在主節點故障時,自動進行主備切換,将從節點提升為主節點繼續服務,保證服務的平穩運作。如果主節點和從節點之間連接配接斷開,重新連接配接時從節點會進行資料的部分重同步,當無法進行部分重同步時,會進行全量重同步。在叢集模式中,采用 Cluster 技術實作備援,每個節點儲存資料和整個叢集狀态,負責一部分哈希槽,每個節點都和其他所有節點連接配接并共享資料。為了使在部分節點失效或者大部分節點無法通信的情況下叢集依然可用,在叢集内部使用了主從複制模型,每個節點都會相應地有 1~N 個從節點,當某個節點不可用時,叢集便會将它的從節點提升作為新的主節點繼續服務。緩存服務發生異常時,可通過 OJ系統的服務監控平台産生報警,提醒運維人員及時處理。

3. 緩存一緻性與分布式算法

為保證 Redis 緩存與原資料庫的資料一緻性,當讀取資料時,會先讀取 Redis緩存中的資料,如果 Redis 緩存中不存在所要的資料,則從原資料庫中讀取,并同步寫入至 Redis 緩存中,當寫回/删除資料時,寫入到原資料庫中,并同步淘汰Redis 緩存中的資料。業務服務通過使用專門的資料通路層來調用增加緩存後的資料庫,使資料緩存機制對應用透明。在緩存内部實作一緻性,通過分布式雜湊演算法來實作,為考慮到日後緩存叢集的擴充需要,是以不能使用簡單的模 N 哈希法,我們在 OJ 系統中采用了哈希環的算法。該算法構造一個長度為 2^32 的整數環,将 Redis 節點放置于環上,當業務服務調用緩存時,首先以服務的應用 ID作為鍵值計算哈希在環上定位,然後沿順時針方向找到最近的 Redis 節點,完成映射。當緩存服務叢集中有節點故障,以及添加新節點時,隻會影響上一個節點的資料,避免了發生緩存雪崩的情況,提高了容錯性和擴充性。哈希環中緩存節點過少時易發生緩存傾斜,我們通過增加虛拟節點的方式解決了該問題。

【總結】

我們在這次系統設計中,還使用了很多其他的緩存設計政策,這裡不再一一贅述。系統在經過性能測試、負載測試、壓力測試、穩定性測試後,自 2019 年10 月正式上線已運作一年有餘,在學校的日常教學考試和競賽教育訓練中投入使用,截至目前已有 3000 名以上的學生使用者、評測了 70000 份以上的程式代碼,獲得了機關同僚上司和學校教師們的一緻好評。日常使用過程中最高出現過 600 餘使用者同時線上進行實驗作業送出、評測的情況,基本未出現頁面加載緩慢、請求逾時的問題,滿足了高校程式設計課平台的基本性能需求。實踐證明,OJ 系統項目能夠順利上線,并且穩定運作,與系統采用了合理的緩存設計密不可分。經過這次大規模分布式系統緩存設計的方法和實施的效果後,我也看到了自己身上的不足之處,在未來還會不斷地更新知識,完善本系統在各方面的設計,使整個系統能夠更加好用,更有效地服務于高校師生。

繼續閱讀