在mysql的文章專題中我寫過了關於傳統關係型資料庫的一些優化思路,整體來說,通過優化之後能夠提升程式存取資料庫的計算效能。但是還是有一些情況,即便是優化之後,使用傳統關係型資料庫無法解決的,比如。
列式資料庫是以列相關儲存架構進行資料儲存的資料庫,主要適合與批次資料處理和即席查詢。相對應的是行式資料庫,資料以行相關的儲存體系架構進行空間分配,主要適合與小批次的資料處理,常用於聯機事務型資料處理。列式資料庫以行、列的二維表的形式儲存資料,但是卻以一維字串的方式儲存,例如以下的一個表:
EmpId |
Lastname |
Firstname |
Salary |
---|---|---|---|
1 | Smith | Joe | 40000 |
2 | Jones | Mary | 50000 |
3 | Johnson | Cathy | 44000 |
這個簡單的表包括員工程式碼(EmpId), 姓名欄位(Lastname and Firstname)及工資(Salary).
這個表儲存在電腦的記憶體(RAM)和儲存(硬碟)中。雖然記憶體和硬碟在機制上不同,電腦的作業系統是以同樣的方式儲存的。資料庫必須把這個二維表儲存在一系列一維的「位元組」中,又作業系統寫到記憶體或硬碟中。
行式資料庫把一行中的資料值串在一起儲存起來,然後再儲存下一行的資料,以此類推。
1,Smith,Joe,40000;2,Jones,Mary,50000;3,Johnson,Cathy,44000;
列式資料庫把一列中的資料值串在一起儲存起來,然後再儲存下一列的資料,以此類推。
1,2,3;Smith,Jones,Johnson;Joe,Mary,Cathy;40000,50000,44000;
這是一個簡化的說法。
列式資料庫的代表包括:Sybase IQ,ParAccel, Sand/DNA Analytics和 Vertica。
傳統的行式資料庫,是按照行儲存的,維護大量的索引和物化檢視無論是在時間(處理)還是空間(儲存)方面成本都很高。而列式資料庫恰恰相反,列式資料庫的資料是按照列儲存,每一列單獨存放,資料即是索引。只存取查詢涉及的列,大大降低了系統I/O,每一列由一個線來處理,而且由於資料型別一致,資料特徵相似,極大方便壓縮。
最後盧東明很務實的指出,沒有萬能的資料庫,Sybase IQ也並非萬能,只不過給DBA們的工具箱裡提供更多的選擇,DBA需根據自己的應用場景自行選擇。
在資料倉儲領域,列式資料庫和傳統的行式資料庫有何差別呢?列式資料庫和行式資料庫的擁護者均認為結合這兩種技術的混合資料庫是個不錯的想法。
行式資料庫擅長隨機讀操作,列式資料庫則更擅長大批次資料量查詢,而混合資料庫則試圖同時包含這兩種技術的優點,在災難恢復環境中,資料要麼按列式儲存,要麼按行式儲存。
未來將是列式資料庫的天下,行資料庫和混合型資料庫都將漸漸消亡,原因如下:資料增長速度很快,對儲存裝置(主記憶體和SSD)的需求也將不斷上升,隨著主記憶體和SSD中壓縮列所佔百分比的提高,列式資料庫隨機讀的弱點反而變成了優點,這樣列式資料庫不管是應付聯機事務處理,還是大批次更新或大型報表需要執行的複雜查詢都能應付自如。對於更新操作而言,列式資料庫和行式資料庫在這方面已經沒有多大差距了,因為大部分更新操作只會影響到一行中的一到三列(欄位),同時,大部分更新操作影響的是最近的資料,因此主記憶體/SSD快取中資料會越來越多。對於插入和刪除操作而言,先在記憶體中快速更新索引,然後再寫入磁碟,這意味著在I/O密集型情況下也不會有明顯的效能下降。對線上備份而言,按列儲存方法壓縮資料後備份時間視窗將會更短。
對今天的資料倉儲而言,列式資料庫的效能和傳統行資料庫相比,根本不在一個數量級上,列式資料庫已經得到了廣泛的認可和使用(Sybase IQ已經有十年曆史,也出現了一些新興列式資料庫公司,如Vertica),資料庫巨人Oracle也按捺不住,在其Exadata資料庫機中也加入了按列儲存選擇,IBM則提供了一個列式專用裝置,它可以確定什麼資料該按列儲存,什麼資料該按行儲存,然後將事務分流到相應的裝置。
列式資料庫從一開始就是面向巨量資料環境下資料倉儲的資料分析而產生,它跟行式資料庫相比當然也有一些前提條件和優缺點.
列式資料庫優點:
缺點:
一個常見的誤區認為如果每次掃描較多行或者全列全表掃描的時候,行式資料庫比列式資料庫更有優勢. 事實上這只是行式資料庫認識上的一個誤區,即認為列式資料庫的主要優勢在於其列分開儲存,而忽略了列式資料庫上面提到的其他幾大特徵,這個才是列式資料庫高效能的核心.
MongoDB是一個介於關聯式資料庫和非關聯式資料庫之間的產品,是非關聯式資料庫當中功能最豐富,最像關聯式資料庫的。他支援的資料結構非常鬆散,是類似json的bjson格式,因此可以儲存比較複雜的資料型別。Mongo最大的特點是他支援的查詢語言非常強大,其語法有點類似於物件導向的查詢語言,幾乎可以實現類似關聯式資料庫單表查詢的絕大部分功能,而且還支援對資料建立索引。
整體架構:
內部架構:
它的特點是高效能、易部署、易使用,儲存資料非常方便。主要功能特性有:
面向集合儲存,易儲存物件型別的資料。
模式自由。
支援動態查詢。
支援完全索引,包含內部物件。
支援查詢。
支援複製和故障恢復。
使用高效的二進位制資料儲存,包括大型物件(如視訊等)。
自動處理碎片,以支援雲端計算層次的擴充套件性
支援RUBY,PYTHON,JAVA,C++,PHP等多種語言。
檔案儲存格式為BSON(一種JSON的擴充套件)
可通過網路存取
所謂「面向集合」(Collenction-Orented),意思是資料被分組儲存在資料集中,被稱為一個集合(Collenction)。每個 集合在資料庫中都有一個唯一的標識名,並且可以包含無限數目的檔案。集合的概念類似關係型資料庫(RDBMS)裡的表(table),不同的是它不需要定 義任何模式(schema)。
模式自由(schema-free),意味著對於儲存在mongodb資料庫中的檔案,我們不需要知道它的任何結構定義。如果需要的話,你完全可以把不同結構的檔案儲存在同一個資料庫裡。
儲存在集合中的檔案,被儲存為鍵-值對的形式。鍵用於唯一標識一個檔案,為字串型別,而值則可以是各中複雜的檔案型別。我們稱這種儲存形式為BSON(Binary Serialized dOcument Format)。
MongoDB伺服器端可執行在Linux、Windows或OS X平臺,支援32位元和64位元應用,預設埠為27017。推薦執行在64位元平臺,因為MongoDB
在32位元模式執行時支援的最大檔案尺寸為2GB。
MongoDB把資料儲存在檔案中(預設路徑為:/data/db),為提高效率使用記憶體對映檔案進行管理。
很多企業都需要處理來自多個資料來源的複雜資料,因此需要利用資料庫管理系統來儲存和管理資料。現在,有很多不同型別的資料庫系統,而找到一個正確的資料庫不是一件容易的事。這需要考慮業務需求,以便選擇正確的資料庫管理系統。
企業使用關聯式資料庫管理系統(RDBMS)來儲存和管理他們的資料。然而,這些系統無法處理海量的複雜資料,無法滿足當今資料庫使用者的需求。因此,很多企業都在尋找能夠在保持傳統資料庫系統重要特性的同時,也能提供可伸縮性、可用性和高效能的資料庫系統。資料庫軟體供應商也已經確定了這一需求,並開發了NewSQL資料庫來彌補傳統資料庫系統的缺陷。
NewSQL資料庫在不放棄傳統資料庫優勢的前提下解決了問題。NewSQL關聯式資料庫管理系統為OLTP提供了與NoSQL系統相同的可伸縮效能,在保證傳統資料庫系統的ACID的同時,也能處理線上事務的讀寫工作負載。NoSQL資料庫使用的資料結構與關聯式資料庫中使用的資料結構不同,這使得NoSQL資料庫中的某些操作更快。
NewSQL資料庫是現代SQL資料庫,它解決了與傳統聯機事務處理(OLTP)RDBMS相關的一些主要問題。它們在保持傳統資料庫管理系統優點的同時,力求實現NoSQL資料庫的可伸縮性和高效能。換句話說,NewSQL資料庫是一種特殊的關聯式資料庫系統,它結合了傳統資料庫OLTP 和NoSQL的高效能和可伸縮性。它們保持了傳統DBMS的ACID(原子性、一致性、隔離性和永續性)。ACID事務特性確保了完整的業務流程、並行事務、系統故障或錯誤時的資料完整性,以及事務前後的一致性。
NewSQL資料庫在內部設計方面有所不同,但它們都是執行在SQL上的rdbms。它們使用SQL來接收新資訊,同時執行許多事務,並修改資料庫的內容。NewSQL系統的主要包括新的技術架構、透明的資料分片中介軟體、SQL引擎和資料庫即服務(DBaaS)。
分割區/分片:幾乎所有的NewSQL資料庫管理系統都是通過將資料庫劃分為不同的子集(稱為分割區或分片)來擴充套件的。資料庫中的表被水平地分割成幾個分片,這些分片的邊界基於列值來劃分,來自不同表的相關片段被連線以建立分割區。
副本: 此功能允許資料庫使用者建立和維護資料庫以及副本。資料庫的副本儲存在與主站相連線的遠端站點或距離很遠的站點。使用者可以同時更新副本,也可以更新一個節點並將結果狀態轉移到其他副本
輔助索引(二級索引): 輔助索引允許資料庫使用者通過使用主鍵以外的其他值有效地存取資料庫記錄。
並行控制: 此功能可解決多使用者系統中當多個使用者同時存取或修改資料時可能出現的問題。NewSQL系統使用此功能來確保同步事務,同時保持資料完整性。
故障恢復:NewSQL資料庫有一種故障恢復的機制,使它們能夠在系統崩潰時恢復資料到一致的狀態。
其中一些好處包括:
Vitess(開源)
Vitess 是一個分散式 MySQL 工具集,它可以自動分片儲存 MySQL 資料表,將單個 SQL 查詢改寫為分散式傳送到多個 MySQL Server 上,支援行快取(比 MySQL 本身快取效率高)與複製容錯等。Vitess 4.0 中有許多改進,可以使新使用者更容易使用,可以很容易的在k8s上部署Vitess,從單一的 MySQL 或 MariaDB 遷移到Vitess 成為可能,而應用對此有所感知。
CockroachDB(免費)
CockroachDB (蟑螂資料庫)是一個可伸縮的、支援地理位置處理、支援事務處理的資料儲存系統。CockroachDB 提供兩種不同的的事務特性,包括快照隔離(snapshot isolation,簡稱SI)和順序的快照隔離(SSI)語意,後者是預設的隔離級別。
蟑螂是一個分散式的K/V資料倉儲,支援ACID事務,多版本值儲存是其首要特性。主要的設計目標是全球一致性和可靠性,從蟑螂的命名上是就能看出這點。蟑螂資料庫能處理磁碟、物理機器、機架甚至資料中心失效情況下最小延遲的服務中斷;整個失效過程無需人工干預。蟑螂的節點是均衡的,其設計目標是同質部署(只有一個二進位制包)且最小設定。CockroachDB 無需重新設定,也無需進行大規模的架構大修 就可以水平擴充套件,只需在叢集中新增一個新節點就可以了,CockroachDB就會處理底層的複雜性。
TiDB (企業版收費)
TiDB 是一款定位於線上事務處理/線上分析處理( HTAP: Hybrid Transactional/Analytical Processing)的融合型資料庫產品,實現了一鍵水平伸縮,強一致性的多副本資料安全,分散式事務,實時 OLAP 等重要特性。同時相容 MySQL 協定和生態,遷移便捷,運維成本極低。但是從使用情況來看,它對硬體要求較高。目前也分社群版和企業版。
ClustrixDB(收費)
MariaDB 2018年收購了ClustrixDB,它目前是一個類MYSQL的關聯式資料庫, 可以很容易的從MySQL遷移 到ClustrixDB。ClustrixDB與MySQL客戶機相容,但與mazon Aurora不同,它是分散式的,可以擴充套件寫操作,並且不會產生單獨的IO和儲存費用,它從底層就支援web、移動和物聯網(IoT)等具有最極端的可延伸性要求的應用程式,並且是在不損害關鍵特性的情況下做到這一點,資料庫需要為帶有關鍵型任務應用程式提供對可靠資料存取服務:事務和SQL。
MemSQL(收費)
MemSQL最大的賣點就是效能,同時相容相容MySQL。MemSQL,2012年12月14日釋出,是世界上最快的關聯式資料庫,能實現每秒150萬次事務。MemSQL是一個分散式的、高度可伸縮的SQL資料庫,可以在任何地方執行。我們使用熟悉的關係模型為事務性和分析性工作負載提供最高效能.MemSQL是一個可延伸的SQL資料庫,它不斷地吸收資料,為您的業務一線執行操作分析。使用ACID事務每秒接收數百萬個事件,同時以關係SQL、JSON、地理空間和全文搜尋格式分析數十億行資料。
NuoDB(商用需要授權)
NuoDB 是世界上首個也是唯一一個具有專利的、彈性可伸縮的SQL關聯式資料庫,主要用於去集中化的計算資源。我們完全從頭開始設計這麼一個全新的資料庫,100% ACID 保證以及相容 SQL 標準規範。支援複雜資料庫管理任務如分割區、快取叢集和效能調優等等。
Altibase(商用收費)
ALTIBASE 資料庫完美結合了,並提出了一個新概念---Hybrid DBMS。ALTIBASE 提供高效能、容錯能力和事務管理的方便性,特別是在通訊、網上銀行、證券交易、實時應用和嵌入式系統領域。
VoltDB(商用收費)
VoltDB是一個記憶體中的開源OLTP SQL資料庫,能夠保證事務的完整性(ACID)。它是Postgres和Ingres聯合創始人Mike Stonebraker領導開發的下一代開源資料庫管理系統。它能在現有的廉價伺服器叢集上實現每秒數百萬次資料處理。VoltDB大幅降低了伺服器資源 開銷,單節點每秒資料處理遠遠高於其它資料庫管理系統。不同於NoSQL的key-value儲存,VoltDB能使用SQL存取,支援傳統資料庫的 ACID模型。VoltDB程式碼採用GPLv3授權,支援訂閱費用從15,000美元起步。
Citus(商用收費)
Citus面向高速簡單的事務,高吞吐量批次載入以及高速亞秒級分析查詢。它還整合了cstore/hll等很多外掛。一個限制是在某些情況下它不支援所有SQL查詢或複雜事務。CitusDB採用PostgreSQL的外掛形式(not a fork),即享受PostgreSQL的強大支援,又同時擁有分散式資料庫能力。Citus的企業版是要收費的。
在寫這個中介軟體前想了很多,因為現在一畢業的人你一問他快取,他都知道用Redis,從09年出現Redis到現在,這玩意已經很成熟和大眾化了,所以在規劃中介軟體文章時想了很久要怎麼寫才能寫出一些新的識知的東西,思考很久後我想了想,正是因為會很的人都會把東西直接放Redis中,如果不明白什麼東西應該放Redis中什麼不該放,如果不明白怎麼合理使用Redis中提供的不同的資料型別及規劃Redis的使用,那麼這種盲目的使用其實對系統來說並不見得是對效能的提升反而是一場災難。
什麼是Nosql:Nosql叫做非關係型資料庫,為了解決高並行、高可用、高可延伸,巨量資料儲存等一系列問題而產生的資料庫解決方案。
Redis是使用ANSI C語言開發的一個高效能Key-Value資料庫,是當今速度最快的記憶體型非關係型(NoSQL)資料庫,可以儲存鍵和五種不同型別的值之間的對映。鍵的型別只能為字串,值支援五種資料型別:字串、列表、集合、雜湊表、有序集合。
Redis 支援很多特性,例如將記憶體中的資料持久化到硬碟中,使用複製來擴充套件讀效能,使用分片來擴充套件寫效能。
應用場景:String是最常用的一種資料型別,普通的key/value儲存都可以化為此類,即可以完全實現目前Memcached的功能,並且效率更高。還具有Redis的持久化,操作紀錄檔以及Replication等功能。除了和Memcached一樣有get set incr decr等操作外,Redis還具有如下操作:
使用場景:常規key-value快取應用。常規計數:微博數、粉絲數。
實現方式:String在redis內部儲存預設就是一個字串,被redisObject所參照,當遇到incr ,decr等操作時會轉成數值型進行計算,此時redisObject的encoding欄位為int
應用場景:Redis list的應用場景非常多,也是redis最重要的資料結構之一,比如twitter的關注列表,粉絲列表等都可以用redis的list結構來實現。
List就是連結串列,使用List結構,我們可以實現最新訊息排行等功能。List的另一個應用就是訊息佇列。
可以利用List的PUSH操作,將任務存在List中,然後工作執行緒再用POP操作將任務取出來進行執行。Redis還提供了操作List中某一段的api,可以直接查詢,刪除List中某一段的元素。
實現方式:Redis List的實現為一個雙向連結串列,即可以支援反向查詢和遍歷,更方便操作,不過會帶來額外記憶體開銷,Redis內部的很多實現,包括傳送緩衝隊等也是採用這個資料結構。
Redis的list是每個子元素都是String型別的雙向連結串列,可以通過push和pop操作從列表的頭部或者尾部新增或者刪除元素,這樣list既可以作為棧又可以作為佇列。
使用場景:訊息佇列
使用list可以構建訊息佇列系統。 比如將Redis 用作紀錄檔收集器,實際上還是一個佇列,多個端點將紀錄檔資訊寫入Redis,然後一個worker統一將所有紀錄檔寫到磁碟。取出最新的N個資料的操作。記錄前N個最新登陸的使用者ID列表,超出範圍的可以從資料庫取出。
Redis 的 Set 是 String 型別的無序集合。集合成員是唯一的,這就意味著集合中不能出現重複的資料。 Redis 中集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)。 集合中最大的成員數為 232 - 1 (4294967295, 每個集合可儲存40多億個成員)。
為什麼不用JVM自帶的Set進行去重: 一般我們的系統都是叢集部署,那麼使用JVM自帶的set比較麻煩,需要再起一個公共服務。
常見命令:
sadd
spop
smembers
sunion
應用場景:set對外提供的功能和list類似,但是set具有自動排重功能。並且set提供了判斷某個成員是否在一個set集合內的重要介面,這要是list所不能提供的。
案例:在微博應用中,可以將一個使用者所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還為集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給使用者端還是存到一個新的集合中。Set是集合,是String型別的無序集合,set是通過hashtable實現的,概念和數學中個的集合基本類似,可以交集,並集,差集等等,set中的元素是沒有順序的。
實現方式:set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。
zadd:向有序集合zset中增加一個元素。例如:zadd zset 1 Hello
zrange:輸出zset中指定範圍內的的所有元素,按照score從小到大的順序。例如:zrange zset 0 -1 withscores,表示輸出有序集合zset中所有的元素,並且輸出順序號。
zrem:刪除名稱為key的zset集合中的元素member。例如:zrem set1 Hello。
zincrby:把有序集合zset中的指定元素的序列號加上指定的值。例如:zincrby zset 4 Hello
zrank:返回名稱為key的zset集合中元素的排名,按照下標從小到大的排名。例如:zrank zset Hello。
zrevrank:返回名稱為key的zset集合中元素的排名,按照下表從大到小的排名。例如:zrevrank zset Hello。
zrevrange:按照score從大到小的順序輸出集合中所有元素。例如:zrevrange zset 0 -1 withscores。
zrangebyscore:返回集合中給定區間的元素。例如:zrangebyscore zset 2 3 withscores
zcount:返回集合中score在給定區間的數量。zcount zset 2 3
zcard:返回集合中元素的個數。
zremrangebyrank:按照索引來刪除給定區間的元素。例如:zremrangebyrank zset 1 2
zremrangebyscore:刪除score在指定範圍內的元素。例如:zremrangebyscore zset 1 2
常見命令:
getbit 指令:獲取到 key 對應的 value 在 offset 處的 bit 值。
setbit 指令:修改 key 對應的 value 在 offset 處的 bit 值
bitcount 指令:統計二進位制資料中 1 的個數