❶ 為什麼資料庫讀寫分離能提高資料庫的性能
讀寫分離主要目的是提高系統吞吐量。某些網站同一時間有大量的讀操作和較少的寫操作。同時,讀操作對數據的實時性要求並沒有那麼高。在此前提下,可以這么設計解決方案。
所以你問題里「數據仍然需要同步」這個理解是不對的。事實上,正是由於允許用戶讀到幾秒鍾甚至幾分鍾前的數據,才可以使用讀寫分離的。
所以這種方案其實就是以數據的時效性,換取了讀操作的吞吐率。
❷ 什麼叫讀寫分離讀是RAID幾寫又是RAID幾
讀寫分離(Read/Write Splitting)」,基本的原理是讓主資料庫處理事務性查詢,而從資料庫處理SELECT查詢。資料庫復制被用來把事務性查詢導致的變更同
步到集群中的從資料庫。
對於大訪問量的網站,一般會採用讀寫分離,比如ebay的讀寫比率是260:1,也就是大型的電子商務網站的。
網上看到說採用讀寫分離有如下工具:
1,oracle的logical standby
2, Quest公司的SharePlex
3, DSG公司的RealSync
如果你是網吧類應用:強烈建議你不要用無盤!!!!
必須有一名專業人員維護!三天兩頭的小問題 軟體游戲更新要你的命!
無盤伺服器的讀寫分離,很早就被提出來了。幾乎所有的商業無盤系統都會將讀寫分離作為提高無盤運行速度的有效途徑。可即使做了讀寫分離,系統性能也並
沒有得到顯著的提升。為什麼?因為他們分離錯了!該分離的沒有分離,而不該分離的卻又分離了!
現在市面上的無盤讀寫分離,都是將系統分區同游戲分區分開二個磁碟。殊不知,系統分區的磁碟讀寫負荷不知要大過游戲分區多少倍!為什麼這么說呢
?程序員都知道,程序一運行就會將自身完全載入內存了。雖然現在的游戲幾乎沒有不超過G大小的,但是,游戲主程序加上其需要調用的DLL文件,可能加起來
也就才幾十M而已,甚至更少!(大家可以運行一個大型游戲來看看它的內存使用量)。那另外那些幾乎超過游戲總大小百分之九十九的東西是什麼呢?不用說
大家都知道,是游戲必不可少的資源文件,比如:地圖、圖像、聲音等等。而游戲一般進去都會有等待載入的畫面,這里等待載入的東西,就是那些資源文件。
而這些資源文件載入後放在哪裡了?即使你系統有NG的內存容量,也不要指望游戲會將它放全部放在內存里。(不信你現在又可以看看游戲所佔用內存使用量)
。那是放哪裡了?那麼多寵大的游戲資源文件是放在哪裡了?去問個游戲程序員吧(問我也行啊,俺也是。。)。他會告訴你,放在頁面文件里了!!! 千
萬不要以為,游戲是邊運行邊從硬碟讀取文件的,游戲為了加快運行速度,都是將需要運行的文件預先載入入內存或是虛擬內存中的!而更多的是載入到虛擬內
存即頁面文件中,即使是幾G的內存,也是擺設。
感覺到恐怖吧!你以為你的系統分區磁碟幾乎沒做什麼事,其實它是最累的!游戲的讀取只需要進行一次,就是說載入一次,但是載入以後的東西是放在頁
面文件中的,游戲對頁面文件的讀取是非常頻繁的!可現在的無盤全弄反了,將系統分區磁碟弄成個普通IDE,將游戲分區弄成陣列。好武器沒有用到該用的地
方。
玩游戲會卡?幾乎每一種技術的無盤系統,玩游戲都會覺得有卡的時候。看看你客戶機的頁面文件大小吧,最小都有二三百M吧,幾十台機每台都來個幾百M
的讀寫量,呵呵,你想想,你那個又要做系統又要放頁面文件而且「待遇又不好」的磁碟,它磁頭會忙成什麼樣子!
我已經分析的很清楚了,該分離的應該是頁面文件!而游戲可以分,也可以不分。對於本身帶有緩沖功能的無盤系統,大型游戲應該都放在無盤伺服器上。
而不常用的硬碟游戲,網路游戲就可以放在網路的其它機上面。(共享或是虛擬磁碟方式)。
打開多個IE卡,最小化IE卡,啟動QQ卡,退出遊戲還是卡。這些都是對頁面文件大量讀寫的時候。將頁面文件分離出來吧!專門弄個硬碟提供頁面文件的讀
寫。這樣,系統更穩定、游戲更流暢!
怎麼解決這個惱人的頁面文件?暫時的方法,你可以升級您的系統分區的磁碟硬體,會有點改善,但解決不了根本。因為頁面文件是同系統分區放在一個磁
盤裡面的,而用戶與操作系統的交互是非常頻繁的,就是說,依現在的磁碟讀寫速度,又要滿足頁面文件的讀寫,又要不影響用戶同系統的交互,是做不到的。
另外一個解決方法,就是使用SetPageFile.exe軟體。
RAID是英文Rendant Array of Independent Disks的縮寫,翻譯成中文意思是「獨立磁碟冗餘陣列」,有時也簡稱磁碟陣列(Disk Array)。
簡單的說,RAID是一種把多塊獨立的硬碟(物理硬碟)按不同的方式組合起來形成一個硬碟組(邏輯硬碟),從而提供比單個硬碟更高的存儲性能和提供數
據備份技術。組成磁碟陣列的不同方式成為RAID級別(RAID Levels)。數據備份的功能是在用戶數據一旦發生損壞後,利用備份信息可以使損壞數據得以恢復
,從而保障了用戶數據的安全性。在用戶看起來,組成的磁碟組就像是一個硬碟,用戶可以對它進行分區,格式化等等。總之,對磁碟陣列的操作與單個硬碟一
模一樣。不同的是,磁碟陣列的存儲速度要比單個硬碟高很多,而且可以提供自動數據備份。
RAID技術的兩大特點:一是速度、二是安全,由於這兩項優點,RAID技術早期被應用於高級伺服器中的SCSI介面的硬碟系統中,隨著近年計算機技術的發展
,PC機的CPU的速度已進入GHz 時代。IDE介面的硬碟也不甘落後,相繼推出了ATA66和ATA100硬碟。這就使得RAID技術被應用於中低檔甚至個人PC機上成為
可能。RAID通常是由在硬碟陣列塔中的RAID控制器或電腦中的RAID卡來實現的。
RAID技術經過不斷的發展,現在已擁有了從 RAID 0 到 6 七種基本的RAID 級別。另外,還有一些基本RAID級別的組合形式,如RAID 10(RAID 0與RAID 1
的組合),RAID 50(RAID 0與RAID 5的組合)等。不同RAID 級別代表著不同的存儲性能、數據安全性和存儲成本。但我們最為常用的是下面的幾種RAID形式。
(1) RAID 0
RAID 0又稱為Stripe(條帶化)或Striping,它代表了所有RAID級別中最高的存儲性能。RAID 0提高存儲性能的原理是把連續的數據分散到多個磁碟上存取
,這樣,系統有數據請求就可以被多個磁碟並行的執行,每個磁碟執行屬於它自己的那部分數據請求。這種數據上的並行操作可以充分利用匯流排的帶寬,顯著提
高磁碟整體存取性能。
例如系統向三個磁碟組成的邏輯硬碟(RADI 0 磁碟組)發出的I/O數據請求被轉化為3項操作,其中的每一項操作都對應於一塊物理硬碟。我們可以清楚的看
到通過建立RAID 0,原先順序的數據請求被分散到所有的三塊硬碟中同時執行。從理論上講,三塊硬碟的並行操作使同一時間內磁碟讀寫速度提升了3倍。 但由
於匯流排帶寬等多種因素的影響,實際的提升速率肯定會低於理論值,但是,大量數據並行傳輸與串列傳輸比較,提速效果顯著顯然毋庸置疑。
RAID 0的缺點是不提供數據冗餘,因此一旦用戶數據損壞,損壞的數據將無法得到恢復。
RAID 0具有的特點,使其特別適用於對性能要求較高,而對數據安全不太在乎的領域,如圖形工作站等。對於個人用戶,RAID 0也是提高硬碟存儲性能的絕
佳選擇。
(2) RAID 1
RAID 1又稱為Mirror或Mirroring(鏡像),它的宗旨是最大限度的保證用戶數據的可用性和可修復性。 RAID 1的操作方式是把用戶寫入硬碟的數據百分之
百地自動復制到另外一個硬碟上。
當讀取數據時,系統先從RAID 0的源盤讀取數據,如果讀取數據成功,則系統不去管備份盤上的數據;如果讀取源盤數據失敗,則系統自動轉而讀取備份
盤上的數據,不會造成用戶工作任務的中斷。當然,我們應當及時地更換損壞的硬碟並利用備份數據重新建立Mirror,避免備份盤在發生損壞時,造成不可挽回
的數據損失。
由於對存儲的數據進行百分之百的備份,在所有RAID級別中,RAID 1提供最高的數據安全保障。同樣,由於數據的百分之百備份,備份數據佔了總存儲空間
的一半,因而Mirror(鏡像)的磁碟空間利用率低,存儲成本高。
Mirror雖不能提高存儲性能,但由於其具有的高數據安全性,使其尤其適用於存放重要數據,如伺服器和資料庫存儲等領域.
( 3) RAID 0+1
正如其名字一樣RAID 0+1是RAID 0和RAID 1的組合形式,也稱為RAID 10。
以四個磁碟組成的RAID 0+1為例,其數據存儲方式:RAID 0+1是存儲性能和數據安全兼顧的方案。它在提供與RAID 1一樣的數據安全保障的同時,也提供
了與RAID 0近似的存儲性能。
由於RAID 0+1也通過數據的100%備份功能提供數據安全保障,因此RAID 0+1的磁碟空間利用率與RAID 1相同,存儲成本高。
RAID 0+1的特點使其特別適用於既有大量數據需要存取,同時又對數據安全性要求嚴格的領域,如銀行、金融、商業超市、倉儲庫房、各種檔案管理等。
(4) RAID 3
RAID 3是把數據分成多個「塊」,按照一定的容錯演算法,存放在N+1個硬碟上,實際數據佔用的有效空間為N個硬碟的空間總和,而第N+1個硬碟上存儲的數
據是校驗容錯信息,當這N+1個硬碟中的其中一個硬碟出現故障時,從其它N個硬碟中的數據也可以恢復原始數據,這樣,僅使用這N個硬碟也可以帶傷繼續工作
(如採集和回放素材),當更換一個新硬碟後,系統可以重新恢復完整的校驗容錯信息。由於在一個硬碟陣列中,多於一個硬碟同時出現故障率的幾率很小,所
以一般情況下,使用RAID3,安全性是可以得到保障的。與RAID0相比,RAID3在讀寫速度方面相對較慢。使用的容錯演算法和分塊大小決定RAID使用的應用場合,
在通常情況下,RAID3比較適合大文件類型且安全性要求較高的應用,如視頻編輯、硬碟播出機、大型資料庫等.
(5) RAID 5
RAID 5 是一種存儲性能、數據安全和存儲成本兼顧的存儲解決方案。 以四個硬碟組成的RAID 5為例,其數據存儲方式:,P0為D0,D1和D2的奇偶校驗信
息,其它以此類推。由圖中可以看出,RAID 5不對存儲的數據進行備份,而是把數據和相對應的奇偶校驗信息存儲到組成RAID5的各個磁碟上,並且奇偶校驗信
息和相對應的數據分別存儲於不同的磁碟上。當RAID5的一個磁碟數據發生損壞後,利用剩下的數據和相應的奇偶校驗信息去恢復被損壞的數據。
RAID 5可以理解為是RAID 0和RAID 1的折衷方案。RAID 5可以為系統提供數據安全保障,但保障程度要比Mirror低而磁碟空間利用率要比Mirror高。RAID
5具有和RAID 0相近似的數據讀取速度,只是多了一個奇偶校驗信息,寫入數據的速度比對單個磁碟進行寫入操作稍慢。同時由於多個數據對應一個奇偶校驗信
息,RAID 5的磁碟空間利用率要比RAID 1高,存儲成本相對較低。
RAID級別的選擇有三個主要因素:可用性(數據冗餘)、性能和成本。如果不要求可用性,選擇RAID0以獲得最佳性能。如果可用性和性能是重要的而成
本不是一個主要因素,則根據硬碟數量選擇RAID 1。如果可用性、成本和性能都同樣重要,則根據一般的數據傳輸和硬碟的數量選擇RAID3、RAID5。
❸ Oracle的讀寫分離在應用程序層面上應該怎麼做
oracle資料庫本身就是讀寫分離的。如果是防止臟讀,那麼直接用一個庫就可以了。
如果你是想把大查詢放到從庫,實時業務放主庫,防止查詢影響主庫效率,那最簡單的就是把你的查詢鏈接資料庫連到從庫上,甚至可以配一個server,先嘗試連從庫,從庫連不上連主庫。
❹ 資料庫的讀寫分離資料庫是怎麼同步的
mysql
最常用的主從復制就是讀寫分離的功能
數據有修改,會通過網路將執行的內容傳輸到從庫,追加到從庫的重做日誌(replay-bin),然後再通過重做日誌還原主庫的操作以達到同步的效果
---------------------------------------
oracle
常用的讀寫分離方案有DG(備庫可讀)
操作寫入archivelog,再通過網路傳輸到備庫,備庫再用archivelog還原數據,已到達同步的目的。
❺ 分布式系統中應用程序怎麼實現資料庫讀寫分離
本文實例分析了Yii實現MySQL多資料庫和讀寫分離的方法。分享給大家供大家參考。具體分析如下: Yii Framework是一個基於組件、用於開發大型 Web 應用的高性能 PHP 框架。Yii提供了今日Web 2.0應用開發所需要的幾乎一切功能,也是最強大的框架之一,下文我們來介紹Yii實現MySQL多庫和讀寫分離的方法 前段時間為SNS產品做了架構設計,在程序框架方面做了不少相關的壓力測試,最終選定了YiiFramework,至於為什麼沒選用公司內部的 PHP框架,其實理由很充分,公司的框架雖然是"前輩"們辛苦的積累,但畢竟不夠成熟,沒有大型項目的歷練,猶如一個涉世未深的年輕小伙。Yii作為一個 頗有名氣開源產品,必定有很多人在使用,意味著有一批人在維護,而且在這之前,我也使用Yii開發過大型項目,Yii的設計模式和它的易擴展特性足以堪當重任。 SNS同一般的社交產品不同的就是它最終要承受大並發和大數據量的考驗,架構設計時就要考慮這些問題, web分布式、負載均衡、分布式文件存儲、MySQL分布式或讀寫分離、NoSQL以及各種緩存,這些都是必不可少的應用方案,本文所講的就是MySQL 分庫和主從讀寫分離在Yii的配置和使用。 Yii默認是不支持讀寫分離的,我們可以利用Yii的事件驅動模式來實現MySQL的讀寫分離。 Yii提供了一個強大的CActiveRecord資料庫操作類,通過重寫getDbConnection方法來實現資料庫的切換,然後通過事件 beforeSave、beforeDelete、beforeFind 來實現讀寫伺服器的切換,還需要兩個配置文件dbconfig和modelconfig分別配置資料庫主從伺服器和model所對應的資料庫名稱,附代碼 DBConfig.php文件如下: 復制代碼 代碼如下:<?php return array( 'passport' => array( 'write' => array( 'class' => 'CDbConnection', 'connectionString' => 'mysql:host=10.1.39.2;dbname=db1′, 'emulatePrepare' => true, //'enableParamLogging' => true, 'enableProfiling' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8′, 'schemaCachingDuration'=>3600, ), 'read' => array( array( 'class' => 'CDbConnection', 'connectionString' => 'mysql:host=10.1.39.3;dbname=db1, 'emulatePrepare' => true, //'enableParamLogging' => true, 'enableProfiling' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8′, 'schemaCachingDuration'=>3600, ), array( 'class' => 'CDbConnection', 'connectionString' => 'mysql:host=10.1.39.4;dbname=db3′, 'emulatePrepare' => true, //'enableParamLogging' => true, 'enableProfiling' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8′, 'schemaCachingDuration'=>3600, ), ), ), ); ModelConfig.php如下: 復制代碼 代碼如下:<?php return array( //key為資料庫名稱,value為Model 'passport' => array('User','Post'), 'microblog' => array('…'), ); ?> ActiveRecord.php如下: 復制代碼 代碼如下:/** * 基於CActiveRecord類的封裝,實現多庫和主從讀寫分離 * 所有Model都必須繼承些類. * */ class ActiveRecord extends CActiveRecord { //model配置 public $modelConfig = ''; //資料庫配置 public $dbConfig = ''; //定義一個多資料庫集合 static $dataBase = array(); //當前資料庫名稱 public $dbName = ''; //定義庫類型(讀或寫) public $dbType = 'read'; //'read' or 'write' /** * 在原有基礎上添加了一個dbname參數 * @param string $scenario Model的應用場景 * @param string $dbname 資料庫名稱 */ public function __construct($scenario='insert', $dbname = '') { if (!empty($dbname)) $this->dbName = $dbname; parent::__construct($scenario); } /** * 重寫父類的getDbConnection方法 * 多庫和主從都在這里切換 */ public function getDbConnection() { //如果指定的資料庫對象存在則直接返回 if (self::$dataBase[$this->dbName]!==null) return self::$dataBase[$this->dbName]; if ($this->dbName == 'db'){ self::$dataBase[$this->dbName] = Yii::app()->getDb(); }else{ $this->changeConn($this->dbType); } if(self::$dataBase[$this->dbName] instanceof CDbConnection){ self::$dataBase[$this->dbName]->setActive(true); return self::$dataBase[$this->dbName]; } else throw new CDbException(Yii::t('yii','Model requires a "db" CDbConnection application component.')); } /** * 獲取配置文件 * @param unknown_type $type * @param unknown_type $key */ private function getConfig($type="modelConfig",$key="){ $config = Yii::app()->params[$type]; if($key) $config = $config[$key]; return $config; } /** * 獲取資料庫名稱 */ private function getDbName(){ if($this->dbName) return $this->dbName; $modelName = get_class($this->model()); $this->modelConfig = $this->getConfig('modelConfig'); //獲取model所對應的資料庫名 if($this->modelConfig)foreach($this->modelConfig as $key=>$val){ if(in_array($modelName,$val)){ $dbName = $key; break; } } return $dbName; } /** * 切換資料庫連接 * @param unknown_type $dbtype */ protected function changeConn($dbtype = 'read'){ if($this->dbType == $dbtype && self::$dataBase[$this->dbName] !== null) return self::$dataBase[$this->dbName]; $this->dbName = $this->getDbName(); if(Yii::app()->getComponent($this->dbName.'_'.$dbtype) !== null){ self::$dataBase[$this->dbName] = Yii::app()->getComponent($this->dbName.'_'.$dbtype); return self::$dataBase[$this->dbName]; } $this->dbConfig = $this->getConfig('dbConfig',$this->dbName); //跟據類型取對應的配置(從庫是隨機值) if($dbtype == 'write'){ $config = $this->dbConfig[$dbtype]; }else{ $slavekey = array_rand($this->dbConfig[$dbtype]); $config = $this->dbConfig[$dbtype][$slavekey]; } //將資料庫配置加到component中 if($dbComponent = Yii::createComponent($config)){ Yii::app()->setComponent($this->dbName.'_'.$dbtype,$dbComponent); self::$dataBase[$this->dbName] = Yii::app()->getComponent($this->dbName.'_'.$dbtype); $this->dbType = $dbtype; return self::$dataBase[$this->dbName]; } else throw new CDbException(Yii::t('yii','Model requires a "changeConn" CDbConnection application component.')); } /** * 保存數據前選擇 主 資料庫 */ protected function beforeSave(){ parent::beforeSave(); $this->changeConn('write'); return true; } /** * 刪除數據前選擇 主 資料庫 */ protected function beforeDelete(){ parent::beforeDelete(); $this->changeConn('write'); return true; } /** * 讀取數據選擇 從 資料庫 */ protected function beforeFind(){ parent::beforeFind(); $this->changeConn('read'); return true; } /** * 獲取master庫對象 */ public function dbWrite(){ return $this->changeConn('write'); } /** * 獲取slave庫對象 */ public function dbRead(){ return $this->changeConn('read'); } } 這是我寫好的類,放在components文件夾里,然後所有的Model都繼承ActiveRecord類就可以實現多庫和主從讀寫分離了,至於如何支持原生的SQL也同時使用讀寫分離,此類都已經實現。 希望本文所述對大家基於Yii框架的PHP程序設計有所幫助。
❻ 資料庫讀寫分離同步延時問題怎麼解決
業務發展初期,資料庫的壓力相對較小,這時候使用單獨一個庫就可以。
引出的問題:如果資料庫出現故障,我們的業務就不能使用,只能說是停機重啟修復故障。
由於單體帶出的問題,這時候我們就需要加一個備用庫,緊急情況可以用備庫頂上,相當於加一個替補隊員。
通過MySQL自帶的主從同步機制,就可以放我們的替補隊員上線。
當正式隊員(主庫)發生故障,我們就可以人工讓其下線,讓替補隊員(備庫)頂上。
引出的問題:隨著業務大規模爆發,主庫的壓力過大,我們就想讓備庫承擔起更大的責任來。
讀寫分離架構本質也就是主備架構,與主備架構沒有本質區別,就是在主備架構的基礎上,增加一層對讀寫請求的處理,使其能夠更大程度上利用備用庫為我們分擔一些讀的壓力。
讀寫分離架構,需要在中間加一層控制讀寫請求的路由
分庫分表的本質上是切分數據,是由於數據量級的提升,不對數據切分會嚴重影響資料庫讀寫性能。
甚至是如果不切分,磁碟、內存、CPU無法承載這樣的壓力,資料庫隨時在奔潰的邊緣。
分庫分表與前三者是有本質區別的,分庫分表後每一個庫分片都可以採取以上三種方式的任意一種,可以是單體分片,也可以是主備分片,也可以是做了讀寫分離的分片。
分庫分表和前三者中的一種是共生的關系。
不知道如何進行分庫分表設計的可以讀我之前的這篇文章《收好這份武林秘籍,讓你分庫分表再無煩惱》
在應用程序和資料庫之間增加代理層,代理層接收應用程序對資料庫的請求,根據不同請求類型轉發到不同的實例,實現讀寫分離的同時還可以實現負載均衡(讀請求按照負載均衡的規則傳入各個從節點)。
代理也就是藉助中間件的方式,控制不同類型請求,進入不同的資料庫。
目前常用的mysql的讀寫分離中間件有:
在程序中進行控制,我們利用持久層框架的攔截器實現,動態路由不同數據源。
利用Sharding-JDBC也可以實現
實現思路:
主從復制模式,一般都是非同步寫數據到從庫,當然這個非同步也可以設置為同步,只有當從庫寫完成,主庫上的寫請求才能返回。
這種方案是最佳單也是最有效的一種,但也是性能最差的一種,尤其是有大量從庫的情況下,嚴重影響請求效率。
寫請求時緩存記錄一個key,這個key的失效時間設置為主從同步的延時,讀請求的時候先去緩存中確認是否存在key,如果key存在說明發生了寫請求,數據未同步到從庫,這時走主庫即可,若不存在這個key,直接走從庫的查詢即可。
中間件應該也是可以判斷是否同步完成,與使用緩存記錄類似。
這種方案最大的弊端是引入了緩存,系統復雜度上升。
對於一些特殊的業務場景,採用強制讀主庫。
弊端,需要把每一個這種情況都找出來,設置成強制走主庫。
MySQL 在執行完事務後,會將該事務的 GTID 會給客戶端,然後客戶端可以使用該命令去要執行讀操作的從庫中執行,等待該 GTID,等待成功後,再執行讀操作;如果等待超時,則去主庫執行讀操作,或者再換一個從庫執行上述流程。
MariaDB 的 MaxScale 就是使用該方案,MaxScale 是 MariaDB 開發的一個資料庫智能代理服務(也支持 MySQL),允許根據資料庫 SQL 語句將請求轉向目標一個到多個伺服器,可設定各種復雜程度的轉向規則。
有延遲就有延遲,對數據強一致性要求不高的場景可以放任不管。