NoSQL數(shù)據(jù)庫有很多種,實現(xiàn)方式差別很大。有接近SQL查詢方式的,也有純粹的鍵值對查詢。
十載建站經(jīng)驗, 成都網(wǎng)站設計、成都網(wǎng)站建設客戶的見證與正確選擇。創(chuàng)新互聯(lián)公司提供完善的營銷型網(wǎng)頁建站明細報價表。后期開發(fā)更加便捷高效,我們致力于追求更美、更快、更規(guī)范。
對于K-V型數(shù)據(jù)庫,比較典型的是Redis,系統(tǒng)提供了get、set之類的命令用于增刪改查。關鍵是鍵值對的鍵和值怎么設計。
一、概念
SQL?(Structured?Query?Language)?數(shù)據(jù)庫,指關系型數(shù)據(jù)庫。主要代表:SQL?Server,Oracle,MySQL(開源),PostgreSQL(開源)。
NoSQL(Not?Only?SQL)泛指非關系型數(shù)據(jù)庫。主要代表:MongoDB,Redis,CouchDB。
二、區(qū)別
1、存儲方式
SQL數(shù)據(jù)存在特定結(jié)構(gòu)的表中;而NoSQL則更加靈活和可擴展,存儲方式可以省是JSON文檔、哈希表或者其他方式。SQL通常以數(shù)據(jù)庫表形式存儲數(shù)據(jù)。舉個栗子,存?zhèn)€學生借書數(shù)據(jù):
而NoSQL存儲方式比較靈活,比如使用類JSON文件存儲上表中熊大的借閱數(shù)據(jù):
2、表/數(shù)據(jù)集合的數(shù)據(jù)的關系
在SQL中,必須定義好表和字段結(jié)構(gòu)后才能添加數(shù)據(jù),例如定義表的主鍵(primary?key),索引(index),觸發(fā)器(trigger),存儲過程(stored?procedure)等。表結(jié)構(gòu)可以在被定義之后更新,但是如果有比較大的結(jié)構(gòu)變更的話就會變得比較復雜。在NoSQL中,數(shù)據(jù)可以在任何時候任何地方添加,不需要先定義表。例如下面這段代碼會自動創(chuàng)建一個新的"借閱表"數(shù)據(jù)集合:
NoSQL也可以在數(shù)據(jù)集中建立索引。以MongoDB為例,會自動在數(shù)據(jù)集合創(chuàng)建后創(chuàng)建唯一值_id字段,這樣的話就可以在數(shù)據(jù)集創(chuàng)建后增加索引。
從這點來看,NoSQL可能更加適合初始化數(shù)據(jù)還不明確或者未定的項目中。
3、外部數(shù)據(jù)存儲
SQL中如何需要增加外部關聯(lián)數(shù)據(jù)的話,規(guī)范化做法是在原表中增加一個外鍵,關聯(lián)外部數(shù)據(jù)表。例如需要在借閱表中增加審核人信息,先建立一個審核人表:
再在原來的借閱人表中增加審核人外鍵:
這樣如果我們需要更新審核人個人信息的時候只需要更新審核人表而不需要對借閱人表做更新。而在NoSQL中除了這種規(guī)范化的外部數(shù)據(jù)表做法以外,我們還能用如下的非規(guī)范化方式把外部數(shù)據(jù)直接放到原數(shù)據(jù)集中,以提高查詢效率。缺點也比較明顯,更新審核人數(shù)據(jù)的時候?qū)容^麻煩。
4、SQL中的JOIN查詢
SQL中可以使用JOIN表鏈接方式將多個關系數(shù)據(jù)表中的數(shù)據(jù)用一條簡單的查詢語句查詢出來。NoSQL暫未提供類似JOIN的查詢方式對多個數(shù)據(jù)集中的數(shù)據(jù)做查詢。所以大部分NoSQL使用非規(guī)范化的數(shù)據(jù)存儲方式存儲數(shù)據(jù)。
5、數(shù)據(jù)耦合性
SQL中不允許刪除已經(jīng)被使用的外部數(shù)據(jù),例如審核人表中的"熊三"已經(jīng)被分配給了借閱人熊大,那么在審核人表中將不允許刪除熊三這條數(shù)據(jù),以保證數(shù)據(jù)完整性。而NoSQL中則沒有這種強耦合的概念,可以隨時刪除任何數(shù)據(jù)。
6、事務
SQL中如果多張表數(shù)據(jù)需要同批次被更新,即如果其中一張表更新失敗的話其他表也不能更新成功。這種場景可以通過事務來控制,可以在所有命令完成后再統(tǒng)一提交事務。而NoSQL中沒有事務這個概念,每一個數(shù)據(jù)集的操作都是原子級的。
7、增刪改查語法
8、查詢性能
在相同水平的系統(tǒng)設計的前提下,因為NoSQL中省略了JOIN查詢的消耗,故理論上性能上是優(yōu)于SQL的。
Hadoop
文件系統(tǒng):文件系統(tǒng)是用來存儲和管理文件,并且提供文件的查詢、增加、刪除等操作。
直觀上的體驗:在shell窗口輸入 ls 命令,就可以看到當前目錄下的文件夾、文件。
文件存儲在哪里?硬盤
一臺只有250G硬盤的電腦,如果需要存儲500G的文件可以怎么辦?先將電腦硬盤擴容至少250G,再將文件分割成多塊,放到多塊硬盤上儲存。
通過 hdfs dfs -ls 命令可以查看分布式文件系統(tǒng)中的文件,就像本地的ls命令一樣。
HDFS在客戶端上提供了查詢、新增和刪除的指令,可以實現(xiàn)將分布在多臺機器上的文件系統(tǒng)進行統(tǒng)一的管理。
在分布式文件系統(tǒng)中,一個大文件會被切分成塊,分別存儲到幾臺機器上。結(jié)合上文中提到的那個存儲500G大文件的那個例子,這500G的文件會按照一定的大小被切分成若干塊,然后分別存儲在若干臺機器上,然后提供統(tǒng)一的操作接口。
看到這里,不少人可能會覺得,分布式文件系統(tǒng)不過如此,很簡單嘛。事實真的是這樣的么?
潛在問題
假如我有一個1000臺機器組成的分布式系統(tǒng),一臺機器每天出現(xiàn)故障的概率是0.1%,那么整個系統(tǒng)每天出現(xiàn)故障的概率是多大呢?答案是(1-0.1%)^1000=63%,因此需要提供一個容錯機制來保證發(fā)生差錯時文件依然可以讀出,這里暫時先不展開介紹。
如果要存儲PB級或者EB級的數(shù)據(jù),成千上萬臺機器組成的集群是很常見的,所以說分布式系統(tǒng)比單機系統(tǒng)要復雜得多呀。
這是一張HDFS的架構(gòu)簡圖:
client通過nameNode了解數(shù)據(jù)在哪些DataNode上,從而發(fā)起查詢。此外,不僅是查詢文件,寫入文件的時候也是先去請教NameNode,看看應該往哪個DateNode中去寫。
為了某一份數(shù)據(jù)只寫入到一個Datanode中,而這個Datanode因為某些原因出錯無法讀取的問題,需要通過冗余備份的方式來進行容錯處理。因此,HDFS在寫入一個數(shù)據(jù)塊的時候,不會僅僅寫入一個DataNode,而是會寫入到多個DataNode中,這樣,如果其中一個DataNode壞了,還可以從其余的DataNode中拿到數(shù)據(jù),保證了數(shù)據(jù)不丟失。
實際上,每個數(shù)據(jù)塊在HDFS上都會保存多份,保存在不同的DataNode上。這種是犧牲一定存儲空間換取可靠性的做法。
接下來我們來看一下完整的文件寫入的流程:
大文件要寫入HDFS,client端根據(jù)配置將大文件分成固定大小的塊,然后再上傳到HDFS。
讀取文件的流程:
1、client詢問NameNode,我要讀取某個路徑下的文件,麻煩告訴我這個文件都在哪些DataNode上?
2、NameNode回復client,這個路徑下的文件被切成了3塊,分別在DataNode1、DataNode3和DataNode4上
3、client去找DataNode1、DataNode3和DataNode4,拿到3個文件塊,通過stream讀取并且整合起來
文件寫入的流程:
1、client先將文件分塊,然后詢問NameNode,我要寫入一個文件到某個路徑下,文件有3塊,應該怎么寫?
2、NameNode回復client,可以分別寫到DataNode1、DataNode2、DataNode3、DataNode4上,記住,每個塊重復寫3份,總共是9份
3、client找到DataNode1、DataNode2、DataNode3、DataNode4,把數(shù)據(jù)寫到他們上面
出于容錯的考慮,每個數(shù)據(jù)塊有3個備份,但是3個備份快都直接由client端直接寫入勢必會帶來client端過重的寫入壓力,這個點是否有更好的解決方案呢?回憶一下mysql主備之間是通過binlog文件進行同步的,HDFS當然也可以借鑒這個思想,數(shù)據(jù)其實只需要寫入到一個datanode上,然后由datanode之間相互進行備份同步,減少了client端的寫入壓力,那么至于是一個datanode寫入成功即成功,還是需要所有的參與備份的datanode返回寫入成功才算成功,是可靠性配置的策略,當然這個設置會影響到數(shù)據(jù)寫入的吞吐率,我們可以看到可靠性和效率永遠是“魚和熊掌不可兼得”的。
潛在問題
NameNode確實會回放editlog,但是不是每次都從頭回放,它會先加載一個fsimage,這個文件是之前某一個時刻整個NameNode的文件元數(shù)據(jù)的內(nèi)存快照,然后再在這個基礎上回放editlog,完成后,會清空editlog,再把當前文件元數(shù)據(jù)的內(nèi)存狀態(tài)寫入fsimage,方便下一次加載。
這樣,全量回放就變成了增量回放,但是如果NameNode長時間未重啟過,editlog依然會比較大,恢復的時間依然比較長,這個問題怎么解呢?
SecondNameNode是一個NameNode內(nèi)的定時任務線程,它會定期地將editlog寫入fsimage,然后情況原來的editlog,從而保證editlog的文件大小維持在一定大小。
NameNode掛了, SecondNameNode并不能替代NameNode,所以如果集群中只有一個NameNode,它掛了,整個系統(tǒng)就掛了。hadoop2.x之前,整個集群只能有一個NameNode,是有可能發(fā)生單點故障的,所以hadoop1.x有本身的不穩(wěn)定性。但是hadoop2.x之后,我們可以在集群中配置多個NameNode,就不會有這個問題了,但是配置多個NameNode,需要注意的地方就更多了,系統(tǒng)就更加復雜了。
俗話說“一山不容二虎”,兩個NameNode只能有一個是活躍狀態(tài)active,另一個是備份狀態(tài)standby,我們看一下兩個NameNode的架構(gòu)圖。
兩個NameNode通過JournalNode實現(xiàn)同步editlog,保持狀態(tài)一致可以相互替換。
因為active的NameNode掛了之后,standby的NameNode要馬上接替它,所以它們的數(shù)據(jù)要時刻保持一致,在寫入數(shù)據(jù)的時候,兩個NameNode內(nèi)存中都要記錄數(shù)據(jù)的元信息,并保持一致。這個JournalNode就是用來在兩個NameNode中同步數(shù)據(jù)的,并且standby NameNode實現(xiàn)了SecondNameNode的功能。
進行數(shù)據(jù)同步操作的過程如下:
active NameNode有操作之后,它的editlog會被記錄到JournalNode中,standby NameNode會從JournalNode中讀取到變化并進行同步,同時standby NameNode會監(jiān)聽記錄的變化。這樣做的話就是實時同步了,并且standby NameNode就實現(xiàn)了SecondNameNode的功能。
優(yōu)點:
缺點:
package basic;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC {
public void findAll() {
try {
// 獲得數(shù)據(jù)庫驅(qū)動
//由于長時間不寫,驅(qū)動名和URL都忘記了,不知道對不對,你應該知道的,自己改一下的哈
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String userName = "system";
String password = "system";
Class.forName("oracle.jdbc.driver.OracleDriver");
// 創(chuàng)建連接
Connection conn = DriverManager.getConnection(url, userName,
password);
// 新建發(fā)送sql語句的對象
Statement st = conn.createStatement();
// 執(zhí)行sql
String sql = "select * from users";
ResultSet rs = st.executeQuery(sql);
// 處理結(jié)果
while(rs.next()){
//這個地方就是給你的封裝類屬性賦值
System.out.println("UserName:"+rs.getString(0));
}
// 關閉連接
rs.close();
st.close();
conn.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void delete(){
try {
//步驟還是那六個步驟,前邊的兩步是一樣的
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String userName = "system";
String password = "system";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(url,userName,password);
//這里的發(fā)送sql語句的對象是PreparedStatement,成為預處理sql對象,因為按條件刪除是需要不定值的
String sql = "delete from users where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(0, 1);
int row = ps.executeUpdate();
if(row!=0){
System.out.println("刪除成功!");
}
// 關閉連接
rs.close();
st.close();
conn.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
NoSQL,指的是非關系型的數(shù)據(jù)庫。隨著互聯(lián)網(wǎng)web2.0網(wǎng)站的興起,傳統(tǒng)的關系數(shù)據(jù)庫在應付web2.0網(wǎng)站,特別是超大規(guī)模和高并發(fā)的
SNS類型的web2.0純動態(tài)網(wǎng)站已經(jīng)顯得力不從心,暴露了很多難以克服的問題,而非關系型的數(shù)據(jù)庫則由于其本身的特點得到了非常迅速的發(fā)展。
NoSQL(NoSQL
= Not Only SQL
),意即“不僅僅是SQL”,是一項全新的數(shù)據(jù)庫革命性運動,早期就有人提出,發(fā)展至2009年趨勢越發(fā)高漲。NoSQL的擁護者們提倡運用非關系型的數(shù)
據(jù)存儲,相對于鋪天蓋地的關系型數(shù)據(jù)庫運用,這一概念無疑是一種全新的思維的注入。
從這一新興技術中選擇一款正確的NoSQL數(shù)據(jù)庫是非常具有挑戰(zhàn)性的。比一下網(wǎng)建議在選擇時考慮以下因素:
并發(fā)控制
并
發(fā)控制指的是當多個用戶同時更新運行時,用于保護數(shù)據(jù)庫完整性的各種技術。并發(fā)機制不正確可能導致臟讀、幻讀和不可重復讀等此類問題。并發(fā)控制的目的是保
證一個用戶的工作不會對另一個用戶的工作產(chǎn)生不合理的影響。在某些情況下,這些措施保證了當用戶和其他用戶一起操作時,所得的結(jié)果和她單獨操作時的結(jié)果是
一樣的。在另一些情況下,這表示用戶的工作按預定的方式受其他用戶的影響。
封鎖
就是事務T在對某個數(shù)據(jù)對象(例如表、記錄等)操作之前,先向系統(tǒng)發(fā)出請求,對其加鎖。加鎖后事務T就對該數(shù)據(jù)對象有了一定的控制,在事務T釋放它的鎖之前,其它的事務不能更新此數(shù)據(jù)對象。
封鎖是一次只允許一個用戶讀取或修改的一種機制,是實現(xiàn)并發(fā)控制的一個非常重要的技術。
MVCC
Multi-Version Concurrency Control多版本并發(fā)控制,維持一個數(shù)據(jù)的多個版本使讀寫操作沒有沖突。MVCC優(yōu)化了數(shù)據(jù)庫并發(fā)系統(tǒng),使系統(tǒng)在有大量并發(fā)用戶時得到最高的性能,并且可以不用關閉服務器就直接進行熱備份。
ACID
指
數(shù)據(jù)庫事務正確執(zhí)行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久
性(Durability)。一個支持事務(Transaction)的數(shù)據(jù)庫系統(tǒng),必需要具有這四種特性,否則在事務過程(Transaction
processing)當中無法保證數(shù)據(jù)的正確性,交易過程極可能達不到交易方的要求。
None
一些系統(tǒng)不提供原子性。
鏡像
數(shù)據(jù)庫鏡像是DBMS根據(jù)DBA的要求,自動把整個數(shù)據(jù)庫或其中的關鍵數(shù)據(jù)復制到另一個磁盤上,每當主數(shù)據(jù)庫更新時,DBMS會自動把更新后的數(shù)據(jù)復制過去,即DBMS自動保證鏡像數(shù)據(jù)與主數(shù)據(jù)的一致性。
鏡像分為同步和異步。
數(shù)據(jù)存儲
指的是數(shù)據(jù)的物理特性怎樣被存儲在數(shù)據(jù)庫中。
磁盤 數(shù)據(jù)被存儲在硬盤驅(qū)動器里;
GFS或谷歌文件系統(tǒng)是一個由谷歌開發(fā)的專有的分布式文件系統(tǒng);
Hadoop是Apache軟件框架,免費許可下支持數(shù)據(jù)密集型分布式應用程序;
RAM隨機存儲器;
插件 可以添加外部插件;
Amazon S3通過Web服務接口提供存儲;
BDB:BDB
全稱是 “Berkeley DB”,它是MySQL具有事務能力的表類型,由Sleepycat
Software開發(fā)。BDB表類型提供了MySQL用戶長久期盼的功能,即事務控制能力。在任何RDBMS中,事務控制能力都是一種極其重要和寶貴的功
能。事務控制能力使得我們能夠確保一組命令確實已經(jīng)全部執(zhí)行成功,或者確保當任何一個命令出現(xiàn)錯誤時所有命令的執(zhí)行結(jié)果均被退回。
實現(xiàn)語言
實現(xiàn)語言會影響數(shù)據(jù)庫的發(fā)展速度。典型的NoSQL數(shù)據(jù)庫是用低級語言如C / C + +編寫的。另一方面,那些更高層次的語言如Java,使自定義更容易。
實現(xiàn)語言有:C, C++, Erlang, Java, Python
特性
考慮下列哪一個特點對你的數(shù)據(jù)庫是最重要的:
持久性
可用性
一致性
分區(qū)容忍性
證書類型
下面這些許可證是一個不同的開放源碼許可的形式:
GPL:通用公共許可證
BSD:伯克利軟件分發(fā)
MPL:Mozilla公共許可證
EPL:Eclipse公共許可證
IDPL:最初的開發(fā)者的公共許可證
LGPL:較寬松通用公共許可證
存儲類型
存儲類型是NoSQL數(shù)據(jù)庫最大的不同,是決定使用哪款數(shù)據(jù)庫的一個首要指標。
關鍵字:支持get、put和刪除操作
按列存儲:相對于傳統(tǒng)的按行存儲,數(shù)據(jù)集成容易多了
面向文件系統(tǒng):存儲像是JSON或XML這樣的結(jié)構(gòu)化文件,很容易就能從面向?qū)ο筌浖蝎@取數(shù)據(jù)。
如何在KALI-LINUX上安裝Nosql-Exploitation-Framework
然后查看文件夾”Nosql" 中的“README”, 可以用notepad打開,接下來執(zhí)行如下命令:
root@kali:~#apt-get install Python-setuptools
root@kali:~#easy_install pip
root@kali:~/Nosql# ./installformac.sh #因為該腳本僅是適合蘋果電腦,所以難免會出現(xiàn)一些問題
root@kali:~/Nosql#pip install -r requirements.txt