用c++寫一個數據庫連接池
數據庫連接池是為了提高數據庫連接的性能,進行連接復用
對于復雜數據庫進行大量引用的場景下就會出現訪問瓶頸
常見的兩種解決方法就是:為了減少磁盤 I/O的次數,在數據庫和服務器的應用中間加一層 緩存數據庫(例如:Redis、Memcache);
或者就是增加連接池,來減少高并發情況下大量 TCP三次握手、MySQL Server連接認證、MySQL Server關閉連接回收資源和TCP四次揮手 所耗費的性能。
機制解讀:連接池呢就是為數據庫連接建立一個緩沖池。
1:從連接池獲取或創建可用連接
2:使用完畢之后,把連接返回給連接池
3:在系統關閉前,斷開所有連接并釋放連接占用的系統資源
4:能夠處理無效連接,限制連接池中的連接總數不低于或者不超過某個限定值
池子里四個基本屬性:
初始連接量(init_size): 表示連接池事先會和MySQL服務器創建init_size個connection連接,當應用發起MySQL訪問時,不用再創建和MySQL服務器新的連接,直接從連接池中獲取一個可用的連接就可以,使用完成后,并不去釋放connection,而是把當前connection再歸還到連接池當中。
大連接(max_size): 當并發訪問MySQL服務器的請求增多時,初始連接量已經不夠使用了,此時會根據新的請求數量去創建更多的連接給應用去使用,但是新創建的連接數量上限是max_size,不能無限制的創建連接。因為每個連接都會占用一個socket資源,一般連接池和服務器程序是部署在一臺主機上的,如果連接池占用過多的socket資源,那么服務器就不能接收更多的客戶端請求了。當這些連接使用完成后,再次歸還到連接池當中來維護。
大空閑時間(max_idle_time): 當訪問MySQL的并發請求多了以后,連接池里面的連接數量會動態增加,上限是max_size個,當這些連接用完再次歸還到連接池當中。如果在指定的max_idle_time里面,這些新增加的連接都沒有被再次使用過,那么新增加的這些連接資源就要被回收,只需要保持初始連接量init_size個連接就可以了。
連接超時時間(connection_timeout): 當MySQL的并發請求量過大,連接池中的連接數量已經到達max_size了,而此時沒有空閑的連接可供使用,那么此時應用無法從連接池獲取連接,它通過阻塞的方式等待獲取連接的時間如果超過connection_timeout時間,那么連接失敗,無法訪問數據庫。
技術點的分析:
通過預先創建一定數量的連接,放到一個池子。當客戶端有請求時,服務器端需要與mysql進行交互,那么只需要從池子里取出一個連接,當操作完成再將連接放到連接池中。如此以來避免了頻繁的創建和銷毀線程。
1.池子只需要一個就夠用了,一個池子里有很多連接了。所以對于線程池這個類而言使用單例模式最為合適。用c++11內部靜態變量這種線程安全的方法做的
2.池子里面連接存在類似隊列這種容器里面,直接用queue了,每次新的連接從隊尾進去,隊頭的連接用完之后,如果空閑太久,占資源就需要把他銷毀掉
3.進行數據庫連接的話需要mysql相關的api,用c++的話,就把這些api封裝一下,具體常用的api之前有寫過一篇博客?C/C++鏈接mysql_
這封裝成一個數據庫連接類,里面就是伴隨著數據庫的初始化,查詢,更新,事務的一系列操作。連接池里面隊列放的就是這一個個數據庫連接的類對象
4.需要訪問數據庫的線程從連接池里面取出連接,和給池子里添加新連接的線程構成了一個典型的生產者消費者,用條件變量加+互斥鎖保證同步,cas原子操作 定義一個連接池內的連接數量,用來當做我們生產和消費線程工作都要參考的變量,變量必須保證其原子性
5.對于獲取連接池中的連接來說,用戶只需要關心使用,去連接池里直接獲取連接并且使用即可,并不用關心連接的生成和銷毀,并且,對于使用完的連接來說,為了達到復用的目的,我們并不希望把它釋放掉,而是使用完之后將其放回到連接池中供其他消費者使用,這個我們就可以使用智能指針來完成用lambda表達式定制連接釋放的功能,(把連接重新還給池子);重新放進連接池呢就是重新push到隊列池子里,不過要更新一下時間戳,記錄每個連接的存活時間
6.連接池實現自動管理連接數(不夠時創建連接,銷毀空閑時間較長的連接)
需要通過兩個子線程,因為主線程不能阻塞在這個地方,所以通過兩個子線程取完成,設置線程分離
一個子線程用來不夠時自動創建連接:
? 線程池維護了兩個數據,一個最小連接數,一個大連接數
一個子線程用來銷毀空閑時間較長的連接:
? 大概實現思路:從隊頭取出連接,并將該連接的空閑時長與設定的大空閑時長比較,如果大于等于就從隊列中彈出并銷毀
7.利用Jsoncpp庫去解析json文件,配置環境
整個流程原理大概就這樣
當時做了四組壓力測試:
一個線程去連接數據庫每次插一條數據,測試5000下
用連接池省了和數據庫建立連接的損耗?
多線程的話,測了五個線程(好比五個用戶)不斷的去同時連接數據庫,每次連接插入一條數據,一共插5000條
接上連接池,效率更高
測了5000條數據,能很明顯的看到單線程多線程下使用連接池,訪問速度有著明顯的提高
總結:深入了解了池化的技術,可以和線程池配套,作為一個不錯的項目
源碼放在這了:Xw-oorik
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
本文題目:C++手撕連接池-創新互聯
路徑分享:http://newbst.com/article2/hhhoc.html
成都網站建設公司_創新互聯,為您提供網站排名、搜索引擎優化、定制網站、品牌網站建設、域名注冊、外貿網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯