操作系統
操作系統的特點?
– 共享:資源可被多個并發執行的進程使用
– 并發:可以在同一時間間隔處理多個進程,需要硬件支持
– 虛擬:將物理實體映射成為多個虛擬設備
– 異步:進程執行走走停停,每次進程執行速度可能不同,但OS需保證進程每次執行結果相同
進程的三個組成部分?
程序段、數據段、PCB(Process Control Block)
并發與并行區別?
并發:同一間隔 并行:同一時刻
進程切換的過程?
保持處理機上下文 -> 更新PCB -> 把PCB移入相應隊列(就緒、阻塞) -> 選擇另一個進程并更新其PCB -> 更新內存管理的數據結構 -> 恢復處理機上下文
進程通信
1、低級通信方式
PV操作(信號量機制)。
– P:wait(S)原語,申請S資源
– V:signal(S)原語,釋放S資源
2、高級通信方式:以較高效率傳輸大量數據的通信方式
– 共享存儲(使用同步互斥工具操作共享空間)
– 消息傳遞(進程間以格式化的消息進行數據交換,有中間實體,分為直接和間接兩種,底層通過發送消息和接收消息兩個原語實現)
– 管道通信(兩個進程中間存在一個特殊的管道文件,進程的輸入輸出都通過管道,半雙工通信)
管程是什么?
由一組數據及對這組數據操作的定義組成的模塊。同一時間只能有一個進程使用管程,即管程是互斥使用的,進程釋放管程后需喚醒申請管程資源的等待隊列上的進程。進程只有通過進入管程并使用管程內部的操作才能訪問其中數據。
死鎖的必要條件?
– 互斥條件:資源在某一時刻只能被一個進程占有
– 不剝奪條件:進程所持有的資源在主動釋放前不能被其他進程強行奪走
– 請求和占用條件:死鎖進程必然是既持有資源又在申請資源的
– 循環等待條件:存在等待鏈,互相申請,互不釋放
避免死鎖:不讓循環等待條件發生。使用銀行家算法。
死鎖與饑餓的區別?
– 都是資源分配問題
– 死鎖是等待永遠不會釋放的資源,而饑餓申請的資源會被釋放,只是永遠不會分配給自己
– 一旦產生死鎖,則死鎖進程必然是多個,而饑餓進程可以只有一個
– 饑餓的進程可能處于就緒狀態,而死鎖進程一定是阻塞進程
進程和線程的區別?
線程被稱作輕量級進程,在進程中包含線程。進程有獨立的內存空間,不同進程間不能直接共享其他進程資源,而同一個進程內的線程共享進程內存空間;相比進程,線程切換對系統開銷更小一些;進程是資源分配的最小單位,線程是程序執行的最小單位。
FCB包含什么?
文件指針:上次讀寫位置。
文件打開數:多少個進程打開了此文件。
文件磁盤位置。
文件的訪問權限:創建、只讀、讀寫等。
頁面置換算法?
最佳置換算法OPT
所選擇的被淘汰頁面將是以后永不使用的,或者是在最長時間內不再被訪問的頁面,這樣可以保證獲得最低的缺頁率。但由于人們目前無法預知進程在內存下的若千頁面中哪個是未來最長時間內不再被訪問的,因而該算法無法實現。
先進先出置換算法FIFO
優先淘汰最早進入內存的頁面,亦即在內存中駐留時間最久的頁面。該算法實現簡單,只需把調入內存的頁面根據先后次序鏈接成隊列,設置一個指針總指向最早的頁面。但該算法與進程實際運行時的規律不適應,因為在進程中,有的頁面經常被訪問。
最近最久未使用算法LRU
最近最長時間未訪問過的頁面予以淘汰,它認為過去一段時間內未訪問過的頁面,在最近的將來可能也不會被訪問。該算法為每個頁面設置一個訪問字段,來記錄頁面自上次被訪問以來所經歷的時間,淘汰頁面時選擇現有頁面中值最大的予以淘汰。
時鐘算法LOCK
LRU算法的性能接近于OPT,但是實現起來比較困難,且開銷大;FIFO算法實現簡單,但性能差。所以操作系統的設計者嘗試了很多算法,試圖用比較小的開銷接近LRU的性能,這類算法都是CLOCK算法的變體。
簡單的CLOCK算法是給每一幀關聯一個附加位,稱為使用位。當某一頁首次裝入主存時,該幀的使用位設置為1;當該頁隨后再被訪問到時,它的使用位也被置為1。對于頁替換算法,用于替換的候選幀集合看做一個循環緩沖區,并且有一個指針與之相關聯。當某一頁被替換時,該指針被設置成指向緩沖區中的下一幀。當需要替換一頁時,操作系統掃描緩沖區,以查找使用位被置為0的一幀。每當遇到一個使用位為1的幀時,操作系統就將該位重新置為0;如果在這個過程開始時,緩沖區中所有幀的使用位均為0,則選擇遇到的第一個幀替換;如果所有幀的使用位均為1,則指針在緩沖區中完整地循環一周,把所有使用位都置為0,并且停留在最初的位置上,替換該幀中的頁。由于該算法循環地檢查各頁面的情況,故稱為CLOCK算法,又稱為最近未用(Not Recently Used, NRU)算法。
改進型時鐘算法
改進型的CLOCK算法優于簡單CLOCK算法之處在于替換時首選沒有變化的頁。由于修改過的頁在被替換之前必須寫回,因而這樣做會節省時間。
批處理作業調度算法?
先來先服務FCFS
就是按照各個作業進入系統的自然次序來調度作業。這種調度算法的優點是實現簡單,公平。其缺點是沒有考慮到系統中各種資源的綜合使用情況,往往使短作業的用戶不滿意,因為短作業等待處理的時間可能比實際運行時間長得多。
最短作業優先SJF
就是優先調度并處理短作業,所謂短是指作業的運行時間短。而在作業未投入運行時,并不能知道它實際的運行時間的長短,因此需要用戶在提交作業時同時提交作業運行時間的估計值。
最高響應比優先HRN
FCFS可能造成短作業用戶不滿,SPF可能使得長作業用戶不滿,于是提出HRN,選擇響應比最高的作業運行。響應比=1+作業等待時間/作業處理時間。
多級隊列調度算法
每一個作業規定一個表示該作業優先級別的整數,當需要將新的作業由輸入井調入內存處理時,優先選擇優先數最高的作業。
進程調度算法?
進程有三種狀態阻塞就緒,運行。
先進先出FIFO
按照進程進入就緒隊列的先后次序來選擇。即每當進入進程調度,總是把就緒隊列的隊首進程投入運行。
時間片輪轉算法RR
分時系統的一種調度算法。輪轉的基本思想是,將CPU的處理時間劃分成一個個的時間片,就緒隊列中的進程輪流運行一個時間片。當時間片結束時,就強迫進程讓出CPU,該進程進入就緒隊列,等待下一次調度,同時,進程調度又去選擇就緒隊列中的一個進程,分配給它一個時間片,以投入運行。
最高優先級算法HPF
進程調度每次將處理機分配給具有最高優先級的就緒進程。最高優先級算法可與不同的CPU方式結合形成可搶占式最高優先級算法和不可搶占式最高優先級算法。
多級隊列反饋算法
幾種調度算法的結合形式多級隊列方式。
磁盤調度算法?
先來先服務FCFS
最短尋道時間優先SSTF
讓離當前磁道最近的請求訪問者啟動磁盤驅動器,即是讓查找時間最短的那個作業先執行,而不考慮請求訪問者到來的先后次序,這樣就克服了先來先服務調度算法中磁臂移動過大的問題
掃描算法SCAN
總是從磁臂當前位置開始,沿磁臂的移動方向去選擇離當前磁臂最近的那個柱面的訪問者。如果沿磁臂的方向無請求訪問時,就改變磁臂的移動方向。在這種調度方法下磁臂的移動類似于電梯的調度,所以它也稱為電梯調度算法。
循環掃描算法C-SCAN
循環掃描調度算法是在掃描算法的基礎上改進的。磁臂改為單項移動,由外向里。當前位置開始沿磁臂的移動方向去選擇離當前磁臂最近的哪個柱面的訪問者。如果沿磁臂的方向無請求訪問時,再回到最外,訪問柱面號最小的作業請求。
FAT(File Allocation Table)?分配
分配給文件的所有盤塊號都放在FAT中,用以記錄了文件的物理位置。
中斷和系統調用區別?
中斷是怎么操作的?
中斷請求-中斷響應-斷點保護---執行中斷服務程序---斷點恢復---中斷返回
中斷:解決處理器速度和硬件速度不匹配,是多道程序設計的必要條件。每個中斷都有自己的數字標識,當中斷發生時,指令計數器PC和處理機狀態字PSW中的內容自動壓入處理器堆棧,同時新的PC和PSW的中斷向量也裝入各自的寄存器中。這時,PC中包含的是該中斷的中斷處理程序的入口地址,它控制程序轉向相應的處理,當中斷處理程序執行完畢,該程序的最后一條iret(中斷返回),它控制著恢復調用程序的環境。 中斷和系統調用的區別: 中斷是由外設產生, 無意的, 被動的 系統調用是由應用程序請求操作系統提供服務產生, 有意的, 主動的。要從用戶態通過中斷進入內核態。(聯系) 中斷過程:中斷請求 中斷響應 斷點保護 執行中斷服務程序 斷點恢復 中斷返回 系統調用過程:應用程序在用戶態執行時請求系統調用,中斷,從用戶態進入內核態,在內核態執行相應的內核代碼。
虛擬存儲的意義和方法?
根據程序執行的互斥性和空間與時間局域性兩個特點,允許作業裝入時候只裝入一部分,另一部分存放在磁盤上,調用時候將常用的放入內存,其他暫時不用的放入外存中。這樣一個小的主存空間也可以運行一個比它大的作業。常用的虛擬存儲技術有分頁分段存儲管理。
windows和linux使用的文件系統?
window:fat32.linux:ext2,fat32.
計算機組成原理
什么是馮諾伊曼結構?
是一種將程序指令存儲器和數據存儲器合并在一起的存儲器結構。
五個組成部分是:輸入輸出,計算單元,控制單元,存儲單元。
輸入數據和程序的輸入設備;
記憶程序和數據的存儲器;
完成數據加工處理的運算器;
控制程序執行的控制器;
輸出處理結果的輸出設備。
高速緩存的作用
連接CPU和內存。
cache和寄存器區別?
寄存器是暫時存儲的CPU組成部分,cache用來做高度CPU和低速的主存之間加速帶。
指令系統
CISC(Complex Instruction Set Computer)復雜指令系統計算器,是一種執行較多類型計算機指令的微處理器。RISC(Reduced Instruction Set Computer)是精簡指令系統計算器,是一種執行較少類型計算機指令的微處理器。
流水線
將重復性的過程分為若干個子過程來完成。
總線和I/O
總線是指數據通信的連接線,有地址,數據,控制指令。
I/O輸入/輸出(Input/Output),分為IO設備和IO接口兩個部分.
I/O的方式有:DIO(Direct I/O),AIO(Asynchronous I/O,異步I/O),Memory-Mapped I/O(內存映射I/O)等,不同的I/O方式有不同的實現方式和性能,在不同的應用中可以按情況選擇不同的I/O方式。
DMA
DMA(Direct Memory Access,直接存儲器訪問) 是所有現代電腦的重要特色,它允許不同速度的硬件裝置互相溝通,而不需要依賴于 CPU 的大量中斷負載。否則,CPU 需要從來源把每一片段的資料復制到暫存器,然后把它們再次寫回到新的地方。在這個時間中,CPU 對于其他的工作來說就無法使用。
Java
java的特點?
一次編譯到處運行,沒有指針,完全對象化,面向對象(封裝、繼承、多態)。
java常用術語
JavaEE:Java Platform Enterprise Edition,是Sun公司為企業級應用推出的標準平臺。
J2EE:Java 2 Platform,Enterprise Edition,是JavaEE以前的叫法。
JDBC:Java DataBase Connectivity,Java數據庫連接。
JNDI:Java Naming and Directory Interface,提供一個目錄系統,使得開發人員可以通過名稱來訪問資源。
EJB:Enterprise JavaBean,用來構建一個可以管理的服務器組件。
Servlet:Java編寫的服務端程序,可以動態修改web內容。
JSP:Java Server Pages,Sun主導的一種動態網頁技術標準,JSP部署于網絡服務器上,可以響應客戶端請求,并返回相應內容。
RMI:Remote Method Invocation,使得客戶端可以像調用本地對象一樣調用遠程服務器上的方法。和RPC(Remote Procedure Call Protocol)不同,RMI只適用于Java,返回結果也有區別。RML在文件傳輸時,需要進行序列化serial,轉換為二進制才能被servlet傳輸
XML:Extensible Markup Language,用于傳輸和存儲數據
JMS:Java Message Service,Java平臺面向消息中間件的一個服務,用于在分布式系統或應用程序間傳遞服務。
JTA:Java Transaction API,事務管理組件。
Weblogic:Oracle公司推出的商業化JavaEE服務器
java怎么處理對象分配和釋放的?
java把內存分為堆棧空間存儲,在堆中new的空間不用自己收回,自動垃圾收回。
JVM
不同于C++需要編程人員手動釋放內存,Java有虛擬機,因此Java不需要程序員主動去釋放內存,而是通過虛擬機自身的垃圾回收器(Garbage Collector-GC)來進行對象的回收。Java語言由于有虛擬機的存在,實現了平臺無關性,在任意平臺都是通過將代碼轉換為字節碼文件,從而在平臺下的虛擬機中運行代碼的。
名詞解釋:
內存區域分布
虛擬機棧:存放每個方法執行時的棧幀,一個方法調用到完成就對應棧幀在虛擬機棧中入棧和出棧的過程。
本地方法棧:和虛擬機棧類似,不過是為Java中native方法服務的。平時所說的“棧內存”指的就是虛擬機棧和本地方法棧的合稱。
程序計數器:當前線程執行字節碼的行號指示器,字節碼解釋器工作依賴于它。占用較小的內存空間,不會出現OOM。
堆:即所謂的“堆內存”。JVM所管理最大的一塊內存,被所有線程共享。唯一作用就是給對象實例分配內存空間,在分代回收算法中的新生代老年代就在于堆中。
方法區(也稱為永久代):不在堆中,被各個線程共享,存儲已被JVM加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。其中包括常量池。
另:直接內存,不屬于JVM內存區域,與NIO聯系緊密,不受JVM內存大小限制。
JVM垃圾回收機制
何時進行垃圾回收?
GC本質上是一道守護進程(Daemon Thread),不停的檢測堆中是否有不可達對象并釋放內存,因此GC在何時發生其實我們是無法預測的。GC通過調用對象的finalize()方法來摧毀對象。
不可達對象的判定:根搜索算法。JVM中有一系列設定的GC Roots,當一個對象到任意一個GC Root都沒有引用鏈時,則說明此對象不可達。
JVM中的垃圾回收算法
1、標記-清除算法
最基礎的算法,GC會判斷堆中對象是否不可達,如果滿足清理條件(查看該對象是否有必要執行finalize()方法,有無必要的標準是該對象有沒有被調用過finalize方法或該對象有沒有覆蓋finalize()方法,因為finalize()只能被調用一次),則給這個對象進行標記,將對象放在F-queue隊列。此時除非對象在finalize()方法中重新獲得了引用,否則它就會被清除掉。
2、復制算法
將內存分為大小相等的兩塊,當對象不可達后并不是及時清理,而是等待正在使用的內存滿了之后,將該內存內還存活的對象整體復制到另一塊內存中,復制結束后再清理掉原內存塊中的所有內容。這種方法的優點是快速,但犧牲了一半的內存。方法的改進版(事實上也是虛擬機的做法)是只在新生代空間使用復制算法,并且由于新生代對象生命周期往往很短,因此又將新生代區域分為Eden和Survivor空間。其中Eden分配的空間又比Survivor大出很多,從而節省內存空間。如果存活對象過多,使得Survivor區也滿,那么就會轉移Survivor區對象到老年代。
3、標記-整理算法
標記過程與1一樣,將1中的清除過程換成了整理,即將內存中存活的對象歸攏到一邊,使得內存更“緊湊”一些,整理之后將邊界之外的對象清理掉。這種算法是為了防止2算法中出現存活率100%的極端情況,那么復制就沒有止境了。
4、分代算法
新生代采用2算法,老年代采用1或3算法。這是由他們的特點決定的,新生代注定了其中很多對象生命周期轉瞬即逝,因此復制算法移動的存貨對象并不是很多。而老年代存活率較高,只能采用1、3來執行,提高效率。
JVM參數相關
可以調整堆內新生代老年代比例
可以調整對象移入老年代的年齡
可以調整堆內存大小
可以設置每個棧大小
可以設置堆內分區大小
可選擇垃圾回收方式
JVM類加載機制
雙親委派模型。
類加載器(ClassLoader)用來實現類的加載動作。JVM中只存在兩種不同的類加載器:啟動類加載器和其他類加載器。
啟動類加載器:即Bootstrap ClassLoader。由C++編寫,在JVM內部。其他類加載器都由Java編寫,在JVM外部,全部繼承于抽象類java.lang.ClassLoader。
類加載器之間的層次關系,稱為雙親委派模型。
頂層為啟動類加載器,下邊為擴展類加載器,再下為應用程序類加載器,其中包含多種自定義類加載器。
如果一個類加載器收到了加載類的請求,它首先不會自己去加載,而是委派給它的父加載器去執行。層層委派之后,到了頂層由啟動類加載器加載,只有當父加載器反饋無法加載此請求,才會讓子加載器去加載。這種結構使得Java類型體系中的加載機制清晰準確,不易造成混亂。
有一種雙親委派模型的異常情況,即類似啟動類加載器這種基礎的類加載器,本應默認為所有類適用的加載器,但由于一些環境下調用SPI(Service Provider Interface),繞過雙親委派模型的層次結構使得父加載器委派子加載器去完成類加載動作。
還有一種情況,即為了實現模塊的動態性、熱部署,不再使用雙親委派模型,而是使用更加復雜的網狀結構。OSGi技術即是類加載器網狀結構的一個最佳實踐。
如何判斷當前系統內是否存在死鎖?
可以打印當前的內存快照,可以看到快照中有deadLock對象,所在的方法,請求被鎖的資源,從而進一步分析死鎖原因。
ThreadLocal
ThreadLocal,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲,其實意思差不多。可能很多朋友都知道ThreadLocal為變量在每個線程中都創建了一個副本,那么每個線程可以訪問自己內部的副本變量。示例:
class ConnectionManager {
private static Connection connect = null;
public static Connection openConnection() {
if(connect == null){
connect = DriverManager.getConnection();
}
return connect;
}
public static void closeConnection() {
if(connect!=null)
connect.close();
}
}
假設有這樣一個數據庫鏈接管理類,這段代碼在單線程中使用是沒有任何問題的,但是如果在多線程中使用呢?很顯然,在多線程中使用會存在線程安全問題:第一,這里面的2個方法都沒有進行同步,很可能在openConnection方法中會多次創建connect;第二,由于connect是共享變量,那么必然在調用connect的地方需要使用到同步來保障線程安全,因為很可能一個線程在使用connect進行數據庫操作,而另外一個線程調用closeConnection關閉鏈接。
ThreadLocal的應用場景
最常見的ThreadLocal使用場景為 用來解決數據庫連接、Session管理等。
C++
c++和c中字符串區別?
c++是類,c中是基本類型函數。
C++的特點是什么?
封裝,繼承,多態。支持面向對象和面向過程的開發。
C++的異常處理機制?
拋出異常和捕捉異常進行處理。(實際開發)
c和c++,java的區別?
c是純過程,c++是對象加過程,java是純面向對象的
純虛函數?
被virtual修飾的成員函數,再基類不能實現,而他的實現放到派生類中實現。
什么是內存泄漏?
內存泄漏(Memory Leak)是指程序中己動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。
指針和引用的區別?
指針是一個存儲地址的變量,該地址為內存的一個存儲單元;引用是原變量的一個別名;
指針可以為空,而引用不能為空;
指針可以有多級,而引用只能有一級;
指針可以重新賦值,而引用只能初始化一次
sizeof引用得到的是變量大小,而sizeof指針得到的是指針本身大小
將引用作為函數返回值的好處是?
在內存中不會產生被返回值的副本,同時不能返回局部變量的引用,因為隨著調用結束局部變量會被銷毀。
三種傳參方式?
值傳遞
傳遞的是實參的一個拷貝,修改形參不會改變實參值。
地址傳遞
傳遞的是實參地址的一個拷貝,修改形參會改變實參值。
引用傳遞
傳遞的是實參的一個別名,修改形參會導致改變實參。
被調用函數的形參只有在被調用時才會臨時分配存儲單元,一旦調用結束則釋放內存。
const作用?
被const修飾符修飾的變量不能被修改。const x表明x數據是常量,不能修改;const x表明指針本身是常量,x的指針不能指向其他內存地址,x本身可被修改;*const *x表明x本身數據和地址都不能被修改。
static作用?
被static修飾符修飾的變量在整個文件中都是可見的,而在文件外是不可見的。該變量在全局數據區分配內存。C++中由程序運行new出的動態數據存放在堆區,而函數內部局部變量存放在棧區。
靜態局部變量:在函數內部定義static變量,第一次運行到這里初始化,存儲到全局數據區,下一次執行到這里不會再重新初始化。
static變量如果沒有顯式初始化,默認初始值為0。
靜態函數不能被其他函數所調用。
面向對象的三個要素(基本特征)?
1、封裝:將客觀事物封裝成類,隱藏實現細節,模塊化代碼。
2、多態:實現多態的兩種方式——覆蓋(重寫)和重載。
覆蓋是子類重新定義父類的虛函數,與多態真正相關。當子類重新定義了父類的虛函數后,父類指針根據賦給它的不同的子類指針,動態的調用屬于子類的該函數,這樣的函數調用在編譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數地址是在運行期綁定的(晚綁定)。
重載是存在多個同名函數,但是函數的參數個數不同。這些函數實際上成為了不同的函數,對它們的調用在編譯期間就已經確定,屬于早綁定,與多態無關。
3、繼承:子類繼承父類功能,對父類功能進行擴展。
結構體和聯合有什么區別?
- 結構和聯合都是由多個不同的數據類型成員組成, 但在任何同一時刻, 聯合中只存放了一個被選中的成員(所有成員共用一塊地址空間), 而結構的所有成員都存在(不同成員的存放地址不同)。
- 對于聯合的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對于結構的不同成員賦值是互不影響的。
C++是不是類型安全的語言?
不是。不同類型間指針可以強制互轉。
const與#define區別?
const修飾常量受到強制保護,程序更健壯,而且const修飾的常量有數據類型,有類型安全檢查。
基類的析構函數為什么是虛函數?
為了防止派生類析構函數未執行,造成資源泄露。
#include尖括號和雙引號區別?
<>是標準頭文件,“”是非系統頭文件
為什么有了指針,還要使用引用?
為了支持運算符的重載。更加方便。
如何避免野指針?
聲明指針記得初始化,暫時不用就指向NULL;使用malloc分配內存,必須經過顯式釋放(free),避免內存泄漏。
計算機網絡
談談對TCP/IP協議的理解
有5層結構,分層處理。
五個分層。
1、應用層:應用層是TCP/IP協議的第一層,是直接為應用進程提供服務的。
(1)對不同種類的應用程序它們會根據自己的需要來使用應用層的不同協議,郵件傳輸應用使用了SMTP協議、萬維網應用使用了HTTP協議、遠程登錄服務應用使用了有TELNET協議。 [1]
(2)應用層還能加密、解密、格式化數據。 [1]
(3)應用層可以建立或解除與其他節點的聯系,這樣可以充分節省網絡資源。
2、運輸層:解決的是計算機程序到計算機程序之間的通信問題,即所謂的“端”到 “端”的通信。引入傳輸層的原因: 增加復用和分用的功能、 消除網絡層的不可靠性、 提供從源端主機到目的端主機的可靠的、與實際使用的網絡無關的信息傳輸。運輸層是ISO/OSI的第四層,處于通信子網和資源子網之間,是整個協議層次中最核心的一層。作為TCP/IP協議的第二層,運輸層在整個TCP/IP協議中起到了中流砥柱的作用。且在運輸層中,TCP和UDP也同樣起到了中流砥柱的作用。
3、網絡層:網絡層在TCP/IP協議中的位于第三層。在TCP/IP協議中網絡層可以進行網絡連接的建立和終止以及IP地址的尋找等功能。
4、網絡接口層:網絡接口層實際上并不是因特網協議組中的一部分,但是它是數據包從一個設備的網絡層傳輸到另外一個設備的網絡層的方法。這個過程能夠在網卡的軟件驅動程序中控制,也可以在韌體或者專用芯片中控制。這將完成如添加報頭準備發送、通過物理媒介實際發送這樣一些數據鏈路功能。另一端,鏈路層將完成數據幀接收、去除報頭并且將接收到的包傳到網絡層,在TCP/IP協議中,網絡接口層位于第四層。由于網絡接口層兼并了物理層和數據鏈路層所以,網絡接口層既是傳輸數據的物理媒介,也可以為網絡層提供一條準確無誤的線路。
5、網際層:提供獨立于硬件的邏輯尋址,從而讓數據能夠在具有不同物理結構的子網之間傳遞。提供路由功能來降低數據流量,支持Intemet 上的數據傳遞(互聯網絡是指多個局域網互相連接而形成的網絡,比如大公司里的網絡或是Intemet)。
TCP/UDP的區別?
TCP是可靠的面向連接的傳輸控制協議,UDP是不可靠的無連接傳輸數據報文協議。
IP和mac的區別?
IP是網絡層,MAC是數據鏈路層且地址是全球唯一的。
登陸baidu.com,簡述協議過程
ARRP(獲得網關地址) - DNS(獲得IP地址) - TCP
簡述ARRP的作用
hub,switch,router屬于OSI哪一層?
hub是集線器屬于物理層,交換機是數據鏈路層,router是路由器網絡層的,負責不同網絡結合。
子網掩碼和IP地址怎么理解?
在國際互聯網(Internet)上有成千百萬臺主機(host),為了區分這些主機,人們給每臺主機都分配了一個專門的“地址”作為標識,稱為IP地址。子網掩碼的作用是用來區分網絡上的主機是否在同一網絡段內。子網掩碼不能單獨存在,它必須結合IP地址一起使用。子網掩碼只有一個作用,就是將某個IP地址劃分成網絡地址和主機地址兩部分。
ipv4,ipv6的區別?
IPV6更安全,更大的存儲空間。
XML和HTML區別?
跨平臺的標記語言,重在儲存數據。HTML重在存儲界面顯示內容
OSI模型全稱?
Opening System Interconnection - Reference Model
七層模型: 應用層? 表示層? 會話層? 傳輸層? 網絡層? 數據鏈路層
第一層是物理層(也即OSI模型中的第一層也是最底層)
在課堂上經常是容易被忽略的。它看起來似乎很簡單。但是,這一層的某些方面有時需要特別留意。物理層實際上就是布線、光纖、網卡和其它用來把兩臺網絡通信設備連接在一起的東西。甚至一個信鴿也可以被認為是一個1層設備。網絡故障的排除經常涉及到1層問題。我們不能忘記用五類線在整個一層樓進行連接的傳奇故事。由于辦公室的椅子經常從電纜線上壓過,導致網絡連接出現斷斷續續的情況。遺憾的是,這種故障是很常見的,而且排除這種故障需要耗費很長時間。第二層是數據鏈路層
運行以太網等協議。請記住,我們要使這個問題簡單一些。第2層中最重要的是你應該理解網橋是什么。交換機可以看成網橋,人們都這樣稱呼它。網橋都在2層工作,僅關注以太網上的MAC地址。如果你在談論有關MAC地址、交換機或者網卡和驅動程序,你就是在第2層的范疇。集線器屬于第1層的領域,因為它們只是電子設備,沒有2層的知識。第2層的相關問題在本網絡講座中有自己的一部分,因此先不詳細討論這個問題的細節。只需要知道第2層把數據幀轉換成二進制位供1層處理就可以了。第三層是網絡層
在計算機網絡中進行通信的兩個計算機之間可能會經過很多個數據鏈路,也可能還要經過很多通信子網。網絡層的任務就是選擇合適的網間路由和交換結點, 確保數據及時傳送。網絡層將數據鏈路層提供的幀組成數據包,包中封裝有網絡層包頭,其中含有邏輯地址信息- -源站點和目的站點地址的網絡地址。
如果你在談論一個IP地址,那么你是在處理第3層的問題,這是“數據包”問題,而不是第2層的“幀”。IP是第3層問題的一部分,此外還有一些路由協議和地址解析協議(ARP)。有關路由的一切事情都在第3層處理。地址解析和路由是3層的重要目的。第四層是處理信息的傳輸層。
第4層的數據單元也稱作數據包(packets)。但是,當你談論TCP等具體的協議時又有特殊的叫法,TCP的數據單元稱為段(segments)而UDP協議的數據單元稱為“數據報(datagrams)”。這個層負責獲取全部信息,因此,它必須跟蹤數據單元碎片、亂序到達的數據包和其它在傳輸過程中可能發生的危險。理解第4層的另一種方法是,第4層提供端對端的通信管理。像TCP等一些協議非常善于保證通信的可靠性。有些協議并不在乎一些數據包是否丟失,UDP協議就是一個主要例子。第五層是會話層
這一層也可以稱為會晤層或對話層,在會話層及以上的高層次中,數據傳送的單位不再另外命名,統稱為報文。會話層不參與具體的傳輸,它提供包括訪問驗證和會話管理在內的建立和維護應用之間通信的機制。如服務器驗證用戶登錄便是由會話層完成的。第六層是表示層
這一層主要解決用戶信息的語法表示問題。它將欲交換的數據從適合于某一用戶的抽象語法,轉換為適合于OSI系統內部使用的傳送語法。即提供格式化的表示和轉換數據服務。數據的壓縮和解壓縮, 加密和解密等工作都由表示層負責。第七層是應用層。
是專門用于應用程序的。應用層確定進程之間通信的性質以滿足用戶需要以及提供網絡與用戶應用軟件之間的接口服務如果你的程序需要一種具體格式的數據,你可以發明一些你希望能夠把數據發送到目的地的格式,并且創建一個第7層協議。SMTP、DNS和FTP都是第7層協議。
DNS工作過程?
應用層協議,使用UDP。分為迭代查詢和遞歸查詢。采用分布式集群的工作方式,防止單點故障,增加通信容量。
迭代:主機訪問本地域名服務器,若緩存沒有IP則本地域名服務器進一步向其他根域名服務器查詢。
遞歸:主機分別向多個服務器發出查詢請求。
UDP的優點?
發送前無需連接,減少了開銷和時延,首部開銷小,無擁塞控制,方便實時應用,不保證可靠交付,無需維持連接狀態表。UDP的可靠性要通過應用層來控制。
數據鏈路層成幀方式?
字符填充法、字符計數法、比特填充法、違規編碼法。
RIP和OSPF?
RIP(Routing Information Protocol)路由信息協議。在應用層,最大站點數為15
OSPF(Open Shortest Path First)網絡層,洪泛法,迪杰斯特拉算法
軟件工程
軟件重用?
同一個函數重復用。
軟件測試類型?
單元,集成,黑盒,白盒,灰盒,。
軟件工程步驟
需求,設計,開發,測試。
UML
系統流程建模工具
軟件工程的認識?
運用工程化的方法管理軟件開發。
類之間的關系有哪些?
繼承:類繼承另一個類的功能
實現:類實現接口的功能
依賴:A類的某個方法使用到了B類
關聯:強依賴關系,B類作為一個屬性出現在了A類
聚合:一種特別的關聯,公司與個人的關系
組合:強聚合關系,整體與部分的聯系更緊密,如汽車與輪胎
軟件工程標準步驟?
問題定義
可行性研究
需求分析
總體設計
詳細設計
編碼和單元測試
綜合測試
軟件維護
有哪些軟件測試分類?
黑盒測試:不考慮軟件內部原理,以用戶角度測試軟件輸入輸出
白盒測試:知道軟件內部工作過程,確定每個分支都能按照預定正常工作
灰盒測試:集合白盒黑盒
冒煙測試:測試軟件基本功能,快速
系統測試:驗證系統是否滿足需求規格的黑盒類測試
性能測試:負載測試和壓力測試
安全測試:假扮黑客侵入系統
兼容性測試:不同平臺不同環境下的測試
自頂向下和自底向上測試方法的區別?
自頂向下:從程序入口主控模塊開始,按照系統程序結構,沿著控制層次從上而下測試各模塊。方便把握整體結構,早期可發現頂層錯誤。
自底向上:從最底層模塊,即葉子結點開始,按照調用從下而上的測試各模塊。最后一個模塊提交后才能完整系統測試,某些模塊可以提前測試。
軟件工程的三要素?
方法、工具、過程。
軟件工程的主要模型?
1、瀑布模型:前一階段工作結束才可以進行下一階段工作。基于文檔,易于維護,但加大了工作量。
2、快速原型:快速建立可以運行的程序,完成的功能是最終軟件的一個子集。不帶反饋環,滿足用戶真實需求,但會導致系統設計差,難以維護。
3、增量模型:每個階段不交付完整產品,軟件由一系列增量構件組成。降低開發風險,易于維護,但不容易控制整體過程
4、螺旋模型:結合快速原型和瀑布模型,有利于軟件重用,減少風險,風險人員需要一定經驗。
5、噴泉模型:迭代,無縫,節省開發時間。
6、敏捷
什么是死代碼?
永遠不會被執行到的代碼。
內聚和耦合
內聚:指一個好的內聚模塊內應當盡量只做一件事,描述的是模塊內的功能聯系。
耦合:各模塊之間相互連接的一種度量,耦合強弱取決于模塊間接口的復雜程度。
(1)內聚類型高→低:功能內聚、信息內聚、通信內聚、過程內聚、時間內聚、邏輯內聚、偶然內聚
(2)耦合類型高→低:內容耦合、公共耦合、外部耦合、控制耦合、標記耦合、數據耦合、非直接耦合
數據結構與算法
順序結構和鏈式結構的區別?
順序結構是指內存連續的存儲單元進行存儲,而鏈式結構是指 內存不連續的結構,通過一個節點指向另外一個節點的地址。
棧和隊列的區別?
棧是先進后出的特殊線性表,隊列是先進先出的線性表。
復雜度是什么?
復雜度包括時間復雜度和空間復雜度,用來評價一個算法的好壞。
頭節點的作用是什么?
頭節點是指向初始地址的一個節點,它本身數據段沒有內容,通過它可以標識這個鏈表。
介紹以下各種樹
樹,二叉樹:有左右子樹的區分和度不超過2.
二叉排序樹:左子樹均小于根,根均小于右節點。。
線索二叉樹:設置兩個標識標記左右指針指向的是孩子還是前軀節點。
平衡二叉樹:左右子樹高度差絕對值小于等于1。
哈夫曼樹:壓縮用的。權值大小排列。
完全二叉樹:只能從右邊為空。
度為2的樹和二叉樹的區別:
二叉樹有左右子樹的定義。
樹的存儲結構
孩子鏈存儲結構和雙親存儲結構。
樹的遍歷
先序中序后序三種。遞歸實現。
圖的存儲
鄰接矩陣和鄰接表,是多對多的關系,分為有向圖和無向圖。
線性表.查找有那幾類?
直接查找和有序表的二分查找。
排序算法的介紹?
插入排序有直接插入和折半插入。都是在有序表里插入進去的。
交換排序:冒泡,快速:以一個數字劃分兩個區域,然后分別對兩個區域繼續劃分,直到區間為一。注意快排是不穩定。
選擇排序:簡單的選擇排序,堆排序
歸并排序:將兩個有序表歸并到一個有序表。將兩個有序表放到一起進行各個比較,比較完之后放回原來數組內。
什么是穩定的算法?
一個序列中,關鍵字相同的數排序后相對位置不變即穩定,比如1、3、2、4、5、2序列,第三個位置2和最后一個位置2排序后,他們的位置先后不變化則穩定。
兩個棧模仿一個隊列?
進隊:入A棧。
出隊:若B棧不為空,則B棧全部出棧;否則將A棧中數據全部入B棧,再依次出B棧。
兩個隊列模仿一個棧?
入棧:入A隊
出棧:將A隊除隊尾元素全部轉移到B隊,出A隊,算法思想就是兩個隊列倒來倒去,只留一個元素時出棧。
如何判斷鏈表是否有環?
設置快慢指針,快指針每次前進兩步,當兩指針重合則有環,快指針為null則無環。
如何判斷有環鏈表環的入口?
1、將遍歷過的結點都入set,如果當前結點在set里有,則此結點即為入口。
2、快慢指針重合后,重置fast指針,此時fast每次走一步,再次重合結點即為入口。
最長公共子序列求解(LCS)?
DP。由最長公共子序列問題的最優子結構性質可知,要找出X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的最長公共子序列,可按以下方式遞歸地進行:當xm=yn時,找出Xm-1和Yn-1的最長公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一個最長公共子序列。當xm≠yn時,必須解兩個子問題,即找出Xm-1和Y的一個最長公共子序列及X和Yn-1的一個最長公共子序列。這兩個公共子序列中較長者即為X和Y的一個最長公共子序列。
鏈表能否使用二分查找?
可以。先將鏈表排序,將各個結點的值記入數組,再二分查找。
給定一顆二叉樹的頭結點,和這顆二叉樹中2個節點n1和n2,求這兩個節點的最近公共祖先
后序遍歷方法
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left != null && right != null) return root;
return left != null ? left : right;
}
}
棧應用括號匹配?
左括號入棧,右括號出棧進行匹配,棧空仍未匹配到則失敗。
二叉樹刪除節點?
被刪除的節點是葉子節點,這時候只要把這個節點刪除,再把指向這個節點的父節點指針置為空就行。
被刪除的節點有左子樹,或者有右子樹,而且只有其中一個,那么只要把當前刪除節點的父節點指向被刪除節點的左子樹或者右子樹就行。
被刪除的節點既有左子樹而且又有右子樹,這時候需要把左子樹的最右邊的節點或者右子樹最左邊的節點提到被刪除節點的位置。
哈希表最好最壞情況下復雜度?
O(1)和O(n),n為表長。
求二叉樹的直徑?
兩次DFS,第一次找出距離root最遠點,第二次以第一次結果為起點找出第二個點,這兩點的距離即為直徑。
設計模式
創建型模式:抽象的實例化過程,隱藏了對象創建的具體細節,使程序代碼不依賴具體的對象。
例:單例模式是 Java 中最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
抽象工廠模式是圍繞一個超級工廠創建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
在抽象工廠模式中,接口是負責創建一個相關對象的工廠,不需要顯式指定它們的類。每個生成的工廠都能按照工廠模式提供對象。
建造者模式建造者模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個復雜的對象。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立于其他對象的。
工廠模式是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的接口來指向新創建的對象。
原型模式
是用于創建重復的對象,同時又能保證性能。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
這種模式是實現了一個原型接口,該接口用于創建當前對象的克隆。當直接創建對象的代價比較大時,則采用這種模式。例如,一個對象需要在一個高代價的數據庫操作之后被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。
。
結構型模式:描述類和對象之間通過組織形成新的結構,以實現新的功能。
例:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
行為型模式:描述算法以及對象之間的任務(職責)分配及它們之間的通訊模式。
例:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式。
設計模式的六大原則
1、開閉原則(Open Close Principle)
開閉原則的意思是:對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是為了使程序的擴展性好,易于維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,后面的具體設計中我們會提到這點。
2、里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP 是繼承復用的基石,只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被復用,而派生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。
3、依賴倒轉原則(Dependence Inversion Principle)
這個原則是開閉原則的基礎,具體內容:針對接口編程,依賴于抽象而不依賴于具體。
4、接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。它還有另外一個意思是:降低類之間的耦合度。由此可見,其實設計模式就是從大型軟件架構出發、便于升級和維護的軟件設計思想,它強調降低依賴,降低耦合。
5、迪米特法則,又稱最少知道原則(Demeter Principle)
最少知道原則是指:一個實體應當盡量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
6、合成復用原則(Composite Reuse Principle)
合成復用原則是指:盡量使用合成/聚合的方式,而不是使用繼承。
數據庫
范式的定義?
改造關系模式,通過分解關系模型來消除其中不合適的數據依賴,以決絕插入異常,刪除異常,數據用余。
事務?
類似查詢一次的命令,要求全部執行完。
事務執行的四個基本要素?
原子性,一致性,隔離性,持久性。
數據庫和文件系統的比較?
數據庫結構化,共享性好,獨立性。有界面接口。
數據模型有哪幾種?
關系模型,層次模型,網狀模型
索引建的多的好還是少的好?
恰當把握,多的話占空間,少的話查詢不足,速度達不到。
數據庫的ACID?
原子性Atomicity:一個事務被視為一個最小單元,要么全部提交,要么全部回滾
一致性Consistency:事務總是由一種狀態轉換為另一種狀態,數據庫事務只會是執行前的狀態或是執行后的狀態,不會出現執行中的狀態。即如果一個事務執行了十秒,那么第一秒讀到的結果和第九秒得到的應該是相同的。
隔離性Isolation:一個事務的執行不會被另一個事務影響,互不干擾。
持久性Durability:事務只要提交了,那么數據庫中的數據也永久的發生了變化。
數據庫三范式?
1NF(Normal Form):R的所有屬性都不能再分解為更基本的數據單位。
2NF:R的所有非主屬性都依賴于R的關鍵屬性,所有列都依賴于任意一組候選關鍵字。
3NF:每一列都與任意候選關鍵字直接相關而不是間接相關,沒有傳遞依賴。
BCNF:3NF基礎上,關系R只有一個單屬性,或R的子集都是單屬性,則R滿足BCNF。
插入100個數據和100萬個數據有何區別?
100數量級小,可以隨意插入;100萬數量級大,如果表里有索引,則索引更新代價很高,可以采取先刪除索引再插入,插入完成后再建索引的策略。
數據庫數據可以無限插入嗎?
可以。大小受到主機內存的制約。數據量大時要先刪索引。減少提交次數,即減少IO次數。
處理大數據量的策略?
表分區,備份,入帶庫。
group by having,having和where的區別?
WHERE 子句用來篩選 FROM 子句中指定的操作所產生的行。
GROUP BY 子句用來分組 WHERE 子句的輸出。
HAVING 子句用來從分組的結果中篩選行。
在查詢過程中聚合語句(sum,min,max,avg,count)要比having子句優先執行.而where子句在查詢過程中執行優先級別優先于聚合語句(sum,min,max,avg,count)。
簡述數據庫以及線程死鎖產生的原理及必要條件,簡述如何避免死鎖?
產生死鎖的原因主要是:
(1) 因為系統資源不足。
(2) 進程運行推進的順序不合適。
(3) 資源分配不當等。
產生死鎖的四個必要條件:
(1)互斥條件:一個資源每次只能被一個進程使用。
(2)請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3)不可剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4)循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
避免死鎖
死鎖的預防是通過破壞產生條件來阻止死鎖的產生,但這種方法破壞了系統的并行性和并發性。
死鎖產生的前三個條件是死鎖產生的必要條件,也就是說要產生死鎖必須具備的條件,而不是存在這3個條件就一定產生死鎖,那么只要在邏輯上回避了第四個條件就可以避免死鎖。
避免死鎖采用的是允許前三個條件存在,但通過合理的資源分配算法來確保永遠不會形成環形等待的封閉進程鏈,從而避免死鎖。該方法支持多個進程的并行執行,為了避免死鎖,系統動態的確定是否分配一個資源給請求的進程。
預防死鎖:具體的做法是破壞產生死鎖的四個必要條件之一。
銀行家算法:該算法需要檢查申請者對各類資源的最大需求量,如果現存的各類資源可以滿足當前它對各類資源的最大需求量時,就滿足當前的申請。換言之,僅當申請者可以在一定時間內無條件歸還它所申請的全部資源時,才能把資源分配給它。這樣申請者就可以很快完成其計算,然后釋放它占用的資源,從而保證了系統中的所有進程都能完成,所以可以避免死鎖的發生。這種算法的主要問題是,要求每個進程必須先知道資源的最大需求量,而且在系統的運行過程中,考察每個進程對各類資源的申請需花費較多的時間。另外,這一算法本身也有些保守,因為它總是考慮最壞可能的情況。
其他
Redis
1、什么是Redis?簡述它的優缺點?
Redis本質上是一個Key-Value類型的內存數據庫,很像memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據flush到硬盤上進行保存。
因為是純內存操作,Redis的性能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB。
Redis的出色之處不僅僅是性能,Redis最大的魅力是支持保存多種數據結構,此外單個value的最大限制是1GB,不像 memcached只能保存1MB的數據,因此Redis可以用來實現很多有用的功能。
比方說用他的List來做FIFO雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的Set可以做高性能的tag系統等等。
另外Redis也可以對存入的Key-Value設置expire時間,因此也可以被當作一 個功能加強版的memcached來用。 Redis的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要局限在較小數據量的高性能操作和運算上。
2、Redis相比memcached是一套分布式的高速緩存系統,有哪些優勢?
(1) memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數據類型
(2) redis的速度比memcached快很多
(3) redis可以持久化其數據
3、Redis支持哪幾種數據類型?
String、List、Set、Sorted Set、hashes
4、Redis主要消耗什么物理資源?
內存。
5、Redis的全稱是什么?
Remote Dictionary Server。
6、Redis有哪幾種數據淘汰策略?
6中淘汰策略。
noeviction:返回錯誤當內存限制達到并且客戶端嘗試執行會讓更多內存被使用的命令(大部分的寫入指令,但DEL和幾個例外)
allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數據有空間存放。
volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵,使得新添加的數據有空間存放。
allkeys-random: 回收隨機的鍵使得新添加的數據有空間存放。
volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限于在過期集合的鍵。
volatile-ttl: 回收在過期集合的鍵,并且優先回收存活時間(TTL)較短的鍵,使得新添加的數據有空間存放。
7、Redis官方為什么不提供Windows版本?
因為目前Linux版本已經相當穩定,而且用戶量很大,無需開發windows版本,反而會帶來兼容性等問題。
8、一個字符串類型的值能存儲最大容量是多少?
512M
9、為什么Redis需要把所有數據放到內存中?
Redis為了達到最快的讀寫速度將數據都讀到內存中,并通過異步的方式將數據寫入磁盤。
所以redis具有快速和數據持久化的特征。如果不將數據放在內存中,磁盤I/O速度為嚴重影響redis的性能。
在內存越來越便宜的今天,redis將會越來越受歡迎。 如果設置了最大使用的內存,則數據已有記錄數達到內存限值后不能繼續插入新值。
10、Redis集群方案應該怎么做?都有哪些方案?
1.codis。
目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在 節點數量改變情況下,舊節點數據可恢復到新hash節點。
2.redis cluster3.0自帶的集群,特點在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持節點設置從節點。具體看官方文檔介紹。
4.在業務代碼層實現,起幾個毫無關聯的redis實例,在代碼層,對key 進行hash計算,然后去對應的redis實例操作數據。 這種方式對hash層代碼要求比較高,考慮部分包括,節點失效后的替代算法方案,數據震蕩后的自動腳本恢復,實例的監控,等等。
11、Redis集群方案什么情況下會導致整個集群不可用?
有A,B,C三個節點的集群,在沒有復制模型的情況下,如果節點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用。
12、MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據?
redis內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。
13、Redis有哪些適合的場景?
(1)會話緩存(Session Cache)
最常用的一種使用Redis的情景是會話緩存(session cache)。用Redis緩存會話比其他存儲(如Memcached)的優勢在于:Redis提供持久化。當維護一個不是嚴格要求一致性的緩存時,如果用戶的購物車信息全部丟失,大部分人都會不高興的,現在,他們還會這樣嗎?
幸運的是,隨著 Redis 這些年的改進,很容易找到怎么恰當的使用Redis來緩存會話的文檔。甚至廣為人知的商業平臺Magento也提供Redis的插件。
(2)全頁緩存(FPC)
除基本的會話token之外,Redis還提供很簡便的FPC平臺。回到一致性問題,即使重啟了Redis實例,因為有磁盤的持久化,用戶也不會看到頁面加載速度的下降,這是一個極大改進,類似PHP本地FPC。
再次以Magento為例,Magento提供一個插件來使用Redis作為全頁緩存后端。
此外,對WordPress的用戶來說,Pantheon有一個非常好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面。
(3)隊列
Reids在內存存儲引擎領域的一大優點是提供 list 和 set 操作,這使得Redis能作為一個很好的消息隊列平臺來使用。Redis作為隊列使用的操作,就類似于本地程序語言(如Python)對 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”,你馬上就能找到大量的開源項目,這些項目的目的就是利用Redis創建非常好的后端工具,以滿足各種隊列需求。例如,Celery有一個后臺就是使用Redis作為broker,你可以從這里去查看。
(4)排行榜/計數器
Redis在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執行這些操作的時候變的非常簡單,Redis只是正好提供了這兩種數據結構。
所以,我們要從排序集合中獲取到排名最靠前的10個用戶–我們稱之為“user_scores”,我們只需要像下面一樣執行即可:
當然,這是假定你是根據你用戶的分數做遞增的排序。如果你想返回用戶及用戶的分數,你需要這樣執行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一個很好的例子,用Ruby實現的,它的排行榜就是使用Redis來存儲數據的,你可以在這里看到。
(5)發布/訂閱
最后(但肯定不是最不重要的)是Redis的發布/訂閱功能。發布/訂閱的使用場景確實非常多。我已看見人們在社交網絡連接中使用,還可作為基于發布/訂閱的腳本觸發器,甚至用Redis的發布/訂閱功能來建立聊天系統!
14、Redis支持的Java客戶端都有哪些?官方推薦用哪個?
Redisson、Jedis、lettuce等等,官方推薦使用Redisson。
15、Redis和Redisson有什么關系?
Redisson是一個高級的分布式協調Redis客服端,能幫助用戶在分布式環境中輕松實現一些Java的對象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。
16、Jedis與Redisson對比有什么優缺點?
Jedis是Redis的Java實現的客戶端,其API提供了比較全面的Redis命令的支持;
Redisson實現了分布式和可擴展的Java數據結構,和Jedis相比,功能較為簡單,不支持字符串操作,不支持排序、事務、管道、分區等Redis特性。Redisson的宗旨是促進使用者對Redis的關注分離,從而讓使用者能夠將精力更集中地放在處理業務邏輯上。
17、Redis如何設置密碼及驗證密碼?
設置密碼:config set requirepass 123456
授權密碼:auth 123456
18、說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節點負責一部分hash槽。
19、Redis集群的主從復制模型是怎樣的?
為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品.
20、Redis集群會有寫操作丟失嗎?為什么?
Redis并不能保證數據的強一致性,這意味這在實際中集群在特定的條件下可能會丟失寫操作。
21、Redis集群之間是如何復制的?
異步復制
22、Redis集群最大節點個數是多少?
16384個。
23、Redis集群如何選擇數據庫?
Redis集群目前無法做數據庫選擇,默認在0數據庫。
24、怎么測試Redis的連通性?
ping
25、Redis中的管道有什么用?
一次請求/響應服務器能實現處理新的請求即使舊的請求還未被響應。這樣就可以將多個命令發送到服務器,而不用等待回復,最后在一個步驟中讀取該答復。
這就是管道(pipelining),是一種幾十年來廣泛使用的技術。例如許多POP3協議已經實現支持這個功能,大大加快了從服務器下載新郵件的過程。
26、怎么理解Redis事務?
事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。
事務是一個原子操作:事務中的命令要么全部被執行,要么全部都不執行。
27、Redis事務相關的命令有哪幾個?
MULTI、EXEC、DISCARD、WATCH
28、Redis key的過期時間和永久有效分別怎么設置?
EXPIRE和PERSIST命令。
29、Redis如何做內存優化?
盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數少)使用的內存非常小,所以你應該盡可能的將你的數據模型抽象到一個散列表里面。
比如你的web系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表里面。
30、Redis回收進程如何工作的?
一個客戶端運行了新的命令,添加了新的數據。
Redi檢查內存使用情況,如果大于maxmemory的限制, 則根據設定好的策略進行回收。
一個新的命令被執行,等等。
所以我們不斷地穿越內存限制的邊界,通過不斷達到邊界然后不斷地回收回到邊界以下。
如果一個命令的結果導致大量內存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內存限制就會被這個內存使用量超越。
redis分布式鎖?
setnx(set if not exist)和expire、delete聯合實現(假設各個客戶端時鐘大致相同,誤差處于可接受范圍)釋放鎖的操作用lua腳本實現來保證原子性。在集群環境下分布式鎖的key值應當是隨機的不可重復的,否則如果一個客戶端獲得了鎖,但發生了阻塞,當鎖過期redis自動釋放了資源,這時第二個客戶端獲得了鎖,客戶端1此時從阻塞中恢復釋放了鎖,就會造成混亂。
為什么Redis是單線程的
單線程指的是網絡請求模塊使用了一個線程(所以不需考慮并發安全性),即一個線程處理所有網絡請求,其他模塊仍用了多個線程(epoll模型)。
因為Redis是基于內存的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器內存的大小或者網絡帶寬。既然單線程容易實現,而且CPU不會成為瓶頸,那就順理成章地采用單線程的方案了。
Redis為什么這么快
1、完全基于內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中,類似于HashMap,HashMap的優勢就是查找和操作的時間復雜度都是O(1);
2、數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的;
3、采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗;
4、使用多路I/O復用模型,非阻塞IO;
5、使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;
(1)多路 I/O 復用模型
多路I/O復用模型是利用 select、poll、epoll 可以同時監察多個流的 I/O 事件的能力,在空閑的時候,會把當前線程阻塞掉,當有一個或多個流有 I/O 事件時,就從阻塞態中喚醒,于是程序就會輪詢一遍所有的流(epoll 是只輪詢那些真正發出了事件的流),并且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。
這里“多路”指的是多個網絡連接,“復用”指的是復用同一個線程。采用多路 I/O 復用技術可以讓單個線程高效的處理多個連接請求(盡量減少網絡 IO 的時間消耗),且 Redis 在內存中操作數據的速度非常快,也就是說內存內的操作不會成為影響Redis性能的瓶頸,主要由以上幾點造就了 Redis 具有很高的吞吐量。
緩存雪崩、緩存穿透、緩存熱點?
一、緩存穿透預防及優化
緩存穿透是指查詢一個根本不存在的數據,緩存層和存儲層都不會命中,但是出于容錯的考慮,如果從存儲層查不到數據則不寫入緩存層,如圖 11-3 所示整個過程分為如下 3 步:
- 緩存層不命中
- 存儲層不命中,所以不將空結果寫回緩存
- 返回空結果
緩存穿透將導致不存在的數據每次請求都要到存儲層去查詢,失去了緩存保護后端存儲的意義。 緩存穿透問題可能會使后端存儲負載加大,由于很多后端存儲不具備高并發性,甚至可能造成后端存儲宕掉。通常可以在程序中分別統計總調用數、緩存層命中數、存儲層命中數,如果發現大量存儲層空命中,可能就是出現了緩存穿透問題。
造成緩存穿透的基本有兩個。第一,業務自身代碼或者數據出現問題,第二,一些惡意攻擊、爬蟲等造成大量空命中,下面我們來看一下如何解決緩存穿透問題。
二、緩存穿透的解決方法
1)緩存空對象
如下圖所示,當第 2 步存儲層不命中后,仍然將空對象保留到緩存層中,之后再訪問這個數據將會從緩存中獲取,保護了后端數據源。
緩存空對象會有兩個問題:
第一,空值做了緩存,意味著緩存層中存了更多的鍵,需要更多的內存空間 ( 如果是攻擊,問題更嚴重 ),比較有效的方法是針對這類數據設置一個較短的過期時間,讓其自動剔除。
第二,緩存層和存儲層的數據會有一段時間窗口的不一致,可能會對業務有一定影響。例如過期時間設置為 5 分鐘,如果此時存儲層添加了這個數據,那此段時間就會出現緩存層和存儲層數據的不一致,此時可以利用消息系統或者其他方式清除掉緩存層中的空對象。
下面給出了緩存空對象的實現偽代碼:
2)布隆過濾器攔截
如下圖所示,在訪問緩存層和存儲層之前,將存在的 key 用布隆過濾器提前保存起來,做第一層攔截。
例如: 一個個性化推薦系統有 4 億個用戶 ID,每個小時算法工程師會根據每個用戶之前歷史行為做出來的個性化放到存儲層中,但是最新的用戶由于沒有歷史行為,就會發生緩存穿透的行為,為此可以將所有有個性化推薦數據的用戶做成布隆過濾器。如果布隆過濾器認為該用戶 ID 不存在,那么就不會訪問存儲層,在一定程度保護了存儲層。
開發提示:
有關布隆過濾器的相關知識,可以參考: Bloom Filter(布隆過濾器)的概念和原理
可以利用 Redis 的 Bitmaps 實現布隆過濾器,GitHub 上已經開源了類似的方案,讀者可以進行參考:
https://github.com/erikdubbelboer/Redis-Lua-scaling-bloom-filter
使用布隆過濾器應對穿透問題
這種方法適用于數據命中不高,數據相對固定實時性低(通常是數據集較大)的應用場景,代碼維護較為復雜,但是緩存空間占用少。
兩種方案對比
前面介紹了緩存穿透問題的兩種解決方法 ( 實際上這個問題是一個開放問題,有很多解決方法 ),下面通過下表從適用場景和維護成本兩個方面對兩種方案進行分析。
緩存空對象和布隆過濾器方案對比
三、緩存雪崩問題優化
從下圖可以很清晰出什么是緩存雪崩:由于緩存層承載著大量請求,有效的保護了存儲層,但是如果緩存層由于某些原因整體不能提供服務,于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會掛掉的情況。緩存雪崩的英文原意是 stampeding herd(奔逃的野牛),指的是緩層宕掉后,流量會像奔逃的野牛一樣,打向后端存儲。
預防和解決緩存雪崩問題,可以從以下三個方面進行著手。
1)保證緩存層服務高可用性。
和飛機都有多個引擎一樣,如果緩存層設計成高可用的,即使個別節點、個別機器、甚至是機房宕掉,依然可以提供服務,例如前面介紹過的 Redis Sentinel 和 Redis Cluster 都實現了高可用。
2)依賴隔離組件為后端限流并降級。
無論是緩存層還是存儲層都會有出錯的概率,可以將它們視同為資源。作為并發量較大的系統,假如有一個資源不可用,可能會造成線程全部 hang 在這個資源上,造成整個系統不可用。降級在高并發系統中是非常正常的:比如推薦服務中,如果個性化推薦服務不可用,可以降級補充熱點數據,不至于造成前端頁面是開天窗。
在實際項目中,我們需要制定如下目標:
- 減少重建緩存的次數
- 數據盡可能一致
- 較少的潛在危險
云計算?
云計算是一種按使用量付費的模式,這種模式提供可用的、便捷的、按需的網絡訪問, 進入可配置的計算資源共享池,這些資源能夠被快速提供,只需投入很少的管理工作,或與服務供應商進行很少的交互。基礎設施、安裝配置好開發環境、應用服務為云計算三個層面。
大數據的特點?
1.Volume:數據量巨大
體量大是大數據區分于傳統數據最顯著的特征。一般關系型數據庫處理的數據量在TB級,大數據所處理的數據量通常在PB級以上。
2.Variety:數據類型多
大數據所處理的計算機數據類型早已不是單一的文本形式或者結構化數據庫中的表,它包括訂單、日志、BLOG、微博、音頻、視頻等各種復雜結構的數據。
3.Velocity:數據流動快
速度是大數據區分于傳統數據的重要特征。在海量數據面前,需要實時分析獲取需要的信息,處理數據的效率就是組織的生命。
4.Value:數據潛在價值大
在研究和技術開發領域,上述三個特征已經足夠表征大數據的特點。但在商業應用領域,第四個特征就顯得非常關鍵!投入如此巨大的研究和技術開發的努力,就是因為大家
都洞察到了大數據的潛在巨大價值。如何通過強大的機器學習和高級分析更迅速地完成數據的價值“提純”,挖掘出大數據的潛在價值,這是目前大數據應用背景下苛待解決的難題。
大數據發展的瓶頸?
沒有成熟的方法采集和處理大數據。
數據涉及到隱私,法律法規還沒有完善。
大量不同類別的數據不知道怎么存儲。
數據的獨占性:有價值的數據別人不一定會分享。
人工智能
算力和數據是核心,以及神經網絡、遺傳算法、深度學習。
區塊鏈:blockchain
存儲數據的一個個塊,通過鏈char256算法將塊鏈接起來。
KNN算法的優缺點?
KNN算法的優點:
1、思想簡單,理論成熟,既可以用來做分類也可以用來做回歸;
2、可用于非線性分類;
3、訓練時間復雜度為O(n);
4、準確度高,對數據沒有假設,對outlier不敏感;
缺點:
1、計算量大;
2、樣本不平衡問題(即有些類別的樣本數量很多,而其它樣本的數量很少);
3、需要大量的內存;
其偽代碼如下:
- 計算已知類別數據集中的點與當前點之間的距離;
- 按照距離遞增次序排序;
- 選擇與當前距離最小的k個點;
- 確定前k個點所在類別的出現概率
- 返回前k個點出現頻率最高的類別作為當前點的預測分類。
windows中程序的啟動過程?
Explorer.exe
Windows 能夠流行起來,很大一個原因是它有友好的用戶圖形界面,操作方便簡單,容易上手。在Windows環境下打開一個程序,只要雙擊軟件的圖標就行了,那么它是如何啟動起來的?
當我們啟動電腦進入桌面時,系統會創建 Explorer.exe 進程。Explorer.exe是Windows程序管理器 或者叫 文件資源管理器,用于管理Windows圖形殼,刪除該程序會導致 Windows 圖形界面無法使用。所以,如果有時候我們電腦的桌面空白了,或者藍屏,可以通過 Alt+Ctrl+delete(或者在dos中輸入 taskmgr 命令) 打開任務管理器, 點擊“文件”-> “新建任務”,輸入 "explorer.exe",就可以找回我們的桌面了。
當雙擊某個圖標時,Explorer.exe進程的一個線程會偵測到這個操作,它根據注冊表中的信息取得文件名,然后Explorer.exe 以這個文件名調用 CreateProcess 函數。注冊表中有相關的項保存著雙擊操作的信息,如 exe 文件關聯、啟動 exe 的 Shell 是哪個。PC中的大多其它的進程都是 Explorer.exe 的子進程,因為它們都是由Explorer.exe 進程創建的。
2. CreateProcess 函數的執行過程
(1)CreateProcess 實際上是通過 NtCreateProcess 函數實現的, 此時,系統會創建一個進程內核對象。進程內核對象可以看作是操作系統用來管理進程的小的數據結構,它是在內核堆區分配的一個結構體,是系統用來存放關于進程統計信息的地方。進程內核對象維護了一個句柄表的結構,當進程被初始化之后,其句柄表是空的。當進程內的一個線程通過指定的函數創建了一個內核對象時,內核會為對象分配一塊內存區域并初始化這塊區域,然后內核會在進程的句柄表中查找一個空的入口,找到之后會初始化句柄表的以索引定位的區域。初始化的主要過程就是填充句柄表的一個單元,包括指定內核對象地址,指定訪問碼,指定標記等。
(2)進程內核對象創建后,它的引用計數被置為1。然后系統為剛剛創建的進程分配的進程虛擬地址空間。要注意了,之所以稱為虛擬地址空間,就是因為這塊地址空間并不在內存之中,它只是在硬盤上劃分的被稱為“頁”的文件。每個進程都有自己的虛擬地址空間,在進程初始化的時候,其所有的程序和數據會被加載到這個地址空間中。等到真正運行的時候,系統為每個進程配置的頁表會把虛擬地址映射為真正的物理地址(這個過程,我會在后面的博客中詳細介紹如何映射)。
(3)初始化虛擬地址空間。進程地址空間創建后,Windows的裝載器(loader,也稱為PE裝載器)開始工作,Loader會讀取EXE文件的信息(PE文件)。此時 loader 會檢查PE文件的有效性,如果PE文件有錯誤,進程也就無法啟動了。如果PE文件沒有錯誤,裝載器就把PE文件的內容(二進制代碼)映射到進程的地址空間中,然后讀取 PE文件的導入地址表(Import Table),這里存放有exe文件需要導入的模塊文件(DLL),系統會一一加載這些DLL到進程的地址空間中,具體做法是調用 LoadLibrary 函數加載程序代碼到某個地址,然后系統會映射這些代碼到進程的地址空間中,要知道DLL只需加載一次就可映射到所有進程的地址空間(映射過程我會在后面詳細闡述)中,并為每個DLL維護一個引用計數,當引用計數為 0 時,DLL就從內存中卸載,釋放占用的內存。DLL里面可能又引用了其它的DLL,因此加載DLL時是遞歸形式的,直到加載完Import Table 里描述的所有DLL模塊,此時進程初始化部分完成。
(4)創建進程的主線程。當進程的初始化完成后,開始創建進程的主線程,一個進程至少要有一個主線程才能運行,可以說進程只是充當一個容器的作用,而線程才是執行代碼的載體。線程是用 CreateThread 這個函數創建的。創建線程時,也和進程相似,系統會創建線程內核對象,初始化線程堆棧。線程堆棧有兩個,一個是核心堆棧,由核心態維護;另一個是用戶堆棧,運行在用戶態下。同樣的,線程的引用計數也置為1。
(5)C/C++運行期庫初始化。當進程的主線程初始化完成后,并且線程得到了CPU時間片,CPU把CS:IP指向程序入口(OEP),這個地址相當重要,因為這是程序運行時第一條指令所在的地址(我們可以使用一些PE輔助工具來查看PE文件的地址信息,注意真實地址==偏移地址 + 基址)。其實,CS:IP指向的地址處是一條JMP指令,它跳轉到程序真正的入口函數,入口函數有以下4種形式:
···
mainCRTStartup (用于 ANSI 版本的控制臺應用程序 )
wmainCRTStartup ( 用于 Unicode 版本的控制臺應用程序 )
WinMainCRTStartup ( 用于 ANSI 版本的窗口應用程序 )
wWinMainCRTStartup ( 用于 Unicode 版本的窗口應用程序)
·
數據挖掘的信息熵?
信息是個很抽象的概念。人們常常說信息很多,或者信息較少,但卻很難說清楚信息到底有多少。比如一本五十萬字的中文書到底有多少信息量。直到1948年,香農提出了“信息熵”的概念,才解決了對信息的量化度量問題。
公式為:H(x)=E[I(xi)]=E[ log(2,1/p(xi)) ]=-∑p(xi)log(2,p(xi)) (i=1,2,..n)該值越大表示信息量越大
在一個系統中,該系統越混亂,那么就越難把它搞清楚,需要的信息量就越大,信息熵就越大,回到數據挖掘中用決策樹進行分類中,在分類的之前,我們需要建立一個決策樹,在建立決策樹的時候屬性的選擇是一個非常關鍵的問題,我們選擇的屬性的標準是讓劃分盡量純(落在給定劃分中的元祖都屬于相同類的越多,那么就越純),結合上面我們可以推理出如果按照某個屬性劃分后,每個該屬性屬性值所對應的元組越統一(元組所屬的類別越統一),那么我們這個屬性的選擇就越符合我們的需求。和信息熵結合,就是選擇該屬性之后,所有屬性值對應的分類的信息熵之和越小,那么我們元組分類所需要的平均信息越少,該屬性就越符合我們的要求
決策樹?
決策樹模型是一類算法的集合,在數據挖掘十大算法中,具體的決策樹算法占有兩席位置,即C4.5和CART算法,本文都會介紹到它們。
決策樹基礎
決策樹是一種用于對實例進行分類的樹形結構。決策樹由節點(node)和有向邊(directed edge)組成。節點的類型有兩種:內部節點和葉子節點。其中,內部節點表示一個特征或屬性的測試條件(用于分開具有不同特性的記錄),葉子節點表示一個分類。
一旦我們構造了一個決策樹模型,以它為基礎來進行分類將是非常容易的。具體做法是,從根節點開始,地實例的某一特征進行測試,根據測試結構將實例分配到其子節點(也就是選擇適當的分支);沿著該分支可能達到葉子節點或者到達另一個內部節點時,那么就使用新的測試條件遞歸執行下去,直到抵達一個葉子節點。當到達葉子節點時,我們便得到了最終的分類結果。