前言
傳統數據庫遇到的問題,數據量很大的時候無法存儲;沒有很好的備份機制;數據達到一定數量開始緩慢,很大的話基本無法支撐;因此我們需要探究更加合適的數據庫來支撐我們的業務。
HBase
什么是HBase
Hbase(Hadoop Database)是建立在HDFS之上的分布式、面向列的NoSQL的數據庫系統。
HBase特點
優點:
-
- 海量存儲:適合存儲PB級別的海量數據,采用廉價PC存儲的情況下,能在幾十到百毫秒內返回數據。
- 列式存儲(半結構化或非結構化數據):即列族存儲,對於數據結構字段不夠確定或雜亂無章非常難按一個概念去進行抽取的數據適合用。
- 極易擴展:一個是基於上層處理能力(RegionServer)的擴展,提升Hbsae服務更多Region的能力。一個是基於存儲的擴展(HDFS),通過橫向添加Datanode的機器,進行存儲層擴容,提升Hbase的數據存儲能力和提升后端存儲的讀寫能力。
- 高並發:采用廉價PC,能獲得高並發、低延遲、高性能的服務。
- 稀疏:列族中,可以指定任意多的列,列數據為空不會占用存儲空間的,也提高了讀性能。
- 多版本號數據:依據Row key和Column key定位到的Value能夠有隨意數量的版本號值,版本號默認是單元格插入時的時間戳。
- 適用於插入比查詢操作更頻繁的情況:比如,對於歷史記錄表和日志文件。
- 數據類型單一:HBase中數據類型都是字符串。
- 無模式:每一行都有一個可以排序的rowKey和任意多的截然不同的列。
缺點:
-
- 單一RowKey固有的局限性決定了它不可能有效地支持多條件查詢。
- 不適合於大范圍掃描查詢。
- 不直接支持 SQL 的語句查詢。
- 僅支持行級(單行)事務(HBase的事務是行級事務,可以保證行級數據的原子性、一致性、隔離性以及持久性)。
- HBase的配置非常麻煩,最低的限度都需要包括Zookeeper ensemble、primary HMaster、secondary HMaster、RegionServers、active NameNode、standby NameNode、HDFS quorum journal manager及DataNodes。使用HBase需求大量的專業知識——甚至是最簡單的監視。RegionServer存在單點故障,當它發生故障時,一個新的RegionServer必須被選舉出,而在可以投入之前,必須重新完成write-ahead日志里的內容,即故障恢復較慢,WAL回放較慢。HBase的API非常笨拙並且具有太強的Java特色,非Java客戶端只能委托給Thrit或者REST。
HBase的體系結構
值得參考的網址:https://www.cnblogs.com/swordfall/p/8737328.html
HBase使用場景
Hbase是一個通過廉價PC機器集群來存儲海量數據的分布式數據庫解決方案。它比較適合的場景概括如下:
-
- 是巨量大(百T、PB級別)
- 查詢簡單(基於rowkey或者rowkey范圍查詢)
- 不涉及到復雜的關聯
有幾個典型的場景特別適合使用Hbase來存儲:
-
- 海量訂單流水數據(長久保存)
- 交易記錄
- 數據庫歷史數據
如何使用HBase
三種模式:單機模式,偽分布式模式,分布式模式
一般生產環境用的是分布式模式,如果是學習的話,可以用單機模式和偽分布式模式。
安裝zookeeper
https://blog.csdn.net/weixin_41558061/article/details/80597174
全分布式模式的Hbase集群需要運行ZooKeeper實例,默認情況下HBase自身維護着一組默認的ZooKeeper實例,可以自己配置實例,這樣Hbase會更加健壯
注意:使用默認的實例時,HBase將自動啟動或停止ZooKeeper,當使用獨立的ZooKeeper實例時,需要用戶手動啟動和停止ZooKeeper實例
安裝Hadoop
安裝HBase
https://www.cnblogs.com/wishyouhappy/p/3707904.html
hbase_home/conf/hbase-site.xml文件中的configuration加入:
1 <property> 2 <name>hbase.rootdir</name> 3 <value>hdfs://hadoop0:9000/hbase</value> 4 </property> 5 <property> 6 <name>hbase.cluster.distributed</name> 7 <value>true</value> 8 </property> 9 <property> 10 <name>hbase.zookeeper.quorum</name> 11 <value>hadoop0</value> 12 </property> 13 <property> 14 <name>dfs.replication</name> //指定Hlog和Hfile副本數,此參數值並不能大於HDFS節點數,如果datanode只有一台則此參數應該設置為1 15 <value>1</value> 16 </property>
注意事項:
1.關於Hadoop
1. 目前的HBase只能依賴特定的Hadoop版本,HBae和Hadoop之間的RPC是版本話的,需要調用方與被調用方相互匹配,細微的差異可能導致通信失敗
2. 由於Hadoop依賴於Hadoop,它要求Hadoop的JAR必須部署在HBase的lib目錄下。HBase使用的Hadoop版本必須與底層Hadoop集群上使用的Hadoop版本一直,因而使用Hadoop集群上運行的JAR替換HBase的lib目錄中依賴的Hadoop的JAR可以避免版本不匹配的問題
3. 集群中所有的節點都要更新為一樣的JAR,否則版本不匹配問題可能造成集群無法啟動或者假死現象
2.關於HBase Shell
1.如果使用的分布式模式,那么在關閉Hadoop之前一定要確認HBase已經被正常關閉了
2. 使用stop-hbase.sh關閉HBase時,控制台會打印關於停止的信息,會周期性的打印 ".",關閉腳本需要幾分鍾完成,如果集群中機器數量很多,那么執行時間會更長
介紹比較全面的網址:https://www.cnblogs.com/JamesXiao/p/6202372.html
了解完HBase后,可帶着問題看這一篇文章:https://blog.csdn.net/nosqlnotes/article/details/79647096
MongoDB
什么是MongoDB
MongoDB是一個介於關系數據庫和非關系數據庫之間,基於分布式文件存儲,由C 語言編寫的數據庫。
MongoDB特點
優點
高性能、易部署、易使用、高寫負載,存儲數據非常方便。
-
-
-
- 面向文檔存儲(類JSON數據模式簡單而強大)
-
-
-
-
-
-
動態查詢
-
全索引支持,擴展到內部對象和內嵌數組
-
查詢記錄分析
-
快速,就地更新
-
高效存儲二進制大對象 (比如照片和視頻)
-
復制和故障切換支持
-
Auto- Sharding自動分片支持雲級擴展性
- 支持RUBY,PYTHON,JAVA,C ,PHP,C#等多種語言。
-
MapReduce 支持復雜聚合
-
商業支持,培訓和咨詢
-
-
-
缺點
-
-
-
- 不支持事務(進行開發時需要注意,哪些功能需要使用數據庫提供的事務支持)
- MongoDB占用空間過大 (不過這個確定對於目前快速下跌的硬盤價格來說,也不算什么缺點了)
-
2.1、空間的預分配:
當MongoDB的空間不足時它就會申請生成一大塊硬盤空間,而且申請的量都是有64M、128M、256M來增加直到2G為單個文件的較大體積,並且隨着數量疊增,可以在數據目錄下看到整塊生成而且不斷遞增的文件。 -
2.2、刪除記錄不釋放空間:
這很容易理解,為避免記錄刪除后的數據的大規模挪動,原記錄空間不刪除,只標記“已刪除”即可,以后還可以重復利用。
-
- MongoDB沒有如MySQL那樣成熟的維護工具,這對於開發和IT運營都是個值得注意的地方
- 在32位系統上,不支持大於2.5G的數據(很多操作系統都已經拋棄了32位版本,所以這個也算不上什么缺點了,3.4版本已經放棄支持32 位 x86平台)
-
-
MongoDB原理
mongodb在電腦磁盤文件系統之上,又包裝了自己的一套文件系統---gridfs,里面存儲的是一個一個的json二進制對象,也就是Bson。
存儲容量需求超出單機磁盤容量時,用分片技術去解決
詳情可參考網址:
https://www.cnblogs.com/wangshouchang/p/6920390.html
https://blog.csdn.net/justlpf/article/details/80392944
場景適用
適用場景
● 網站數據:Mongo 非常適合實時的插入,更新與查詢,並具備網站實時數據存儲所需的復制及高度伸縮性。● 緩存:由於性能很高,Mongo 也適合作為信息基礎設施的緩存層。在系統重啟之后,由Mongo 搭建的持久化緩存層可以避免下層的數據源過載。● 大尺寸、低價值的數據:使用傳統的關系型數據庫存儲一些數據時可能會比較昂貴,在此之前,很多時候程序員往往會選擇傳統的文件進行存儲。● 高伸縮性的場景:Mongo 非常適合由數十或數百台服務器組成的數據庫,Mongo 的路線圖中已經包含對MapReduce 引擎的內置支持。● 用於對象及JSON 數據的存儲:Mongo 的BSON 數據格式非常適合文檔化格式的存儲及查詢。
不適場景
● 高度事務性的系統:例如,銀行或會計系統。傳統的關系型數據庫目前還是更適用於需要大量原子性復雜事務的應用程序。● 傳統的商業智能應用:針對特定問題的BI 數據庫會產生高度優化的查詢方式。對於此類應用,數據倉庫可能是更合適的選擇。● 需要SQL 的問題。
如何使用MongoDB
linux平台安裝MongoDB
http://www.runoob.com/mongodb/mongodb-linux-install.html
spring中集成MongoDB,通過引入MongoDB的maven依賴,引入約束mongo來配置spring托管
xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation=" http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd"
配置連接池
<!--連接池配置--> <mongo:mongo host="${mongo.host}" port="${mongo.port}"> <mongo:options connections-per-host="${mongo.options.connections-per-host}" threads-allowed-to-block-for-connection-multiplier="${mongo.options.threads-allowed-to-block-for-connection-multiplier}" connect-timeout="${mongo.options.connect-timeout}" max-wait-time="${mongo.options.max-wait-time}" auto-connect-retry="${mongo.options.auto-connect-retry}" socket-keep-alive="${mongo.options.socket-keep-alive}" socket-timeout="${mongo.options.socket-timeout}" slave-ok="${mongo.options.slave-ok}" write-number="${mongo.options.write-number}" write-timeout="${mongo.options.write-timeout}" write-fsync="${mongo.options.write-fsync}"/> </mongo:mongo> <!--連接池工廠配置--> <mongo:db-factory dbname="${mongo.dbname}" username="${mongo.username}" password="${mongo.password}" mongo-ref="mongo"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> </bean> <!--實體映射自動掃描注入的包--> <mongo:mapping-converter> <mongo:custom-converters base-package="com.xyh.mongodb_model" /> </mongo:mapping-converter>
在實體類中加入相應的@Document、@id、@Indexed、@PersistenceConstructor注解,來實現對數據實例化對象進行增刪改查的操作。
詳細信息可參考網址:https://blog.csdn.net/xuanyonghao/article/details/76976149
Cassandra
什么是Cassandra
Cassandra是數據放置在具有多個復制因子的不同機器上,處理大量數據的分布式架構的非關系數據庫。
Cassandra特點
優點
配置簡單
不需要多模塊協同操作。
模式靈活
使用Cassandra,像文檔存儲,你不必提前解決記錄中的字段。你可以在系統運行時隨意的添加或移除字段。這是一個驚人的效率提升,特別是在大型部署上。
真正的可擴展性
Cassandra是純粹意義上的水平擴展。為給集群添加更多容量,可以指向另一台電腦。你不必重啟任何進程,改變應用查詢,或手動遷移任何數據。
多數據中心識別
你可以調整你的節點布局來避免某一個數據中心起火,一個備用的數據中心將至少有每條記錄的完全復制。
范圍查詢
如果你不喜歡全部的鍵值查詢,則可以設置鍵的范圍來查詢。
列表數據結構
在混合模式可以將超級列添加到5維。對於每個用戶的索引,這是非常方便的。
分布式寫操作
有可以在任何地方任何時間集中讀或寫任何數據。並且不會有任何單點失敗。
原理
在Cassandra中,是無中心的P2P架構,網絡中的所有節點都是對等的,它們構成了一個環,節點之間通過P2P協議每秒鍾交換一次數據,這樣每個節點都擁有其它所有節點的信息,包括位置、狀態等,以避免單點故障。

寫請求
當寫事件發生時,首先由Commit Log捕獲寫事件並持久化;每個數據中心選取一個Coordinator來完成它所在數據中心的數據復制;存儲結構類似LSM樹(Log-Structured Merge Tree)這種結構;Commit Log記錄每次寫請求的完整信息,此時並不會根據主鍵進行排序,而是順序寫入;寫入到Memtable時,Cassandra能夠動態地為它分配內存空間;當memtable中的數據刷到SSTable后,Commit Log中的數據將被清理掉;Cassandra對Update操作的處理和傳統關系數據庫完全不一樣,並不立即對原有數據進行更新,而是會增加一條新的記錄,后續在進行Compaction時將數據再進行合並。Delete操作也同樣如此,要刪除的數據會先標記為Tombstone,后續進行Compaction時再真正永久刪除。

圖來源網址:https://www.yiibai.com/cassandra/cassandra-architecture.html
讀請求
讀取數據時,首先檢查Bloom filter,每一個SSTable都有一個Bloom filter用來檢查partition key是否在這個SSTable,這一步是在訪問任何磁盤IO的前面就會做掉。如果存在,再檢查partition key cache。讀請求(Read Request)分兩種,一種是Rirect Read Request,根據客戶端配置的Consistency Level讀取到數據即可返回客戶端結果。一種是Background Read Repair Request,除了直接請求到達的節點外,會被發送到其它復制節點,用於修復之前寫入有問題的節點,保證數據最終一致性。
行緩存和鍵緩存請求流程圖
圖來源網址:https://blog.csdn.net/fs1360472174/article/details/55005335
可參考網址:https://blog.csdn.net/doc_sgl/article/details/51068131
如何使用Cassandra
Cassandra集群搭建
https://blog.csdn.net/ch648966459/article/details/51671276/#commentBox
代碼應用
引入pom.xml
<dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-extras</artifactId> <version>3.1.1</version> </dependency>
連接代碼
String[] hosts = new String[]{"192.168.1.1", "192.168.1.2", "192.168.1.3"};//cassandra主機地址 //認證配置 AuthProvider authProvider = new PlainTextAuthProvider("ershixiong", "123456"); LoadBalancingPolicy lbp = new TokenAwarePolicy( DCAwareRoundRobinPolicy.builder().withLocalDc("myDC").build() ); //讀超時或連接超時設置 SocketOptions so = new SocketOptions().setReadTimeoutMillis(3000).setConnectTimeoutMillis(3000); //連接池配置 //PoolingOptions poolingOptions = new PoolingOptions().setConnectionsPerHost(HostDistance.LOCAL, 2, 3); //集群在同一個機房用HostDistance.LOCAL 不同的機房用HostDistance.REMOTE 忽略用HostDistance.IGNORED PoolingOptions poolingOptions= new PoolingOptions() .setMaxRequestsPerConnection(HostDistance.LOCAL, 64)//每個連接最多允許64個並發請求 .setCoreConnectionsPerHost(HostDistance.LOCAL, 2)//和集群里的每個機器都至少有2個連接 .setMaxConnectionsPerHost(HostDistance.LOCAL, 6);//和集群里的每個機器都最多有6個連接 //查詢配置 //設置一致性級別ANY(0),ONE(1),TWO(2),THREE(3),QUORUM(4),ALL(5),LOCAL_QUORUM(6),EACH_QUORUM(7),SERIAL(8),LOCAL_SERIAL(9),LOCAL_ONE(10); //可以在每次生成查詢statement的時候設置,也可以像這樣全局設置 QueryOptions queryOptions = new QueryOptions().setConsistencyLevel(ConsistencyLevel.ONE); //重試策略 RetryPolicy retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE; int port = 9042;//端口號 String keyspace = "keyspacename";//要連接的庫,可以不寫 Cluster cluster = Cluster.builder() .addContactPoints(hosts) .withAuthProvider(authProvider) .withLoadBalancingPolicy(lbp) .withSocketOptions(so) .withPoolingOptions(poolingOptions) .withQueryOptions(queryOptions) .withRetryPolicy(retryPolicy) .withPort(port) .build(); Session session = cluster.connect(keyspace);
具體可參考:https://blog.csdn.net/u010003835/article/details/52516571
scylla、hazelcast大家也可以私下研究一下。
結論
當你僅僅是存儲海量增長的消息數據,存儲海量增長的圖片,小視頻的時候,你要求數據不能丟失,你要求人工維護盡可能少,你要求能迅速通過添加機器擴充存儲,那么毫無疑問,Cassandra現在是占據上風的。
但是如果你希望構建一個超大規模的搜索引擎,產生超大規模的倒排索引文件(當然是邏輯上的文件,真實文件實際上被切分存儲於不同的節點上),那么目前HDFS+HBase是你的首選。