2020 Java/JVM/Springboot/SpringCloud/Redis/Oracle詳解

一、Java基礎

1.集合(數據結構:數組 、鏈表、棧和隊列、二叉樹、堆和堆棧、散列表、紅黑樹

   1.1 List:元素按進入先後有序保存,可重複。

(1)ArrayList: 底層數據結構是數組,查詢快,增刪慢,線程不安全,效率高,可存貯重複元素;

(2)LinkList: 底層數據結構是鏈表,查詢慢,增刪快,線程不安全,效率高,可存貯重複元素;

(3)Vector: 底層數據結構是數組,查詢快,增刪慢,線程安全,效率低,可存貯重複元素;

 1.2 Set: 僅接收一次,不可重複,並做內部排序,唯一性需重寫hashcode和equals方法。

(1) HashSet: 底層數據結構採用哈希表實現,元素無序且唯一,線程不安全,效率高;

(2) ListHashSet: 底層數據結構鏈表+hash,有序且唯一,線程不安全,效率高;

(3) TreeSet: 底層數據結構採用二叉樹實現,有序且唯一;

 1.3 Map:

  (1) HashMap: 非線程安全 

      a. 底層數據結構: 基於hash表, 數組+ 鏈表(jdk1.8加入紅黑樹);當鏈表的長度 >= 8的時候,將鏈表轉換成紅黑樹;

       紅黑樹數量 <= 6,紅黑樹轉換爲鏈表;

      b. HashMap主幹是一個靜態內部類Entry,包含key,value,next,  hash;

     c. 初始化容量initialCapacity默認16,加載因子默認0.75, 實際容量 = 負載因子 x 容量,也就是 12 = 0.75 x 16;

     d. 數組長度一定是2的次冪, 方便&二進制中的與運算,  減少hash衝突;

     e. Hash衝突:一種是開放尋址法,另一種是鏈表法

      兩個節點的key值相同(hash值一定相同),導致衝突
      兩個節點的key值不同,由於hash函數的侷限性導致hash值相同,導致衝突
      兩個節點的key值不同,hash值不同,但hash值對數組長度取模後相同,導致衝突

     解決hash衝突:

     鏈表法也正是被應用HashMap中,每一個Entry對象通過next指針指向它的下一個Entry節點。當新來的Entry映射到與之衝突的數組位置時,只需要插入到對應的鏈表中即可。

     f. 允許使用 null 做爲值(key)和鍵(value)

     g. 解決線程安全問題:

       Map<String, Integer> map = Collections.synchronizedMap(hashMap)

  (2) HashTable: 線程安全,加入synchronized關鍵字

2.多線程

2.1 多線程狀態:

線程在一定條件下,狀態會發生變化。線程變化的狀態轉換圖如下:

200705181179465004843.png

(1)、新建狀態(New):新創建了一個線程對象。

(2)、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。

(3)、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

(4)、阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:

(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。

(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。

(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

(5)、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

2.2 線程調度:

  • a. sleep 線程轉到阻塞狀態,結束後轉爲就緒;
  • b. wait 當前線程等待,notify或notifyAll喚醒;
  • c. yield 暫定當前正在執行線程對象,讓相同或者優先級高的線程執行;
  • d. join 等待其他線程終止,當前線程調用另一個線程join,當前線程轉入阻塞,直到另一個線程結束,當前線程阻塞轉爲就緒,如多個線程統計累加數量。

2.3 併發編程三大特性:可見性、原子性、有序性

(1) Volatile保證變量可見性與有序性,但不能保證原子性,原子性要藉助synchronized這樣的鎖機制。

 (2)JMM內存模型

所有的變量都存儲在主內存中, 總線MESI緩存一致性協議,store寫回內存操作,會使其他CPU緩存地址數據無效

(3) Synchronized關鍵字: 鎖是存在對象頭裏面。

a. 三種方式:

  •   A. 修飾普通方法: new出來的實例對象鎖;
  •   B. 修飾靜態方法: 其鎖就是當前類的class對象鎖;
  •   C. 修飾代碼塊: 實例對象鎖;

b. synchronized底層原理: 是由一對monitorenter和monitorexit指令實現的,Monitor對象是同步的基本實現單元。

  • 同步代碼塊是通過monitorenter和monitorexit來實現,當線程執行到monitorenter的時候要先獲得monitor鎖,才能執行後面的方法。當線程執行到monitorexit的時候則要釋放鎖。
  • 同步方法是通過中設置ACC_SYNCHRONIZED標誌來實現,當線程執行有ACC_SYNCHRONI標誌的方法,需要獲得monitor鎖。
  • 每個對象維護一個加鎖計數器,爲0表示可以被其他線程獲得鎖,不爲0時,只有當前鎖的線程才能再次獲得鎖。
  • 同步方法和同步代碼塊底層都是通過monitor來實現同步的。
  • 每個對象都與一個monitor相關聯,線程可以佔有或者釋放monitor。

(4)線程池

 a. Executors四種線程池:

  • newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
  • newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
  • newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
  • newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

  b. 執行方法

  • execute(Runnable): 接收的是一個Runnable實例,並異步執行,run()方法是void,沒有返回值;
  • submit(Runnable): 和execute一樣,只是會返回一個Future對象,可以檢測任務是否執行完畢;
  • submit(Callable): 接收的是一個Callable實例,Callable接口中的call()方法有返回值,可返回任務執行結果;
  • invokeAny(...): 接收的是一個Callable的集合,不會返回Future,會返回任意一個執行結果;
  • invokeAll(...): 和invokeAny一樣,返回Future的List;

3.設計模式

4.JVM

 對象包含對象頭、實例數據和填充數據三部分。

 4.1 JVM構成:字節碼命令:javap -v Test.class

4.2 五大內存區域

(1) 程序計數器:當前線程的行號指標號,記錄虛擬機字節碼指令的位置。

(2) 本地方法棧:使用native方法服務的,底層調用c或者c++;

(3) 棧:先進後出(FILO), 棧幀是一種數據結構, 入棧和出棧的一個單元。

  • 局部變量表:存放方法參數和方法內部定義的局部變量。
  • 操作數棧:把局部變量表裏的數據、實例的字段等數據入棧。(字節碼指令,壓入棧)
  • 動態鏈接:方法之間調用,符號引用和直接引用在運行時進行解析和鏈接的過程
  • 方法出口:方法調用完成,返回給調用方法的值。

  (4) 堆:

   a. 堆內存分爲年輕代、老年代

   b. 年輕代分爲Eden(伊甸園區)和Survivor,Survivor又分爲FromSpace和ToSpace。默認比例Eden:S0:S1=8:1:1。

   c. Eden存放new出來的新對象,Eden內存滿了,會進行minor GC, 每經歷一次GC年齡+1,默認年齡閾值到達15, 進入老年代。

  (5) 方法區(非堆內存):也稱元空間(Metaspace),  jdk1.8以前叫永久代(已廢棄),存儲程序運行時長期存活的對象,比如類的元       數據、方法、常量、屬性等。

  • MetaspaceSize :初始化元空間大小,控制發生GC閾值。
  • MaxMetaspaceSize : 限制元空間大小上限,防止異常佔用過多物理內存。

4.3 JVM 調優:減少fullgc次數和時間

 1. 三大GC收集算法:效率:複製算法 > 標記/整理算法 > 標記/清除算法

  • 標記/清除算法(最基礎):老年代GC算法)
    • 標記階段:對象的header中, 遍歷所有的GC Roots對象, 可達的對象(可達性分析算法)都打上一個標識。
    • 清除階段:遍歷堆內存,發現某個對象沒有被標記爲可達對象(通過讀取對象header信息),則將其收回。
  • 複製算法:(新生代GC算法) 將可用內存按容量劃分爲大小相等的兩塊,每次使用其中的一塊。當這一塊的內存用完了,就將還存活的對象複製到另一塊內存上,然後把這一塊內存所有的對象一次性清理掉。Eden區中所有存活的對象都會被複制到To Survivor區,而在From Survivor區中,仍存活的對象會根據它們的年齡值決定去向,年齡值達到年齡閥值(默認爲15,新生代中的對象每熬過一輪垃圾回收,年齡值就加1)的對象會被移到老年代中。
  • 標記整理算法: (老年代GC算法)跟標標記清除算法類似,讓所有存活的對象都向一端移動,然後直接清理掉端邊線以外的內存。

 2.調優工具:jconsole、VisualVM、jstat

   JAVA內存管理機制及配置參數:

  1. JAVA_OPTS="-server -Xms512m -Xmx2g -XX:+UseG1GC -XX:SurvivorRatio=6 -XX:MaxGCPauseMillis=400 -XX:G1ReservePercent=15 -XX:ParallelGCThreads=4 -XX:
  2. ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:../logs/gc.log"
  • 設置堆內存最小和最大值,最大值參考歷史利用率設置
  • 設置GC垃圾收集器爲G1
  • 啓用GC日誌,方便後期分析,idea配置參數(-XX:+PrintGCDetails)

 3.垃圾收集器

  • 串行收集器(Serial)
    比較老的收集器,單線程。收集時,必須暫停應用的工作線程,直到收集結束。
  • 並行收集器(Parallel)
    多條垃圾收集線程並行工作,在多核CPU下效率更高,應用線程仍然處於等待狀態。
  • CMS收集器(Concurrent Mark Sweep)
    CMS收集器是縮短暫停應用時間爲目標而設計的,是基於標記-清除算法實現,整個過程分爲4個步驟,包括:
    • 初始標記(Initial Mark)
    • 併發標記(Concurrent Mark)
    • 重新標記(Remark)
    • 併發清除(Concurrent Sweep)

初始標記、重新標記這兩個步驟仍然需要暫停應用線程(stop the world)

 4.內存溢出(OOM)

  • 老年代內存不足:java.lang.OutOfMemoryError:Javaheapspace
  • 永久代內存不足:java.lang.OutOfMemoryError:PermGenspace
  • 代碼bug,佔用內存無法及時回收。

 

二、Spring

1.Spring IOC(反射機制)

  • 依賴注入:通過諸如實例化對象,替代new對象,由Spring 容器進行管理,解耦。
  • 控制反轉:對象創建權交給是spring容器。
  • 注入三種方式:構造方法注入,setter注入,基於註解的注入。
  • 自動裝配有三種模式:byType(類型模式),byName(名稱模式)、constructor(構造函數模式)。

2.Spring AOP

(1) 面向切面編程,主要是日誌記錄、權限認證、安全控制、事務處理、異常處理。

(2) 底層原理:使用代理模式

  • JDK動態代理:必須是面向接口,目標業務類必須實現接口。通過反射代理目標信息,InvokeHandler來處理。
  • CGLIB動態代理:利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。

 如果目標對象實現了接口,默認使用JDK動態代理,也可以使用CGLIB代理;如果目標對象沒有實現接口,則必須實現CGLIB。

(3) AOP註解方式:

@Aspect 註釋修飾,聲明爲一個切面類。@Component註解註釋爲一個bean對象。

@Pointcut:定義切點。

@Around:環繞通知("execution(public * com.xxx.controller..*.*(..))")。

(4) 過濾器和攔截器

  • Filter:依賴Servlet容器,基於函數回調,filter一般實現統一設置編碼、用戶是否登錄、權限訪問等。攔截web訪問url地址。
  • Interceptor:攔截器基於Java反射,使用代理模式。可以繼承HandlerInterceptorAdapter類。攔截Action的訪問。

3.Spring MVC

(1) 流程圖

(2) 運行原理:

  • 客戶端發起Http請求到DispatcherServlet
  • DispatcherServlet控制器尋找HanderMapping, 查詢具體的Handler
  • HanderMapping調用HandlerAdapter執行handler
  • HandlerAdapter經過適配調用具體Controller,處理業務邏輯
  • Controller處理完成將ModelAndView返回DispatcherServlet
  • DispatcherServlet請求視圖解析器ViewReslover解析ModelAndView

4.Spring 事務

(1) 四個原則:

  • 原子性:一個事務要麼全部執行,要麼不執行
  • 一致性:事務執行前後數據處於正確狀態
  • 隔離性:併發事務之間互不影響
  • 持久性:事務一旦執行成功,數據永久存在

(2) 事務分類:

  • 編程式事務:在業務邏輯中自行實現事務
  • 聲明式事務:通過XML配置或者註解@Transactional實現

(3) 隔離級別

  • ISOLATION_DEFAULT:用數據庫默認隔離級別
  • ISOLATION_READ_UNCOMMITTED(未提交讀):最低隔離級別,事務未提交,可被其他事務讀取(幻讀、髒讀、不可重複讀)
  • ISOLATION_READ_COMMITTED(提交讀):一個事務修改的數據提交後才能被其他事務讀取(幻讀、不能重複讀)(Oracle默認級別)
  • ISOLATION_REPEATABLE_READ(可重複讀):保證多次讀取同一數據是一致(幻讀)(MySql默認級別)
  • ISOLATION_SERIALIZABLE(序列化):代價最高最可靠的隔離級別

(4) 事務傳播性:

  • PROPAGATION_REQUIRED:支持當前事務,如果當前沒有事務,就新建一個事務。(Spring 默認)
  • PROPAGATION_REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。
  • PROPAGATION_SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行。
  • PROPAGATION_MANDATORY:支持當前事務,如果當前沒有事務,就拋出異常
  • PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起
  • PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
  • PROPAGATION_NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中。

4.Mybatis

(1) 封裝JDBC操作,利用反射打通Java類與SQL語句之間的相互轉換

(2) 工作原理:

  • 讀取 MyBatis 配置文件:mybatis-config.xml
  • 加載映射文件。映射文件即 SQL 映射文件
  • 通過配置信息構建會話工廠 SqlSessionFactory
  • 由會話工廠創建 SqlSession 對象, 包含了執行 SQL 語句的所有方法
  • Executor 執行器:在 Executor 接口的執行方法中有一個 MappedStatement 類型的參數
  • 輸入參數映射:輸入參數類型可以是 Map、List 等集合類型,也可以是基本數據類型和 POJO 類型
  • 輸出結果映射:輸出結果類型可以是 Map、 List 等集合類型,也可以是基本數據類型和 POJO 類型

MyBatis框架的執行流程圖

三、Spring Boot/Spring Cloud

1、原理

Eureka:註冊中心,心跳機制,30時間s,最長時間90s。底層是ConcurrentHashMap實現數據存取,有多層緩存機制,讀緩存,寫緩存等多級。

2、Eureka服務註冊與發現

在這裏插入圖片描述

(1) Euraka Server:註冊中心服務端

  • 服務註冊: 服務提供者啓動時,通過Euraka Client向Euraka Server註冊元數據(IP 地址、端口、狀態等信息)。Eureka採用的是ConcurrentHashMap來存儲註冊表信息,使用二層緩存機制來維護整個註冊表。
  • 提供註冊表: 服務消費者調用服務,若本地沒有,會去服務端Euraka Server拉取存放本地。

(2) Euraka Client:Eureka Client 會拉取、更新和緩存 Eureka Server 中的信息。

(3) Renew: 服務續約,Eureka Client 會每隔 30 秒發送一次心跳來檢測續約,告知 Eureka Server 該 Eureka Client 運行正常。

如果 Eureka Server 在 90 秒內沒有收到 Eureka Client 的續約,Server 端會將實例從其註冊表中刪除。

(4) 自我保護機制:

Eureka Server 在運行期間會去統計心跳失敗比例在 15 分鐘之內是否低於 85%,如果低於 85%,Eureka Server 即會進入自我保護機制。

(5) Eureka集羣:

Eureka Server 高可用集羣,集羣相互之間通過 Replicate(複製)來同步數據,不區分主從,如果某臺Euraka Server宕機,Euraka Client的請求會自動切換新的Eureka Server。

Eureka 提供了 Region(地址位置的區域)和 Zone(具體機房) 兩個概念來進行分區。

(6) 工作流程:

  1. Eureka Server 啓動成功,等待服務端註冊。在啓動過程中如果配置了集羣,集羣之間定時通過 Replicate 同步註冊表,每個 Eureka Server 都存在獨立完整的服務註冊表信息
  2. Eureka Client 啓動時根據配置的 Eureka Server 地址去註冊中心註冊服務
  3. Eureka Client 會每 30s 向 Eureka Server 發送一次心跳請求,證明客戶端服務正常
  4. 當 Eureka Server 90s 內沒有收到 Eureka Client 的心跳,註冊中心則認爲該節點失效,會註銷該實例
  5. 單位時間內 Eureka Server 統計到有大量的 Eureka Client 沒有上送心跳,則認爲可能爲網絡異常,進入自我保護機制,不再剔除沒有上送心跳的客戶端
  6. 當 Eureka Client 心跳請求恢復正常之後,Eureka Server 自動退出自我保護模式
  7. Eureka Client 定時全量或者增量從註冊中心獲取服務註冊表,並且將獲取到的信息緩存到本地
  8. 服務調用時,Eureka Client 會先從本地緩存找尋調取的服務。如果獲取不到,先從註冊中心刷新註冊表,再同步到本地緩存
  9. Eureka Client 獲取到目標服務器信息,發起服務調用
  10. Eureka Client 程序關閉時向 Eureka Server 發送取消請求,Eureka Server 將實例從註冊表中刪除

3、ribbon客服端負載均衡

實現客戶端負載均衡,可以自定義Ribbon Client, 也可以yml中配置負載的策略(隨機、輪詢、權重),默認是輪詢。

4、hystrix熔斷

(1) 服務雪崩效應:分佈式系統中經常會出現某個基礎服務不可用造成整個系統不可用的情況(如:服務器宕機、緩存擊穿、程序bug等)

(2) 服務之間相互調用,分佈式環境中經常出現某個服務節點故障,調用失敗。熔斷器就是當服務調用失敗時候提供保障服務正常運行不被卡死。@HystrixCommand(fallbackMethod = "fallback")

(3) 斷路器機制:hystrix存在三種狀態:CLOSED、OPEN、HALF_OPEN。默認closed時,服務在一定時間內(10s) 請求次數達到了某個閥值(20次),並且錯誤率也達到了某個閥值(>50%)此時斷路器變成了OPEN的狀態, 過了一定的時間(5s)將會放行一個請求,此時變成HALF_OPEN狀態,如果可以訪問就變成CLOSED否則變成OPEN狀態。

5、feign 基於Ribbon和Hystrix的聲明式服務調用組件

JAX-RS 注意不能使用GetMapping不支持,PathVariable需設置value

6、zuul網關(通過過濾器來實現)

生命週期:

  • pre Filter:這種過濾器再請求被路由之前調用。如:認證鑑權、限流等。
  • route:將請求路由到微服務,構建發送給微服務的請求,HttpClient或Ribbon請求微服務。
  • post:在路由到微服務執行之後執行,返回結果或者發生異常後執行的filter。
  • error:發生異常,執行改filter。

7、Springcloud config 配置中心(實現方式是git管理配置)

  • 環境部署之前,將所需的配置信息推送到配置倉庫
  • 啓動配置中心服務端,將配置倉庫的配置信息拉取到服務端,配置服務端對外提供REST接口
  • 啓動配置客戶端,客戶端根據 spring.cloud.config 配置的信息去服務器拉取相應的配置

8、zipkin服務追蹤

分佈式服務追蹤,收集來自各個系統的監控數據。

  • Collector 接受或者收集各個應用傳輸的數據
  • Storage:負責存儲接收到的數據,默認是存儲在內存當中的,也可以支持存在MySQL當中
  • API:負責查詢Storage中存儲的數據,主要是提供給Web UI來使用
  • Web:主要是提供簡單的web界面

四、redis 

1、數據結構

redis是一個key-value存儲系統,常見數據結構:

  • String:常用命令(set,get,decr,incr,mget)value可以是String,也可以是數字。常規計數:微博數,粉絲數等
  • Hash:常用命令(hget,hset,hgetall)跟map一樣,適合用於存儲對象,如:用戶信息,商品信息等。
  • List:常用命令(lpush,rpush,lpop,rpop,lrange)list就是雙向鏈表,即可以支持反向查找和遍歷。如:微博粉絲列表、最小消息排行等。
  • Set:常用命令(sadd,spop,smembers,sunion)與list類似是一個列表的功能,可以自動去重複數據。如:共同好友、好友推薦。
  • Sorted Set:常用命令(zadd,zrange,zrem,zcard)和set相比,sorted set增加了一個權重參數score,能夠按score進行有序排列。如:禮物排行榜,彈幕消息。

  • hyperloglog:統計頁面訪問量等數據。

  • GEO:用於處理地理位置的信息,可以保存地理位置,可以計算地理位置的距離。

2、分佈式鎖

(1) 原理

  • 加鎖:(setnx) key設置一個值(SET lock_key random_value NX PX 5000)
  • 解鎖:刪除key 先判斷當前鎖的字符串random_value是否與傳入的值相等,是的話就刪除Key,解鎖成功。
  • 鎖超時:避免死鎖,給定一個過期時間。

(2) redisson實現分佈式鎖

  • 原子性,lua腳本發送給redist。
  • watch dog自動延期機制,後臺守護線程,每隔10s檢查。

3、緩存:數據保存在內存,存取速度快,併發能力強(mybatis二級緩存)

持久化方式:(開機的時候掃描持久化文件)

  • RDB:RDB 持久化可以在指定的時間間隔內生成數據集的時間點快照
  • AOF:AOF 持久化記錄服務器執行的所有寫操作命令

4、緩存失效

1. 緩存過了失效時間,緩存被刪除,需要更新緩存。

  • 互斥鎖:發起請求,將緩存中該數據上鎖。無緩存,則等待數據庫查詢,並更新緩存。

  • 設置不同的失效時間:緩存失效時間錯開,加個隨機數等。

2.redis內存不足時的策略

(1)noeviction: 拒絕寫操作, 讀、刪除可以正常使用。默認策略,不建議使用;
(2)allkeys-lru: 移除最近最少使用的key,最常用的策略;
(3)allkeys-random:隨機刪除某個key,不建議使用;
(4)volatile-lru:在設置了過期時間的key中,移除最近最少使用的key,不建議使用;
(5)volatile-random:在設置了過期時間的key中,隨機刪除某個key,不建議使用;
(6)volatile-ttl: 在設置了過期時間的key中,把最早要過期的key優先刪除。

5、緩存雪崩

(1) 雪崩:網絡不穩定或服務器宕機,服務調用者阻塞,引發雪崩連鎖效應。

(2) 緩存雪崩:當緩存服務器重啓或者大量緩存集中在某一個時間段失效,直接訪問數據庫,數據庫宕機,從而造成系統的崩潰。

(3) 雪崩解決方案:

  • 熔斷模式:使用Hystrix(熔斷、降級、限流)一旦發現當前服務的請求失敗率達到預設的值,Hystrix將會拒絕隨後該服務的所有請求,直接返回一個預設的結果。這就是所謂的“熔斷”
  • 隔離模式:緩存失效後,通過枷鎖,對某個key只允許一個線程查詢數據和寫緩存。
  • 限流模式:對請求設置最高的QPS閾值,高於閾值直接返回。

6、緩存穿透

一般緩存系統,都是按照key去緩存查詢數據,如果不存在對應的value,就去數據庫查詢。頻繁訪問數據庫,這就叫緩存穿透。

1.緩存空數據:查詢結果爲空的key也存儲在緩存中,該key的查詢請求時,緩存直接返回null,而無需查詢數據庫。

2.BloomFilter(推薦):bloomFilter就類似一個hashset(bigmap),判斷某個key是否存在,不存在直接返回null。

7、集羣(高可用、可擴展性、分佈式、容錯)

  • 主從複製

    將Master(讀寫操作)的數據自動同步到Slave數據庫。

    實現原理:

  1. 從服務器向主服務器發送SYNC命令
  2. 主服務器收到SYNC命令後,執行BGSAVE命令,在後臺生成RDB文件,使用緩衝區記錄從現在開始執行的所有的寫命令。
  3. 當主服務器的BGSAVE命令執行完畢後,主服務器後將BGSAVE命令生成的RDB文件發送給從服務器,從服務器接收並載入這個RDB文件,將自己的數據庫狀態更新至主服務器執行BGSAVE命令時的數據庫狀態。
  4. 主服務器將記錄在緩衝區裏面的所有寫命令發送給從服務器,從服務器執行這些寫命令,將自己的數據庫狀態更新至主服務器數據庫當前所處的狀態。

  缺點:master 宕機需要手動將slave提升爲master。

  • 哨兵模式

   Redis Sentinel(哨兵):節點數量要滿足 2n+1奇數個。

   Sentinel功能:

  1. 監控主從數據庫是否正常運行
  2. master出現故障時,自動將slave轉化爲master
  3. 多哨兵配置的時候,哨兵之間也會自動監控
  4. 多個哨兵可以監控同一個redis

  缺點:Redis較難支持在線擴容,選舉leader(slave轉化爲master)時候服務無法工作。

阿里架構師進階專題:Redis集羣的5種使用方式,各自優缺點分析

  • Cluster集羣(3.0版本)推薦使用 

   (1) Redis Cluster是多個Redis主從節點,在分區期間還提供了一定程度的可用性。

   (2) Redis集羣數據分片,分片採用slot(槽)的概念,一共分成16384個槽。對於每個進入Redis的鍵值對,每個key通過CRC16校驗,分配到這16384個slot中的某一箇中。

   比如當前集羣有3個節點:(slots)默認是平均分配槽,推薦工具redis client

  • 節點 A 包含 0 到 5500號哈希槽;

  • 節點 B 包含5501 到 11000 號哈希槽;

  • 節點 C 包含11001 到 16384號哈希槽;

  (3) 擴容

  • 增加節點的順序是先增加Master主節點,然後在增加Slave從節點

  • 分配數據槽,從其他節點分配槽。

五、數據庫

1.mysql

1. InnoDB:存儲引擎,支持行鎖(B+Tree)

局部內存,按照頁取數據,每頁16kb,放在內存中  每行數據最多存65535個字節 佔位符3個

數據插入的時候是B+Tree聚集索引

按照主鍵創建索引,沒有使用唯一索引,沒有才使用rowId

640?

2. myISAM:非聚集性索引

3. mysql explain 詳解

explain查看sql執行計劃,查看sql有沒有使用索引,有沒有全表掃描。

  • id:選擇標識符
  • select_type:表示查詢的類型。
  • table:輸出結果集的表
  • partitions:匹配的分區
  • type:表示表的連接類型
  • possible_keys:表示查詢時,可能使用的索引
  • key:表示實際使用的索引
  • key_len:索引字段的長度
  • ref:列與索引的比較
  • rows:掃描出的行數(估算的行數)
  • filtered:按表條件過濾的行百分比
  • Extra:執行情況的描述和說明

2. Sql優化

  1. sql避免全表掃描,避免  ‘ * ‘ 或 is null 或 != 或 <> 或 or 等查詢
  2. 儘量使用(NOT) EXISTS 替代( NOT)IN
  3. 通配符%,like '%c%'不會使用索引,而 like 'c%'會使用所有
  4. 合理的建立索引能夠加速數據讀取效率,不合理的建立索引反而會拖慢數據庫的響應速度
  5. 索引越多,更新數據的速度越慢
  6. 儘量用union all代替union
  7. 對於聯合索引來說,要遵守最左前綴法則,創建聯合索引的時候一定要注意索引字段順序,常用的查詢字段放在最前面。

3. Oracle

(1) LATCH:Latch是用於保護SGA區數據結構的一種串行化鎖定機制,對內存數據結構提供互斥訪問的一種機制。

(2) Latch和Lock的區別:

  1.  Latch是對內存數據結構提供互斥訪問的一種機制,而Lock是以不同的模式來套取共享資源對象,各個模式間存在着兼容或排斥,從這點看出,Latch的訪問,包括查詢也是互斥的,任何時候,只能有一個進程能pin住內存的某一塊,幸好這個過程是相當的短暫,否則系統性能將沒的保障,現在從9I開始,允許多個進程同時查詢相同的內存塊,但性能並沒有想象中的好。
  2.  Latch只作用於內存中,他只能被當前實例訪問,而L ock作用於數據庫對象,在RAC體系中實例間允許Lock檢測與訪問
  3.  Latch是瞬間的佔用,釋放,Lock的釋放需要等到事務正確的結束,他佔用的時間長短由事務大小決定
  4.  Latch是非入隊的,而Lock是入隊的
  5.  Latch不存在死鎖,而Lock中存在(死鎖在Oracle中是非常少見的)

(3) 按鎖的機制分類

       排他鎖( X ):如果事務T對對象A加上排他鎖,則只允許T對A對象讀取和修改,其他事務不能對A增加任何鎖,直到T釋放加載A上的排他鎖

  共享鎖( S ):如果事務T對錶A加上共享鎖,則事務T可以讀該表,但是不能修改該表數據。其他事務也只能對該對象加上共享鎖,但是不能加上排他鎖。這就保證了其他事務可以讀A表數據,但是不能修改A表數據(這就不會影響到讀該表的事務了,有利於併發操作)。

(4) 按操作行爲分類

  • DML Locks  保證併發情況下的數據完整性
  1. Row Locks (TX) 稱爲行級鎖。當事務執行 DML 語句(INSERT, UPDATE, DELETE, and SELECT with the FOR UPDATE clause)時會申請TX 類型的鎖,TX 的機制是排他鎖。
  2. Table Locks (TM) 稱爲表級鎖。當Oracle執行 DML 語句時,系統自動在所要操作的表上申請TM類型的鎖。
  • DDL Locks  用於保護數據庫對象的結構
  1. 排他DDL鎖(Exclusive DDL lock):阻塞其他會話得到該對象的DDL鎖或DML鎖。在DDL操作期間你可以查詢一個表,但是無法以任何方式修改這個表。 
  2. 共享DDL鎖(Share DDL lock):保護所引用對象的結構,使其結構不會被其他會話修改
  • System Locks 保護數據庫的內部結構

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章