微軟雲自主醫療保健手冊

​今天我們給大家說說Azure上的MySQL的健康保健相關的話題,不帶推銷保健品,大家可以放心食用。

微軟雲自主醫療保健手冊

數據庫是所有應用中最不可或缺的一個組件,所有有狀態的數據都需要依託數據庫提供的格式,規範進行存儲、讀取、改寫等。那麼既然是一個炙手可熱的角色,如何讓系統能夠快速有效的和數據庫進行溝通,就是一個比較有意思的話題了。如果把這個內容全部展開,可能會涉及到數據庫的冗餘性,擴展性設計等一系列的問題,這次我們就先把目標鎖定在如何快速管理連接這個點上。

如果把各個應用比作是需要看病就醫的病患,那麼醫院可以說是一個大的數據庫。那如何看病就醫,井然有序,就需要一個規章法度,比如病人是否有此地就醫的資格,是否已經掛號,有否既往病史,還需要什麼化驗等。那麼同樣,應用如果要得到數據庫的增刪改查的權限也一定要有一個流程。簡要來說,流程就是通過一些網絡協議,握手連接到數據庫,提供一個有效的連接字符串,隨後數據庫會對比此應用是否有資格來訪問這個數據庫,最後就能愉快的增刪改查了。

微軟雲自主醫療保健手冊

接下來我們將以Azure上面的MySQL PaaS為例,給大家講解一些簡單的數據庫連接的使用場景,以及最佳實踐。

第一種場景:單個進程連接,非頻繁訪問

我們假設一個病人只是有點小的頭疼腦熱,那麼第一次就診結束,配了點藥,然後可能需要第二天去複診。這個時候也許他還得要走一次掛號,查醫保信息,配藥看醫生等一系列流程。所以並不能直接敲開醫生診室的門,說我想直接看病配藥。那麼同樣的道理,我們到數據庫的連接中,會有一個超時(timeout)的概念,也就是說我第一次增刪改查完,也許我等待了60秒,再一次查詢,發現數據庫說對不起,請重新連接“掛號”因為時間太長了,我不認識你了,或者說你的狀態我不知道了,請重新握手協議,連接字符串,身份驗證走一遍。那麼我們看圖示,裡面哪些是我們需要一個數據庫連接要提供的信息呢。

1.數據庫的連接字符串,這個可以在Azure上得到你的程序需要的連接字符串。需要注意的是Azure上的數據庫用戶名比較特殊,在@後面會帶上服務器名,這個和本地自建的不太一樣。

微軟雲自主醫療保健手冊

2.隨後我們用Python的程序新建一個表格,並且插入一些數據,模擬一個單進程的非頻繁訪問。

微軟雲自主醫療保健手冊

3.那麼現在我們加入一個延時60秒,看看會發生什麼?

微軟雲自主醫療保健手冊

微軟雲自主醫療保健手冊

4.為什麼之前連接執行語句都好好的,怎們就加了60秒的等待就歇菜了呢?彆著急,我們在Azure MySQL的參數調整裡看一下wait_timeout的值,你會發現,咦,怎麼有一個值是30秒呢?原來超過了30秒這個時間,原來的連接就超時了,我們程序裡寫得是休眠60秒。就需要重新連接,重新掛號了。

微軟雲自主醫療保健手冊

那麼你會發現一旦程序有了空閒時間段,數據庫就會不繼續等待了,直接用timeout這個參數把你的連接給掐斷了,需要你從頭再來。這個很好理解,比如你在昨天看了醫生,醫生也不可能一直記得你,也不可能一直等你,只有到了你再去的時候,重新掛號然後再和白衣天使一起討論病情。那麼你有可能會問,那麼如果是比較複雜的病情,一會要拍個片,一會要驗血,其中都需要等待時間,那麼拿了報告,醫生又讓我掛號,驗證身份,豈不是很煩?那有沒有一個比較人性化的制度可以讓這些頻繁的檢查能夠管理起來,那麼我們就來看第二個場景。

第二個場景:單個進程,需要頻繁交互的數據庫

之前我們討論那種需要等化驗結果,多次詢問醫生的場景。那麼映射到數據庫,就是說單個進程,需要頻繁的訪問數據庫。這個其實有兩個思路可以解決,第一種是把timeout的參數調的大一點其實就好了。這個沒錯,但是也存在一定安全和資源浪費,比如這個長連接會不會被非法佔用,寶貴的數據庫連接數是不是會被長時間佔用,這些都是問題。那麼第二個思路是,由一箇中間人來協調所有的連接,同時讓這些連接不會超時,同時也可以免去某一個進程需要頻繁交互,頻繁驗證握手等,給程序帶了很多等待時間。那麼這種中間人的技術就叫做連接池,它的作用就相當於一共有10個醫生坐班,連接池就是一個醫導(可以是人,也可以是醫院的信息化系統),事先都和這些醫生很熟,建立了信任的連接,那麼病患只要和這個醫導建立連接,掛號驗證身份,就能做完各種化驗,繼續找醫生看病,省卻了很多流程上的時間。那麼再數據庫的技術上有很多這些連接池的技術,比如DBUtils,PySQLpool等再python上使用比較頻繁的模塊。這次我們就以DBUtils來給大家講解一下。

1.先看一下大概的概念,對比一下醫導和連接池的類似概念。如圖上顯示的連接池在第一次驗證之後,把所有的連接都放在它的大池子裡,應用端不用每次都走一遍繁瑣的流程,如果要在一個交易或者業務邏輯裡頻繁增刪改查幾十次,那麼完全可以省下來之前這麼多步驟,應用速度大大提升。

微軟雲自主醫療保健手冊

2.那麼接下來, 用DBUtils來建立一個9個連接的連接池,數據庫timeout參數還是30s不變,然後我們同樣休眠60s,發現繼續使用conn1還是可以連接,說明數據庫連接池並沒有釋放掉原來的連接,而是緩存在了連接池之中。連接池一直保持這和數據庫的硬連接,這個“硬”連接是真正走過所有的握手協議身份驗證的,而應用和連接池的連接則是軟連接是放在一個緩存池中裡的。當然你還能定義有多少硬連接是在連接池建立完之後一直保留著的,這樣會對突發的軟連接有一定的幫助。

微軟雲自主醫療保健手冊

微軟雲自主醫療保健手冊

3.一旦設置了連接池,就比較完美解決了單進程的頻繁訪問問題了。那麼你可能會問,如果是多進程怎麼處理呢?連接池可以完美解決這個問題嗎?接下來我們來看看下一個場景。

第三種場景:多進程訪問數據庫

一般在顯示問題裡,資源都是比較緊俏的。資源不緊俏說的好聽是冗餘度高,防範黑天鵝,說的不好聽就是浪費,但是這個平衡點確實很難掌握。那麼我們現在討論的場景就是資源相當緊俏的數據庫連接,要被很多進程頻繁同時訪問。比如現在是流行病高發時期,醫院看呼吸道疾病的醫生可能只有10個人,但是同時要看病的患者可能成百上千,那麼怎麼樣才能讓這些心急火燎的病患能夠看病治療呢?那麼醫導這個系統可以記住所有來訪的病人,知道哪些可以先去做血液檢查,哪些在這個空隙,可以找醫生看片子,那麼10個醫生的效率得到了最有話。只需要醫導系統與這10個醫生連接,所有的病人信息都緩存在醫導這裡;而不需要病人直接和醫生建立連接,那麼效率就是等10個病人全部檢查完畢,才能看接下來的病人,效率會十分的緩慢。

1.現在我們先看一下, 如果不做任何共享連接的方式。也就是說到了連接上限就掐斷,所有應用被勸離。

微軟雲自主醫療保健手冊

2.先看一下目前Azure MySQL的設置的連接數上限是10(當然這個不是最大值,最大連接數隨著你選擇的實例大小而變化)

微軟雲自主醫療保健手冊

3.初始化連接池的時候,不選共享連接, 參數上Blocking放成False。啟動20個併發的線程

微軟雲自主醫療保健手冊

4.沒有共享等待連接機制的情況下,超出連接數的線程就報錯了。

微軟雲自主醫療保健手冊

5.那麼現在我們把等待緩存機制換上,那麼併發來的線程就能夠等待之前的線程釋放資源後,繼續使用有限的連接數。這樣就達到了一個緩存池的作用。同樣的道理,如果我們醫生醫院不夠大的時候,就可以建立很多簡易或者野外的醫院,隔離病房等,讓看病的病患先得到妥善安置,然後在按需就醫。

微軟雲自主醫療保健手冊

6.現在我們把緩存機制打開,把Blocking參數置成True。發現即使有20個進程同時併發,也會通過連接池緩存技術,妥善把所有進程完成,達到共享10個連接數的可能性。

微軟雲自主醫療保健手冊

場景總結

最後我們來總結一下前面三個場景。第一個場景是單進程非頻繁訪問,所以每一次訪問都需要做一次數據庫連接,會消耗一定資源和數據庫連接數量。那麼第二個場景是單進程,但是頻繁訪問,引入了數據庫連接池的概念,可以事先維護好一定數量的連接池,不用每次訪問都去建立一次連接,那麼頻繁訪問的速度得到了保證。第三種場景的問題是如果是多進程的訪問情況,連接數量會不夠,這個時候引入了連接池緩存等待機制,就很好的解決了高併發多進程的問題。

所以在什麼場景下選擇什麼樣的技術方案是至關重要的。

要解決數據庫連接或者看病難這種緊缺資源的問題,需要用到一些中間調劑人或者系統,那麼這個系統是用公平的輪詢機制,隨機數機制,還是帶有權重的機制,就涉及到資源分配的大問題了。設計系統的時候一定要把這些因素考慮進去,那麼願天下系統安穩,一切苦厄消散。

最後,提供本文技術參考指南及MySQL 連接池代碼供各位查閱:

DBUtils 用戶指南:

https://cito.github.io/DBUtils/UsersGuide.html#id2

代碼傳送門:

https://github.com/jurejoy/MySQLconnectionpool


分享到:


相關文章: