1. 程式人生 > >java面試總結(十)—— 常用技術介紹

java面試總結(十)—— 常用技術介紹

對於面試,面試官總會對我們簡歷上的專案經歷涉及到一些技術進行詢問,大多讓我們介紹一下技術的用途、特點等等,本文就提供一些常用的技術的簡介,如果大家有一些想分享的,可以留言,我在新增。

注:本文只提供一些應用技術的簡單介紹,具體的一些特性,請大家查詢相關資料深入研究。

Zookeeper

ZooKeeper是一種為分散式應用所設計的高可用、高效能且一致的開源協調服務,它提供了一項基本服務:分散式鎖服務。由於ZooKeeper的開源特性,後來我們的開發者在分散式鎖的基礎上,摸索了出了其他的使用方法:配置維護、組服務、分散式訊息佇列、分散式通知/協調等。

分散式鎖:假設有三臺機器,每臺機器各跑一個應用程式。然後我們將這三臺機器通過網路將其連線起來,構成一個系統來為使用者提供服務,對使用者來說這個系統的架構是透明的,他感覺不到我這個系統是一個什麼樣的架構。那麼我們就可以把這種系統稱作一個分散式系統。如下圖:
這裡寫圖片描述


在這個分散式系統中如何對程序進行排程,我門假設在第一臺機器上掛載了一個資源,然後這三個物理分佈的程序都要競爭這個資源,但我們又不希望他們同時進行訪問,這時候我們就需要一個協調器,來讓他們有序的來訪問這個資源。這個協調器就是我們經常提到的那個鎖,比如說”程序-1”在使用該資源的時候,會先去獲得鎖,”程序1”獲得鎖以後會對該資源保持獨佔,這樣其他程序就無法訪問該資源,”程序1”用完該資源以後就將鎖釋放掉,讓其他程序來獲得鎖,那麼通過這個鎖機制,我們就能保證了分散式系統中多個程序能夠有序的訪問該臨界資源。那麼我們把這個分散式環境下的這個鎖叫作分散式鎖。這個分散式鎖也就是我們分散式協調技術實現的核心內容,

注:ZooKeeper效能上的特點決定了它能夠用在大型的、分散式的系統當中。從可靠性方面來說,它並不會因為一個節點的錯誤而崩潰。除此之外,它嚴格的序列訪問控制意味著複雜的控制原語可以應用在客戶端上。ZooKeeper在一致性、可用性、容錯性的保證,也是ZooKeeper的成功之處,它獲得的一切成功都與它採用的協議——Zab協議是密不可分的。

Zookeeper總體結構

Zookeeper服務自身組成一個叢集(2n+1個服務允許n個失效)。Zookeeper服務有兩個角色,一個是leader,負責寫服務和資料同步,剩下的是follower,提供讀服務,leader失效後會在follower中重新選舉新的leader。Zookeeper邏輯圖如下:
這裡寫圖片描述

  1. 客戶端可以連線到每個server,每個server的資料完全相同。
  2. 每個follower都和leader有連線,接受leader的資料更新操作。
  3. Server記錄事務日誌和快照到持久儲存。
  4. 大多數server可用,整體服務就可用。

Zookeeper資料模型

Zookeeper表現為一個分層的檔案系統目錄樹結構(不同於檔案系統的是,節點可以有自己的資料,而檔案系統中的目錄節點只有子節點)。資料模型結構圖如下:
這裡寫圖片描述

圓形節點可以含有子節點,多邊形節點不能含有子節點。一個節點對應一個應用,節點儲存的資料就是應用需要的配置資訊。

Zookeeper 特點

順序一致性:按照客戶端傳送請求的順序更新資料。
原子性:更新要麼成功,要麼失敗,不會出現部分更新。
單一性 :無論客戶端連線哪個server,都會看到同一個檢視。
可靠性:一旦資料更新成功,將一直保持,直到新的更新。
及時性:客戶端會在一個確定的時間內得到最新的資料。

ZooKeeper處理單點故障

單點故障:通常分散式系統採用主從模式,就是一個主控機連線多個處理節點。主節點負責分發任務,從節點負責處理任務,當我們的主節點發生故障時,那麼整個系統就都癱瘓了,那麼我們把這種故障叫作單點故障。

傳統方式處理單點故障的方式:準備一個主節點,一個備用主節點,備用主節點定時請求主節點,如果主節點回復則不管,如果沒有回覆則認為主節點掛了,然後啟用備用主節點,這有個缺點就是容易受到網路影響,即雖然主節點發出了反映了,但是由於網路原因,備用主節點並沒有收到迴應,這時候就會有兩個主節點同時在連線從節點。

ZooKeeper的處理方式:我們啟動兩個主節點,”主節點-A”和”主節點-B”他們啟動以後,都向ZooKeeper去註冊一個節點。我們 假設”主節點-A”鎖註冊地節點是”master-00001”,”主節點-B”註冊的節點是”master-00002”,註冊完以後進行選舉,編號最 小的節點將在選舉中獲勝獲得鎖成為主節點,也就是我們的”主節點-A”將會獲得鎖成為主節點,然後”主節點-B”將被阻塞成為一個備用節點。那麼,通過這 種方式就完成了對兩個Master程序的排程。

如果”主節點-A”掛了,這時候他所註冊的節點將被自動刪除,ZooKeeper會自動感知節點的變化,然後再次發出選舉,這時候”主節點-B”將在選舉中獲勝,替代”主節點-A”成為主節點。

如果主節點恢復了,他會再次向ZooKeeper註冊一個節點,這時候他註冊的節點將會是”master-00003”,ZooKeeper會感知節點的變化再次發動選舉,這時候”主節點-B”在選舉中會再次獲勝繼續擔任”主節點”,”主節點-A”會擔任備用節點。

Shiro

Apache Shiro是一個強大且易用的Java安全框架,Shiro 可以幫助我們完成:認證、授權、加密、會話管理、與 Web 整合、快取等。其基本功能點如下圖所示:
這裡寫圖片描述

Authentication:身份認證 / 登入,驗證使用者是不是擁有相應的身份;
Authorization:授權,即許可權驗證,驗證某個已認證的使用者是否擁有某個許可權;即判斷使用者是否能做事情,常見的如:驗證某個使用者是否擁有某個角色。或者細粒度的驗證某個使用者對某個資源是否具有某個許可權;
Session Manager:會話管理,即使用者登入後就是一次會話,在沒有退出之前,它的所有資訊都在會話中;會話可以是普通 JavaSE 環境的,也可以是如 Web 環境的;
Cryptography:加密,保護資料的安全性,如密碼加密儲存到資料庫,而不是明文儲存;
Web Support:Web 支援,可以非常容易的整合到 Web 環境;
Caching:快取,比如使用者登入後,其使用者資訊、擁有的角色 / 許可權不必每次去查,這樣可以提高效率;
Concurrency:shiro 支援多執行緒應用的併發驗證,即如在一個執行緒中開啟另一個執行緒,能把許可權自動傳播過去;
Testing:提供測試支援;
Run As:允許一個使用者假裝為另一個使用者(如果他們允許)的身份進行訪問;
Remember Me:記住我,這個是非常常見的功能,即一次登入後,下次再來的話不用登入了。

注:Shiro 不會去維護使用者、維護許可權;這些需要我們自己去設計 / 提供;然後通過相應的介面注入給 Shiro 即可。

Shiro架構

一個好的框架,從外部來看應該具有非常簡單易於使用的 API,且 API 契約明確;從內部來看的話,其應該有一個可擴充套件的架構,即非常容易插入使用者自定義實現,因為任何框架都不能滿足所有需求。
首先,我們從外部來看 Shiro 吧,即從應用程式角度的來觀察如何使用 Shiro 完成工作。如下圖:
這裡寫圖片描述
可以看到:應用程式碼直接互動的物件是 Subject,也就是說 Shiro 的對外 API 核心就是 Subject;其每個 API 的含義:

Subject:主體,代表了當前 “使用者”,這個使用者不一定是一個具體的人,與當前應用互動的任何東西都是 Subject,如網路爬蟲,機器人等;即一個抽象概念;所有 Subject 都繫結到 SecurityManager,與 Subject 的所有互動都會委託給 SecurityManager;可以把 Subject 認為是一個門面;SecurityManager 才是實際的執行者;
SecurityManager:安全管理器;即所有與安全有關的操作都會與 SecurityManager 互動;且它管理著所有 Subject;可以看出它是 Shiro 的核心,它負責與後邊介紹的其他元件進行互動,如果學習過 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
Realm:域,Shiro 從從 Realm 獲取安全資料(如使用者、角色、許可權),就是說 SecurityManager 要驗證使用者身份,那麼它需要從 Realm 獲取相應的使用者進行比較以確定使用者身份是否合法;也需要從 Realm 得到使用者相應的角色 / 許可權進行驗證使用者是否能進行操作;可以把 Realm 看成 DataSource,即安全資料來源。

也就是說對於我們而言,最簡單的一個 Shiro 應用:
應用程式碼通過 Subject 來進行認證和授權,而 Subject 又委託給 SecurityManager;
我們需要給 Shiro 的 SecurityManager 注入 Realm,從而讓 SecurityManager 能得到合法的使用者及其許可權進行判斷。
從以上也可以看出,Shiro 不提供維護使用者 / 許可權,而是通過 Realm 讓開發人員自己注入。

接下來我們來從 Shiro 內部來看下 Shiro 的架構,如下圖所示:
這裡寫圖片描述

Subject:主體,可以看到主體可以是任何可以與應用互動的 “使用者”;
SecurityManager:相當於 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher;是 Shiro 的心臟;所有具體的互動都通過 SecurityManager 進行控制;它管理著所有 Subject、且負責進行認證和授權、及會話、快取的管理。
Authenticator:認證器,負責主體認證的,這是一個擴充套件點,如果使用者覺得 Shiro 預設的不好,可以自定義實現;其需要認證策略(Authentication Strategy),即什麼情況下算使用者認證通過了;
Authrizer:授權器,或者訪問控制器,用來決定主體是否有許可權進行相應的操作;即控制著使用者能訪問應用中的哪些功能;
Realm:可以有 1 個或多個 Realm,可以認為是安全實體資料來源,即用於獲取安全實體的;可以是 JDBC 實現,也可以是 LDAP 實現,或者記憶體實現等等;由使用者提供;注意:Shiro 不知道你的使用者 / 許可權儲存在哪及以何種格式儲存;所以我們一般在應用中都需要實現自己的 Realm;
SessionManager:如果寫過 Servlet 就應該知道 Session 的概念,Session 呢需要有人去管理它的生命週期,這個元件就是 SessionManager;而 Shiro 並不僅僅可以用在 Web 環境,也可以用在如普通的 JavaSE 環境、EJB 等環境;所有呢,Shiro 就抽象了一個自己的 Session 來管理主體與應用之間互動的資料;這樣的話,比如我們在 Web 環境用,剛開始是一臺 Web 伺服器;接著又上了臺 EJB 伺服器;這時想把兩臺伺服器的會話資料放到一個地方,這個時候就可以實現自己的分散式會話(如把資料放到 Memcached 伺服器);
SessionDAO:DAO 大家都用過,資料訪問物件,用於會話的 CRUD,比如我們想把 Session 儲存到資料庫,那麼可以實現自己的 SessionDAO,通過如 JDBC 寫到資料庫;比如想把 Session 放到 Memcached 中,可以實現自己的 Memcached SessionDAO;另外 SessionDAO 中可以使用 Cache 進行快取,以提高效能;
CacheManager:快取控制器,來管理如使用者、角色、許可權等的快取的;因為這些資料基本上很少去改變,放到快取中後可以提高訪問的效能
Cryptography:密碼模組,Shiro 提高了一些常見的加密元件用於如密碼加密 / 解密的。

Dubbo

Dubbo是一個分散式服務框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分散式的需求,其實是不需要用的,只有在分散式的時候,才有dubbo這樣的分散式服務框架的需求,並且本質上是個服務呼叫的東東,說白了就是個遠端服務呼叫的分散式框架.

其核心部分包含:

  1. 遠端通訊: 提供對多種基於長連線的NIO框架抽象封裝,包括多種執行緒模型,序列化,以及“請求-響應”模式的資訊交換方式。
  2. 叢集容錯: 提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及軟負載均衡,失敗容錯,地址路由,動態配置等叢集支援。
  3. 自動發現: 基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

Dubbo能做什麼?

  1. 透明化的遠端方法呼叫,就像呼叫本地方法一樣呼叫遠端方法,只需簡單配置,沒有任何API侵入。
  2. 軟負載均衡及容錯機制,可在內網替代F5等硬體負載均衡器,降低成本,減少單點。
  3. 服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於介面名查詢服務提供者的IP地址,並且能夠平滑新增或刪除服務提供者。

Dubbo採用全spring配置方式,透明化接入應用,對應用沒有任何API侵入,只需用Spring載入Dubbo的配置即可,Dubbo基於Spring的Schema擴充套件進行載入。

Dubbo架構
這裡寫圖片描述

Provider: 暴露服務的服務提供方。
Consumer: 呼叫遠端服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的呼叫次調和呼叫時間的監控中心。
Container: 服務執行容器。

呼叫關係說明

  1. 服務容器負責啟動,載入,執行服務提供者。
  2. 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  3. 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  4. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
  5. 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
  6. 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。

連通性

  1. 註冊中心負責服務地址的註冊與查詢,相當於目錄服務,服務提供者和消費者只在啟動時與註冊中心互動,註冊中心不轉發請求,壓力較小
  2. 監控中心負責統計各服務呼叫次數,呼叫時間等,統計先在記憶體彙總後每分鐘一次傳送到監控中心伺服器,並以報表展示
  3. 服務提供者向註冊中心註冊其提供的服務,並彙報呼叫時間到監控中心,此時間不包含網路開銷
  4. 服務消費者向註冊中心獲取服務提供者地址列表,並根據負載演算法直接呼叫提供者,同時彙報呼叫時間到監控中心,此時間包含網路開銷
  5. 註冊中心,服務提供者,服務消費者三者之間均為長連線,監控中心除外
  6. 註冊中心通過長連線感知服務提供者的存在,服務提供者宕機,註冊中心將立即推送事件通知消費者
  7. 註冊中心和監控中心全部宕機,不影響已執行的提供者和消費者,消費者在本地快取了提供者列表
  8. 註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者

健狀性

  1. 監控中心宕掉不影響使用,只是丟失部分取樣資料
  2. 資料庫宕掉後,註冊中心仍能通過快取提供服務列表查詢,但不能註冊新服務
  3. 註冊中心對等叢集,任意一臺宕掉後,將自動切換到另一臺
  4. 註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地快取通訊
  5. 服務提供者無狀態,任意一臺宕掉後,不影響使用
  6. 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復

消費者和服務提供者配置檔案
comsumer

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://code.alibabatech.com/schema/dubbo        
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- dubbo配置 -->
    <!-- 服務提供方 名稱 計算機使用 -->
    <dubbo:application id="*" name="***" />
    <!-- 配置註冊中心 -->
    <dubbo:registry protocol="zookeeper" address="zookeeper1.***.com:2181"  file="/root/.dubbo/dubbo-registry/dubbo-registry.properties" check="true" />
    <!-- dubbo的埠 預設是20880 -->
    <dubbo:protocol name="dubbo" port="31881" host="127.0.0.1" />
    <!-- 暴露的服務介面 -->
    <dubbo:service interface="com.***.***.CoreNewsService" ref="newsService" timeout="1200000" />
</beans>

provider

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://code.alibabatech.com/schema/dubbo        
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- dubbo配置 -->
    <!-- 服務提供方 名稱 計算機使用 -->
    <dubbo:application id="***" name="***" />
    <!-- 配置註冊中心 -->
    <dubbo:registry protocol="zookeeper" address="zookeeper1.binggou.com:2181"  file="/root/.dubbo/dubbo-registry/dubbo-registry.properties" check="true" />
    <!-- <dubbo:registry address="N/A" register="false"/> -->
    <!-- dubbo的埠 預設是20880 -->
    <dubbo:protocol name="dubbo" port="31881" host="127.0.0.1" />
    <!-- 暴露的服務介面 -->
    <dubbo:service interface="com.***.***.CoreNewsService" ref="newsService" timeout="1200000" />
</beans>

Redis

Redis 是完全開源免費的,是一個高效能的key-value資料庫。

Redis 與其他 key - value 快取產品有以下三個特點:
Redis支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。
Redis不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存。
Redis支援資料的備份,即master-slave模式的資料備份。

String:Strings 資料結構是簡單的key-value型別,value其實不僅是String,也可以是數字.String在redis內部儲存預設就是一個字串,被redisObject所引用,當遇到incr,decr等操作時會轉成數值型進行計算,此時redisObject的encoding欄位為int。

Hash:Hash對應Value內部實際就是一個HashMap,實際這裡會有2種不同實現,這個Hash的成員比較少時Redis為了節省記憶體會採用類似一維陣列的方式來緊湊儲存,而不會採用真正的HashMap結構,對應的value redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。

List:Lists 就是連結串列,相信略有資料結構知識的人都應該能理解其結構。使用Lists結構,我們可以輕鬆地實現最新訊息排行等功能。Lists的另一個應用就是訊息佇列,可以利用Lists的PUSH操作,將任務存在Lists中,然後工作執行緒再用POP操作將任務取出進行執行。Redis還提供了操作Lists中某一段的api,你可以直接查詢,刪除Lists中某一段的元素。
Redis list的實現為一個雙向連結串列,即可以支援反向查詢和遍歷,更方便操作,不過帶來了部分額外的記憶體開銷,Redis內部的很多實現,包括髮送緩衝佇列等也都是用的這個資料結構。

Set:set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。

Sorted set:sorted set的內部使用HashMap和跳躍表(SkipList)來保證資料的儲存和有序,HashMap裡放的是成員到score的對映,而跳躍表裡存放的是所有的成員,排序依據是HashMap裡存的score,使用跳躍表的結構可以獲得比較高的查詢效率,並且在實現上比較簡單。

sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過使用者額外提供一個優先順序(score)的引數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set資料結構,比如twitter 的public timeline可以以發表時間作為score來儲存,這樣獲取時就是自動按時間排好序的。另外還可以用Sorted Sets來做帶權重的佇列,比如普通訊息的score為1,重要訊息的score為2,然後工作執行緒可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

pub/sub:Pub/Sub 從字面上理解就是釋出(Publish)與訂閱(Subscribe),在Redis中,你可以設定對某一個key值進行訊息釋出及訊息訂閱,當一個key值上進行了訊息釋出後,所有訂閱它的客戶端都會收到相應的訊息。這一功能最明顯的用法就是用作實時訊息系統,比如普通的即時聊天,群聊等功能。

Transactions:Redis的Transactions提供的並不是嚴格的ACID的事務(比如一串用EXEC提交執行的命令,在執行中伺服器宕機,那麼會有一部分命令執行了,剩下的沒執行),但是這個Transactions還是提供了基本的命令打包執行的功能(在伺服器不出問題的情況下,可以保證一連串的命令是順序在一起執行的,中間有會有其它客戶端命令插進來執行)。Redis還提供了一個Watch功能,你可以對一個key進行Watch,然後再執行Transactions,在這過程中,如果這個Watched的值進行了修改,那麼這個Transactions會發現並拒絕執行。

Redis實際應用場景

1、顯示最新的專案列表
下面這個語句常用來顯示最新專案,隨著資料多了,查詢毫無疑問會越來越慢。

SELECT * FROM foo WHERE … ORDER BY time DESC LIMIT 10

在Web應用中,“列出最新的回覆”之類的查詢非常普遍,這通常會帶來可擴充套件性問題。這令人沮喪,因為專案本來就是按這個順序被建立的,但要輸出這個順序卻不得不進行排序操作。

類似的問題就可以用Redis來解決。比如說,我們的一個Web應用想要列出使用者貼出的最新20條評論。在最新的評論邊上我們有一個“顯示全部”的連結,點選後就可以獲得更多的評論。

我們假設資料庫中的每條評論都有一個唯一的遞增的ID欄位。

我們可以使用分頁來製作主頁和評論頁,使用Redis的模板,每次新評論發表時,我們會將它的ID新增到一個Redis列表:

LPUSH latest.comments

我們將列表裁剪為指定長度,因此Redis只需要儲存最新的5000條評論:
LTRIM latest.comments 0 5000
每次我們需要獲取最新評論的專案範圍時,我們呼叫一個函式來完成(使用虛擬碼):

FUNCTION get_latest_comments(start, num_items):  
    id_list = redis.lrange("latest.comments",start,start+num_items - 1)  
    IF id_list.length < num_items  
        id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")  
    END  
    RETURN id_list  
END  

這裡我們做的很簡單。在Redis中我們的最新ID使用了常駐快取,這是一直更新的。但是我們做了限制不能超過5000個ID,因此我們的獲取ID函式會一直詢問Redis。只有在start/count引數超出了這個範圍的時候,才需要去訪問資料庫。

我們的系統不會像傳統方式那樣“重新整理”快取,Redis例項中的資訊永遠是一致的。SQL資料庫(或是硬碟上的其他型別資料庫)只是在使用者需要獲取“很遠”的資料時才會被觸發,而主頁或第一個評論頁是不會麻煩到硬碟上的資料庫了。

2、刪除與過濾
我們可以使用LREM來刪除評論。如果刪除操作非常少,另一個選擇是直接跳過評論條目的入口,報告說該評論已經不存在。

有些時候你想要給不同的列表附加上不同的過濾器。如果過濾器的數量受到限制,你可以簡單的為每個不同的過濾器使用不同的Redis列表。畢竟每個列表只有5000條專案,但Redis卻能夠使用非常少的記憶體來處理幾百萬條專案。

3、排行榜相關
另一個很普遍的需求是各種資料庫的資料並非儲存在記憶體中,因此在按得分排序以及實時更新這些幾乎每秒鐘都需要更新的功能上資料庫的效能不夠理想。

典型的比如那些線上遊戲的排行榜,比如一個Facebook的遊戲,根據得分你通常想要:

     - 列出前100名高分選手

     - 列出某使用者當前的全球排名

這些操作對於Redis來說小菜一碟,即使你有幾百萬個使用者,每分鐘都會有幾百萬個新的得分。

模式是這樣的,每次獲得新得分時,我們用這樣的程式碼:

  ZADD leaderboard  <score>  <username> 

你可能用userID來取代username,這取決於你是怎麼設計的。

得到前100名高分使用者很簡單:ZREVRANGE leaderboard 0 99。

使用者的全球排名也相似,只需要:ZRANK leaderboard 。

4、按照使用者投票和時間排序

排行榜的一種常見變體模式就像Reddit或Hacker News用的那樣,新聞按照類似下面的公式根據得分來排序:

score = points / time^alpha

因此使用者的投票會相應的把新聞挖出來,但時間會按照一定的指數將新聞埋下去。下面是我們的模式,當然演算法由你決定。

模式是這樣的,開始時先觀察那些可能是最新的專案,例如首頁上的1000條新聞都是候選者,因此我們先忽視掉其他的,這實現起來很簡單。

每次新的新聞貼上來後,我們將ID新增到列表中,使用LPUSH + LTRIM,確保只取出最新的1000條專案。
有一項後臺任務獲取這個列表,並且持續的計算這1000條新聞中每條新聞的最終得分。計算結果由ZADD命令按照新的順序填充生成列表,老新聞則被清除。這裡的關鍵思路是排序工作是由後臺任務來完成的。

5、處理過期專案

另一種常用的專案排序是按照時間排序。我們使用unix時間作為得分即可。
模式如下:
- 每次有新專案新增到我們的非Redis資料庫時,我們把它加入到排序集合中。這時我們用的是時間屬性,current_time和time_to_live。
- 另一項後臺任務使用ZRANGE…SCORES查詢排序集合,取出最新的10個專案。如果發現unix時間已經過期,則在資料庫中刪除條目。

6、計數

Redis是一個很好的計數器,這要感謝INCRBY和其他相似命令。

我相信你曾許多次想要給資料庫加上新的計數器,用來獲取統計或顯示新資訊,但是最後卻由於寫入敏感而不得不放棄它們。
好了,現在使用Redis就不需要再擔心了。有了原子遞增(atomic increment),你可以放心的加上各種計數,用GETSET重置,或者是讓它們過期。

   例如這樣操作:

     INCR user:<id> EXPIRE 

     user:<id> 60 

你可以計算出最近使用者在頁面間停頓不超過60秒的頁面瀏覽量,當計數達到比如20時,就可以顯示出某些條幅提示,或是其它你想顯示的東西。

7、特定時間內的特定專案

另一項對於其他資料庫很難,但Redis做起來卻輕而易舉的事就是統計在某段特點時間裡有多少特定使用者訪問了某個特定資源。比如我想要知道某些特定的註冊使用者或IP地址,他們到底有多少訪問了某篇文章。

每次我獲得一次新的頁面瀏覽時我只需要這樣做:
SADD page:day1:
當然你可能想用unix時間替換day1,比如time()-(time()%3600*24)等等。
想知道特定使用者的數量嗎?只需要使用SCARD page:day1:。
需要測試某個特定使用者是否訪問了這個頁面?SISMEMBER page:day1:。

8、實時分析正在發生的情況,用於資料統計與防止垃圾郵件等

我們只做了幾個例子,但如果你研究Redis的命令集,並且組合一下,就能獲得大量的實時分析方法,有效而且非常省力。使用Redis原語命令,更容易實施垃圾郵件過濾系統或其他實時跟蹤系統。

9、Pub/Sub
Redis的Pub/Sub非常非常簡單,執行穩定並且快速。支援模式匹配,能夠實時訂閱與取消頻道。

10、佇列

你應該已經注意到像list push和list pop這樣的Redis命令能夠很方便的執行佇列操作了,但能做的可不止這些:比如Redis還有list pop的變體命令,能夠在列表為空時阻塞佇列。

現代的網際網路應用大量地使用了訊息佇列(Messaging)。訊息佇列不僅被用於系統內部元件之間的通訊,同時也被用於系統跟其它服務之間的互動。訊息佇列的使用可以增加系統的可擴充套件性、靈活性和使用者體驗。非基於訊息佇列的系統,其執行速度取決於系統中最慢的元件的速度(注:短板效應)。而基於訊息佇列可以將系統中各元件解除耦合,這樣系統就不再受最慢元件的束縛,各元件可以非同步執行從而得以更快的速度完成各自的工作。

此外,當伺服器處在高併發操作的時候,比如頻繁地寫入日誌檔案。可以利用訊息佇列實現非同步處理。從而實現高效能的併發操作。

11、快取
Redis的快取部分值得寫一篇新文章,我這裡只是簡單的說一下。Redis能夠替代memcached,讓你的快取從只能儲存資料變得能夠更新資料,因此你不再需要每次都重新生成資料了。

MQ(訊息佇列)

訊息即是資訊的載體。為了讓訊息傳送者和訊息接收者都能夠明白訊息所承載的資訊(訊息傳送者需要知道如何構造訊息;訊息接收者需要知道如何解析訊息),它們就需要按照一種統一的格式描述訊息,這種統一的格式稱之為訊息協議。所以,有效的訊息一定具有某一種格式;而沒有格式的訊息是沒有意義的。

而訊息從傳送者到接收者的方式也有兩種。一種我們可以稱為即時訊息通訊,也就是說訊息從一端發出後(訊息傳送者)立即就可以達到另一端(訊息接收者),這種方式的具體實現就是RPC(當然單純的http通訊也滿足這個定義);另一種方式稱為延遲訊息通訊,即訊息從某一端發出後,首先進入一個容器進行臨時儲存,當達到某種條件後,再由這個容器傳送給另一端。 這個容器的一種具體實現就是訊息佇列

訊息佇列中介軟體是分散式系統中重要的元件,主要解決應用耦合非同步訊息流量削鋒等問題,實現高效能,高可用,可伸縮和最終一致性架構。
使用較多的訊息佇列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ,IBM WebSphere MQ

應用場景

1.非同步處理
場景說明:使用者註冊後,需要發註冊郵件註冊簡訊。傳統的做法有兩種 1.序列的方式;2.並行方式
序列方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件,再發送註冊簡訊。以上三個任務全部完成後,返回給客戶端
並行方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件的同時,傳送註冊簡訊。以上三個任務完成後,返回給客戶端。與序列的差別是,並行的方式可以提高處理的時間

假設三個業務節點每個使用50毫秒鐘,不考慮網路等其他開銷,則序列方式的時間是150毫秒,並行的時間可能是100毫秒。因為CPU在單位時間內處理的請求數是一定的,假設CPU1秒內吞吐量是100次。則序列方式1秒內CPU可處理的請求量是7次(1000/150)。並行方式處理的請求量是10次(1000/100)

如以上案例描述,傳統的方式系統的效能(併發量,吞吐量,響應時間)會有瓶頸。

引入訊息佇列,將不是必須的業務邏輯,非同步處理。改造後的架構如下:
這裡寫圖片描述
使用者的響應時間相當於是註冊資訊寫入資料庫的時間,也就是50毫秒。註冊郵件,傳送簡訊寫入訊息佇列後,直接返回,因此寫入訊息佇列的速度很快,基本可以忽略,因此使用者的響應時間可能是50毫秒。因此架構改變後,系統的吞吐量提高到每秒20 QPS。比序列提高了3倍,比並行提高了兩倍。

2.應用解耦

場景說明:使用者下單後,訂單系統需要通知庫存系統。
這裡寫圖片描述

傳統的做法是:訂單系統呼叫庫存系統的介面

傳統模式的缺點:

  1. 假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗
  2. 訂單系統與庫存系統耦合

引入訊息佇列:
這裡寫圖片描述

訂單系統:使用者下單後,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功
庫存系統:訂閱下單的訊息,採用拉/推的方式,獲取下單資訊,庫存系統根據下單資訊,進行庫存操作
假如:在下單時庫存系統不能正常使用。也不影響正常下單,因為下單後,訂單系統寫入訊息佇列就不再關心其他的後續操作了。實現訂單系統與庫存系統的應用解耦

3.流量削鋒
流量削鋒也是訊息佇列中的常用場景,一般在秒殺或團搶活動中使用廣泛

應用場景:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入訊息佇列。

步驟:

  1. 對於使用者的請求,伺服器接收後,首先寫入訊息佇列。假如訊息佇列長度超過最大數量,則直接拋棄使用者請求或跳轉到錯誤頁面
  2. 秒殺業務根據訊息佇列中的請求資訊,再做後續處理

優點:

  1. 可以控制活動的人數
  2. 可以緩解短時間內高流量壓垮應用

4.日誌處理

日誌處理是指將訊息佇列用在日誌處理中,比如Kafka的應用,解決大量日誌傳輸的問題。

IBM WebSphere MQ 十大優勢

  1. 強健的訊息傳遞中介軟體,為高價值的商業資料傳輸提供可靠保證
    • 資訊的傳遞是“傳一次且僅一次,- 不- 丟失,- 不- 重傳”
    • 系統或線路發生故障時,- 自動恢復,- 不- 需人為干涉,- 業務不- 受到影響。
  2. 支援多達35個不同平臺,具有最廣的連通性
  3. 統一開發介面,跨越35種平臺,並完全相同。
    • 常用就兩個API,- 簡單的”MQPUT”和”MQGET”即可完成在35種平臺上的開發。
    • 不- 必考慮作業系統和通訊,- 特別是底層的網路通訊,- 節省大約50%到75%的通訊程式設計工作。
  4. 基於鬆耦合環境的機制,隨時根據業務變化改變IT環境變化
    • 是發展EAI, BPM等業務整合和應用整合的基礎。
  5. 應用觸發機制,大大地節省了系統資源。
    • WebSphere MQ應用程式不必總是在執行中的。當資訊到達一個指定的佇列時,一個應用可以有選擇的被觸發起來,大大地節省了系統資源,
  6. 支援複雜拓撲結構的動態負載均衡、群集、路由等,大大提高了系統的效能、可靠性和靈活性。
  7. 支援事務處理,保證資料完整性,適用同步和非同步的事務處理應用。
  8. 遵循開放標準,可靠投資保護,支援JMS標準,能夠實現與J2EE應用伺服器的無縫連線。
  9. 佔據訊息通訊中介軟體81%以上的市場,是業界事實的工業標準
  10. WebSphere MQ是IBM業界領先的企業應用整合和業務流程整合的基礎

Flowable

工作流引擎:所謂工作流引擎是指工作流作為應用系統的一部分,併為之提供對各應用系統有決定作用的根據角色、分工和條件的不同決定資訊傳遞路由、內容等級等核心解決方案。工作流引擎包括了,流程的節點管理、流向管理、流程樣例管理等重要功能。

例如開發一個系統最關鍵的部分不是系統的介面,也不是和資料庫之間的資訊交換,而是如何根據業務邏輯開發出符合實際需要的程式邏輯並確保其穩定性、易維護性(模組化和結構化)和彈性(容易根據實際業務邏輯的變化作出程式上的變動,例如決策權的改變、組織結構的變動和由於業務方向的變化產生的全新業務邏輯等等)。 工作流引擎解決的就是這個問題:如果應用程式缺乏強大的邏輯層,勢必變得容易出錯(資訊的路由錯誤、死迴圈等等)。

會組成如圖的流程定義:
這裡寫圖片描述
每一個節點如何到下一個節點,通過設定來確定,其會根據設定自動走到下一個流程。

Flowable是一個使用Java編寫的輕量級工作流引擎。Flowable流程引擎讓你可以部署BPMN 2.0流程定義、建立這些流程定義的流程例項、進行查詢、訪問執行中或歷史的流程例項與相關資料,等等。

Flowable可以十分靈活地加入你的應用/服務/構架。可以將JAR形式釋出的Flowable庫加入應用或服務,來嵌入引擎。以JAR形式釋出使Flowable可以輕易加入任何Java環境:Java SE;Tomcat、Jetty或Spring之類的servlet容器;JBoss或WebSphere之類的Java EE伺服器,等等。另外,也可以使用Flowable REST API通過HTTP通訊。也有許多Flowable應用(Flowable Modeler, Flowable Admin, Flowable IDM 與 Flowable Task),提供了直接可用的UI示例,可以使用流程與任務。

所有設定Flowable方法的共同點是核心引擎。核心引擎可被看做是一組服務的集合,並暴露了管理與執行業務流程的API。

FlowableActivit分支

Jwt

JWT簡單的說是一種token的實現方式,一般用來身份驗證的場景。

身份認證在這種場景下,一旦使用者完成了登陸,在接下來的每個請求中包含JWT,可以用來驗證使用者身份以及對路由,服務和資源的訪問許可權進行驗證。由於它的開銷非常小,可以輕鬆的在不同域名的系統中傳遞,所有目前在單點登入(SSO)中比較廣泛的使用了該技術。 資訊交換在通訊的雙方之間使用JWT對資料進行編碼是一種非常安全的方式,由於它的資訊是經過簽名的,可以確保傳送者傳送的資訊是沒有經過偽造的。

JWT的結構
JWT包含了使用.分隔的三部分: Header 頭部 Payload 負載 Signature 簽名

其結構看起來是這樣的Header.Payload.Signature
Header:在header中通常包含了兩部分:token型別和採用的加密演算法。{ “alg”: “HS256”, “typ”: “JWT”} 接下來對這部分內容使用 Base64Url 編碼組成了JWT結構的第一部分。
Payload:Token的第二部分是負載,它包含了claim, Claim是一些實體(通常指的使用者)的狀態和額外的元資料,有三種類型的claim:reserved, public 和 private.Reserved claims: 這些claim是JWT預先定義的,在JWT中並不會強制使用它們,而是推薦使用,常用的有 iss(簽發者),exp(過期時間戳), sub(面向的使用者), aud(接收方), iat(簽發時間)。 Public claims:根據需要定義自己的欄位,注意應該避免衝突 Private claims:這些是自定義的欄位,可以用來在雙方之間交換資訊 負載使用的例子:{ “sub”: “1234567890”, “name”: “John Doe”, “admin”: true} 上述的負載需要經過Base64Url編碼後作為JWT結構的第二部分。
Signature:建立簽名需要使用編碼後的header和payload以及一個祕鑰,使用header中指定簽名演算法進行簽名。例如如果希望使用HMAC SHA256演算法,那麼簽名應該使用下列方式建立: HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret) 簽名用於驗證訊息的傳送者以及訊息是沒有經過篡改的。 完整的JWT 完整的JWT格式的輸出是以. 分隔的三段Base64編碼,與SAML等基於XML的標準相比,JWT在HTTP和HTML環境中更容易傳遞。 下列的JWT展示了一個完整的JWT格式,它拼接了之前的Header, Payload以及祕鑰簽名:
這裡寫圖片描述

如何使用JWT

在身份鑑定的實現中,傳統方法是在服務端儲存一個session,給客戶端返回一個cookie,而使用JWT之後,當用戶使用它的認證資訊登陸系統之後,會返回給使用者一個JWT,使用者只需要本地儲存該token(通常使用local storage,也可以使用cookie)即可。 當用戶希望訪問一個受保護的路由或者資源的時候,通常應該在Authorization頭部使用Bearer模式新增JWT,其內容看起來是下面這樣:Authorization: Bearer <token>

因為使用者的狀態在服務端的記憶體中是不儲存的,所以這是一種無狀態的認證機制。服務端的保護路由將會檢查請求頭Authorization中的JWT資訊,如果合法,則允許使用者的行為。由於JWT是自包含的,因此減少了需要查詢資料庫的需要。 JWT的這些特性使得我們可以完全依賴其無狀態的特性提供資料API服務,甚至是建立一個下載流服務。因為JWT並不使用Cookie的,所以你可以使用任何域名提供你的API服務而不需要擔心跨域資源共享問題(CORS)。 下面的序列圖展示了該過程:
這裡寫圖片描述

為什麼要使用JWT

相比XML格式,JSON更加簡潔,編碼之後更小,這使得JWT比SAML更加簡潔,更加適合在HTML和HTTP環境中傳遞。 在安全性方面,SWT只能夠使用HMAC演算法和共享的對稱祕鑰進行簽名,而JWT和SAML token則可以使用X.509認證的公私祕鑰對進行簽名。與簡單的JSON相比,XML和XML數字簽名會引入複雜的安全漏洞。 因為JSON可以直接對映為物件,在大多數程式語言中都提供了JSON解析器,而XML則沒有這麼自然的文件-物件對映關係,這就使得使用JWT比SAML更方便 java json web token工具類

Beetl

模板引擎:是為了使使用者介面與業務資料(內容)分離而產生的,它可以生成特定格式的文件,用於網站的模板引擎就會生成一個標準的HTML文件。

模板引擎不屬於特定技術領域,它是跨領域跨平臺的概念。不只是java中有。在Asp下有模板引擎,在PHP下也有模板引擎,在C#下也有,甚至JavaScript、WinForm開發都會用到模板引擎技術。
java中比較流行的模板引擎包括freemarker ,velocity,以及下面的Beetl,各有所長。

Beetl是一款java的模版引擎,用於生成我們常用的java程式碼,無論是前端html程式碼、後端邏輯程式碼、資料庫的sql程式碼等等,都可以根據模板進行生成對應的程式碼。

相對於其他java模板引擎,具有功能齊全,語法直觀,效能超高,以及編寫的模板容易維護等特點。使得開發和維護模板有很好的體驗。是新一代的模板引擎。總得來說,它的特性如下:

功能完備:作為主流模板引擎,Beetl具有相當多的功能和其他模板引擎不具備的功能。適用於各種應用場景,從對響應速度有很高要求的大網站到功能繁多的CMS管理系統都適合。Beetl本身還具有很多獨特功能來完成模板編寫和維護,這是其他模板引擎所不具有的。
非常簡單:類似Javascript語法和習俗,只要半小時就能通過半學半猜完全掌握用法。拒絕其他模板引擎那種非人性化的語法和習俗。同時也能支援html 標籤,使得開發CMS系統比較容易
超高的效能:Beetl 遠超過主流java模板引擎效能(引擎效能5-6倍與freemaker,2倍於JSP。參考附錄),而且消耗較低的CPU。
易於整合:Beetl能很容易的與各種web框架整合,如Spring MVC,JFinal,Struts,Nutz,Jodd,Servlet等。
支援模板單獨開發和測試,即在MVC架構中,即使沒有M和C部分,也能開發和測試模板。
擴充套件和個性化:Beetl支援自定義方法,格式化函式,虛擬屬性,標籤,和HTML標籤. 同時Beetl也支援自定義佔位符和控制語句起始符號也支援使用者完全可以打造適合自己的工具包。
可以擴充套件為指令碼引擎,規則引擎,能定製引擎從而實現高階功能。

效能

在使用FastRuntimeEngine情況下,通過與主流模板引擎Freemarker,Vecloity以及JSP對比,Beetl6倍於Freemarker2倍於JSP。這是因為巨集觀上,通過了優化的渲染引擎,IO的二進位制輸出,位元組碼屬性訪問增強,微觀上,通過一維陣列儲存上下文Context,靜態文字合併處理,通過重複使用位元組陣列來防止java頻繁的建立和銷燬陣列,還使用模板快取,執行時優化等方法。

NoSql

在現代的計算系統上每天網路上都會產生龐大的資料量。這些資料有很大一部分是由關係資料庫管理系統(RDBMS)來處理。 1970年 E.F.Codd’s提出的關係模型的論文 “A relational model of data for large shared data banks”,這使得資料建模和應用程式程式設計更加簡單。

通過應用實踐證明,關係模型是非常適合於客戶伺服器程式設計,遠遠超出預期的利益,今天它是結構化資料儲存在網路和商務應用的主導技術。

NoSQL 是一項全新的資料庫革命性運動,早期就有人提出,發展至2009年趨勢越發高漲。NoSQL的擁護者們提倡運用非關係型的資料儲存,相對於鋪天蓋地的關係型資料庫運用,這一概念無疑是一種全新的思維的注入。

關係型資料庫遵循ACID規則
事務在英文中是transaction,和現實世界中的交易很類似,它有如下四個特性:

  1. A (Atomicity) 原子性:原子性很容易理解,也就是說事務裡的所有操作要麼全部做完,要麼都不做,事務成功的條件是事務裡的所有操作都成功,只要有一個操作失敗,整個事務就失敗,需要回滾。
    比如銀行轉賬,從A賬戶轉100元至B賬戶,分為兩個步驟:1)從A賬戶取100元;2)存入100元至B賬戶。這兩步要麼一起完成,要麼一起不完成,如果只完成第一步,第二步失敗,錢會莫名其妙少了100元。

  2. C (Consistency) 一致性:一致性也比較容易理解,也就是說資料庫要一直處於一致的狀態,事務的執行不會改變資料庫原本的一致性約束。
    例如現有完整性約束a+b=10,如果一個事務改變了a,那麼必須得改變b,使得事務結束後依然滿足a+b=10,否則事務失敗。

  3. I (Isolation) 獨立性:所謂的獨立性是指併發的事務之間不會互相影響,如果一個事務要訪問的資料正在被另外一個事務修改,只要另外一個事務未提交,它所訪問的資料就不受未提交事務的影響。
    比如現在有個交易是從A賬戶轉100元至B賬戶,在這個交易還未完成的情況下,如果此時B查詢自己的賬戶,是看不到新增加的100元的。

  4. D (Durability) 永續性:永續性是指一旦事務提交後,它所做的修改將會永久的儲存在資料庫上,即使出現宕機也不會丟失。

分散式系統

分散式系統(distributed system)由多臺計算機和通訊的軟體元件通過計算機網路連線(本地網路或廣域網)組成。
分散式系統是建立在網路之上的軟體系統。正是因為軟體的特性,所以分散式系統具有高度的內聚性和透明性。
因此,網路和分散式系統之間的區別更多的在於高層軟體(特別是作業系統),而不是硬體。
分散式系統可以應用在不同的平臺上如:Pc、工作站、區域網和廣域網上等。

分散式計算的優點

可靠性(容錯) :分散式計算系統中的一個重要的優點是可靠性。一臺伺服器的系統崩潰並不影響到其餘的伺服器。
可擴充套件性:在分散式計算系統可以根據需要增加更多的機器。
資源共享:共享資料是必不可少的應用,如銀行,預訂系統。
靈活性:由於該系統是非常靈活的,它很容易安裝,實施和除錯新的服務。
更快的速度:分散式計算系統可以有多臺計算機的計算能力,使得它比其他系統有更快的處理速度。
開放系統:由於它是開放的系統,本地或者遠端都可以訪問到該服務。
更高的效能:相較於集中式計算機網路叢集可以提供更高的效能(及更好的價效比)。

分散式計算的缺點

故障排除:故障排除和診斷問題。
軟體:更少的軟體支援是分散式計算系統的主要缺點。
網路:網路基礎設施的問題,包括:傳輸問題,高負載,資訊丟失等。
安全性:開放系統的特性讓分散式計算系統存在著資料的安全性和共享的風險等問題。

Nosq簡介

NoSQL,指的是非關係型的資料庫。NoSQL有時也稱作Not Only SQL的縮寫,是對不同於傳統的關係型資料庫的資料庫管理系統的統稱。

NoSQL用於超大規模資料的儲存。(例如谷歌或Facebook每天為他們的使用者收集萬億位元的資料)。這些型別的資料儲存不需要固定的模式,無需多餘操作就可以橫向擴充套件。

RDBMS vs NoSQL(關係型資料庫VS非關係型資料庫)

RDBMS NoSQL
高度組織化結構化資料 代表著不僅僅是SQL
結構化查詢語言(SQL) (SQL) 沒有宣告性查詢語言
資料和關係都儲存在單獨的表中。 沒有預定義的模式
資料操縱語言,資料定義語言 鍵 - 值對儲存,列儲存,文件儲存,圖形資料庫
嚴格的一致性 最終一致性,而非ACID屬性
基礎事務 非結構化和不可預知的資料
- 高效能,高可用性和可伸縮性
- CAP定理

CAP定理(CAP theorem)

在電腦科學中, CAP定理(CAP theorem), 又被稱作 布魯爾定理(Brewer’s theorem), 它指出對於一個分散式計算系統來說,不可能同時滿足以下三點:

  • 一致性(Consistency) (所有節點在同一時間具有相同的資料)
  • 可用性(Availability) (保證每個請求不管成功或者失敗都有響應)
  • 分隔容忍(Partition tolerance) (系統中任意資訊的丟失或失敗不會影響系統的繼續運作)

CAP理論的核心是:一個分散式系統不可能同時很好的滿足一致性,可用性和分割槽容錯性這三個需求,最多隻能同時較好的滿足兩個。

因此,根據 CAP 原理將 NoSQL 資料庫分成了滿足 CA 原則、滿足 CP 原則和滿足 AP 原則三 大類:

  • CA - 單點叢集,滿足一致性,可用性的系統,通常在可擴充套件性上不太強大。
  • CP - 滿足一致性,分割槽容忍性的系統,通常效能不是特別高。
  • AP - 滿足可用性,分割槽容忍性的系統,通常可能對一致性要求低一些。

NoSQL 資料庫分類

型別 部分代表 特點
列儲存 Hbase、Cassandra、Hypertable 顧名思義,是按列儲存資料的。最大的特點是方便儲存結構化和半結構化資料,方便做資料壓縮,對針對某一列或者某幾列的查詢有非常大的IO優勢。
文件儲存 MongoDB、CouchDB 文件儲存一般用類似json