学习笔记2
1. 分享:Java垃圾回收機制
一、常用垃圾回收機制
1. 標記-清除算法(mark-sweep)
顧名思義,標記-清除算法分為兩個階段,標記(mark)和清除(sweep).
在標記階段,collector從mutator根對象開始進行遍歷,對從mutator根對象可以訪問到的對象都打上一個標識,一般是在對象的header中,將其記錄為可達對象。
而在清除階段,collector對堆內存(heap memory)從頭到尾進行線性的遍歷,如果發現某個對象沒有標記為可達對象-通過讀取對象的header信息,則就將其回收。
從上圖我們可以看到,在Mark階段,從根對象1可以訪問到B對象,從B對象又可以訪問到E對象,所以B,E對象都是可達的。同理,F,G,J,K也都是可達對象。到了Sweep階段,所有非可達對象都會被collector回收。同時,Collector在進行標記和清除階段時會將整個應用程序暫停(mutator),等待標記清除結束后才會恢復應用程序的運行。
缺點:
? 標記-清除算法的比較大的缺點就是垃圾收集后有可能會造成大量的內存碎片,像上面的圖片所示,垃圾收集后內存中存在三個內存碎片,假設一個方格代表1個單位的內存,如果有一個對象需要占用3個內存單位的話,那么就會導致Mutator一直處于暫停狀態,而Collector一直在嘗試進行垃圾收集,直到Out of Memory。
2. 標記-壓縮算法(mark-compact)
? 顧名思義,標記-壓縮算法分為兩個階段,標記(mark)和壓縮(compact).
? 其中標記階段跟標記-清除算法中的標記階段是一樣的,而對于壓縮階段,它的工作就是移動所有的可達對象到堆內存的同一個區域中,使他們緊湊的排列在一起,從而將所有非可達對象釋放出來的空閑內存都集中在一起,通過這樣的方式來達到減少內存碎片的目的。
3. 復制算法(copying)
堆內存對半分為兩個半區,只用其中一個半區來進行對象內存的分配,如果在這個半區內存不夠給新的對象分配了,那么就開始進行垃圾收集,將這個半區中的所有可達對象都拷貝到另外一個半區中去,然后繼續在另外那個半區進行新對象的內存分配。
?
**缺點: **
? 內存壓縮為原來的一半,利用率比較低,典型的空間換時間
4. 引用計數算法(reference counting)
? 通過在對象頭中分配一個空間來保存該對象被引用的次數。如果該對象被其它對象引用,則它的引用計數加一,如果刪除對該對象的引用,那么它的引用計數就減一,當該對象的引用計數為0時,那么該對象就會被回收。
? 采用引用計數的垃圾收集機制跟前面三種垃圾收集機制最大的不同在于,垃圾收集的開銷被分攤到整個應用程序的運行當中了,而不是在進行垃圾收集時,要掛起整個應用的運行,直到對堆中所有對象的處理都結束。因此,采用引用計數的垃圾收集不屬于嚴格意義上的"Stop-The-World"的垃圾收集機制。
注意:
-
當某個對象的引用計數減為0時,collector需要遞歸遍歷它所指向的所有域,將它所有域所指向的對象的引用計數都減一,然后才能回收當前對象。
-
但是這種引用計數算法有一個比較大的問題,那就是它不能處理環形數據 - 即如果有兩個對象相互引用,那么這兩個對象就不能被回收,因為它們的引用計數始終為1。這也就是我們常說的“內存泄漏”問題。如下圖:
5. 分代收集算法
? 當前的商業虛擬機都采用的是”分代收集“算法,一般是把java堆分成新生代和老生代,這樣就可以根據各個年代的特點采用最適當的垃圾收集算法,新生代中,對象大多是”朝生夕死“可以采用復制算法,而老年代的對象存活率比較高,而且沒有擔??臻g進行內存分配,就要采用”標記-清除算法“或者”標記-整理“算法。
##?二、Java垃圾回收
1. Java的內存分布
其中,堆內存分為年輕代和年老代,非堆內存主要是Permanent區域,主要用于存儲一些類的元數據,常量池等信息。而年輕代又分為兩種,一種是Eden區域,另外一種是兩個大小對等的Survivor區域。
2. Java年輕代垃圾回收機制
? 部分的新創建對象分配在新生代。因為大部分對象很快就會變得不可達,所以它們被分配在新生代,然后消失不再。當對象從新生代移除時,我們稱之為"Minor GC"。新生代使用的是復制收集算法。
? 新生代劃分為三個部分:分別為Eden、Survivor from、Survivor to,大小比例為8:1:1(為了防止復制收集算法的浪費內存過大)。每次只使用Eden和其中的一塊Survivor,回收時將存活的對象復制到另一塊Survivor中,這樣就只有10%的內存被浪費,但是如果存活的對象總大小超過了Survivor的大小,那么就把多出的對象放入老年代中。
在三個區域中有兩個是Survivor區。對象在三個區域中的存活過程如下:
如上所述,兩個Survivor區域在任何時候必定有一個保持空白。如果同時有數據存在于兩個Survivor區或者兩個區域的的使用量都是0,則意味著你的系統可能出現了運行錯誤。
3. Java老年代垃圾回收機制
? 存活在新生代中但未變為不可達的對象會被復制到老年代。一般來說老年代的內存空間比新生代大,所以在老年代GC發生的頻率較新生代低一些。當對象從老年代被移除時,我們稱之為 "Major GC"(或者Full GC)。 老年代使用標記-清理或標記-整理算法
空間分配擔保
在發生Minor GC前,虛擬機會先檢查老年代最大可用的連續空間是否大于新生代所有對象總空間。
如果大于,那么Minor GC可以確保是安全的。
如果小于,虛擬機會查看HandlePromotionFailure設置值是否允許擔任失敗。
- 如果允許,那么會繼續檢查老年代最大可用連續空間是否大于歷次晉升老年代對象的平均大小
- 如果大于,將嘗試著進行一次Minor GC,盡管這次Minor GC是有風險的
- 如果小于,進行一次Full GC
- 如果不允許,也要改為進行一次Full GC
? 前面提到過,新生代使用復制收集算法,但為了內存利用率,只使用其中一個Survivor空間來作為輪換備份,因此當出現大量對象在Minor GC后仍然存活的情況時(最極端就是內存回收后新生代中所有對象都存活),就需要老年代進行分配擔保,讓Survivor無法容納的對象直接進入老年代。與生活中的貸款擔保類似,老年代要進行這樣的擔保,前提是老年代本身還有容納這些對象的剩余空間,一共有多少對象會活下來,在實際完成內存回收之前是無法明確知道的,所以只好取之前每一次回收晉升到老年代對象容量的平均大小值作為經驗值,與老年代的剩余空間進行比較,決定是否進行Full GC來讓老年代騰出更多空間。
? 取平均值進行比較其實仍然是一種動態概率的手段,也就是說如果某次Minor GC存活后的對象突增,遠遠高于平均值的話,依然會導致擔保失敗(Handle Promotion Failure)。如果出現了HandlePromotionFailure失敗,那就只好在失敗后重新發起一次Full GC。雖然擔保失敗時繞的圈子是最大的,但大部分情況下都還是會將HandlePromotionFailure開關打開,避免Full GC過于頻繁。
2.Java垃圾收集器
-
Serial收集器(Serial/Serial Old)
Serial是一個單線程的收集器,但它的“單線程”意義并不僅僅說明它只會使用一個CPU或一條手機此案成去完成垃圾和收集工作,更重要的是它進行垃圾收集時,必須暫停其他所有的工作線程,直到它收集結束。
-
ParNew收集器
ParNew收集器其實就是Serial收集器的多線程版本。
它是運行在Server模式下的虛擬機中首選的新生代收集器,其中有一個與性能無關但很重要的原因是:除了Serial收集器外,目前只有它能與CMS收集器配合工作。
-
Parallel Scavenge收集器
? 該收集器也是一個新生代的垃圾收集器,他也是使用復制算法的收集器,又是一個并行的垃圾收集器。該收集器的特點是他的關注點與其他的收集器不同,CMS等收集器的關注點是盡可能縮短垃圾回收時用戶線程的停頓時間,而parallel Scavenge收集器的目標是達到一個可控制的吞吐量。所謂吞吐量就是CPU用于運行代碼的時間與CPU總消耗時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾回收時間),比如虛擬機總共運行100分鐘,垃圾回收占用了1分鐘,那么吞吐量就是99%。
-
Parallel Old收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。
-
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。CMS是基于“標記-清除”算法實現的,它的運作過程相對于前面幾種收集器來說更復雜一些,整個過程分為4個步驟,包括:
- 初始標記(CMS initial mark)
- 并發標記(CMS concurrent mark)
- 重新標記(CMS remark)
- 并發清除(CMS concurrent sweep)
其中,初始標記、重新標記這兩個步驟仍然需要”Stop The world”。初始標記僅僅只是標記一下GC Roots Tracing的過程,而重新標記階段則是為了修正并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比并發標記的時間短。
由于整個過程中耗時最長的并發標記和并發清除過程收集器線程都可以與用戶線程一起工作,所以,從總體上來說,CMS收集器的內存回收過程是與用戶線程一起并發執行的。
**CMS的優勢:**并發收集、低停頓。
CMS的缺點:
- 對CPU資源非常敏感。CMS默認啟動的回收線程數是(CPU數量 + 3)/4,并發回收時垃圾收集線程所占CPU資源隨著CPU數量的增加而下降,而且在CPU不足4個時,CMS對用戶程序的影響就可能變得很大,導致執行速度降低。
- CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure”失敗而導致另一次Full GC的產生。
- CMS是一款基于“標記-清除”算法實現的收集器,這意味著收集結束時會有大量空間碎片產生。空間碎片太多的時候,將會給大對象分配帶來很大麻煩。
-
G1收集器
G1是一款面向服務端應用的垃圾收集器。HOtSpot開發團隊賦予它的使命是未來可以替換掉CMS收集器。
G1具備如下特點:
- **并行與并發:**G1能充分利用多CPU、多核環境下的硬件優勢,使用多個CPU來縮短Stop-The-World停頓的時間,部分其他收集器原本需要停頓Java線程執行的GC動作,G1收集器仍然可以通過并發的方式讓Java程序繼續執行。
- **分代收集:**雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但它能夠采用不同的方式去處理新創建的對象和已經存活了一段時間、熬過多次GC的就對象以獲取更好的收集效果。
- 空間整合:G1從整體上來看是基于“標記-整理”算法實現的收集器,從局部(兩個Region之間)上來看是基于“復制”算法實現的,這意味著G1運作期間不會產生內存空間碎片,收集后能提供規整的可用內存。
- 可預測的停頓:這是G1相對于CMS的另一大優勢。
?
G1垃圾收集器和CMS垃圾收集器有幾點不同。首先,最大的不同是內存的組織方式變了。Eden,Survivor和Tenured等內存區域不再是連續的了,而是變成了一個個大小一樣的region - 每個region從1M到32M不等。
?
?
一個region有可能屬于Eden,Survivor或者Tenured內存區域。圖中的E表示該region屬于Eden內存區域,S表示屬于Survivor內存區域,T表示屬于Tenured內存區域。圖中空白的表示未使用的內存空間。G1垃圾收集器還增加了一種新的內存區域,叫做Humongous內存區域,如圖中的H塊。這種內存區域主要用于存儲大對象-即大小超過一個region大小的50%的對象。
?
在G1垃圾收集器中,年輕代的垃圾回收過程跟PS垃圾收集器和CMS垃圾收集器差不多。
?
對于年老代上的垃圾收集,G1垃圾收集器也分為4個階段,基本跟CMS垃圾收集器一樣,但略有不同:
-
Initial Mark階段 - 同CMS垃圾收集器的Initial Mark階段一樣,G1也需要暫停應用程序的執行,它會標記從根對象出發,在根對象的第一層孩子節點中標記所有可達的對象。但是G1的垃圾收集器的Initial Mark階段是跟minor gc一同發生的。也就是說,在G1中,你不用像在CMS那樣,單獨暫停應用程序的執行來運行Initial Mark階段,而是在G1觸發minor gc的時候一并將年老代上的Initial Mark給做了。
-
Concurrent Mark階段 - 在這個階段G1做的事情跟CMS一樣。但G1同時還多做了一件事情,那就是,如果在Concurrent Mark階段中,發現哪些Tenured region中對象的存活率很小或者基本沒有對象存活,那么G1就會在這個階段將其回收掉,而不用等到后面的clean up階段。這也是Garbage First名字的由來。同時,在該階段,G1會計算每個 region的對象存活率,方便后面的clean up階段使用 。
-
Remark階段 - 在這個階段G1做的事情跟CMS一樣, 但是采用的算法不同,能夠在Remark階段更快的標記可達對象。
-
Clean up/Copy階段 - 在G1中,沒有CMS中對應的Sweep階段。相反 它有一個Clean up/Copy階段,在這個階段中,G1會挑選出那些對象存活率低的region進行回收,這個階段也是和minor gc一同發生的,如下圖所示:
從上可以看到,由于Initial Mark階段和Clean up/Copy階段都是跟minor gc同時發生的,相比于CMS,G1暫停應用程序的時間更少,從而提高了垃圾回收的效率。
?
2. Octave學習
內建基本數學函數
cos???余弦函數 (弧度制) sin??? 正弦函數 (弧度制) tan ???正切函數 (弧度制) exp ???指數函數 (e x ) log ???以 e 為底的指數函數 log10?? 以 10 為底的指數函數? sinh ???雙曲正弦函數 tanh ???雙曲正切函數 cosh ???雙曲余弦函數 acos ???反余弦函數 acosh ??反雙曲余弦函數 asin ???反正弦函數 asinh ??反雙曲正弦函數 atan ???反正切函數 atanh ???反雙曲正切函數 abs ????絕對值函數 (復數取模) round ????四舍五入 floor ????近似為比它小的最大整數 ceil????? 近似為比它大的最小整數 fix ??????向 0 方向近似 rem????? 求余數
變量
Octave 中變量的類型是不用聲明的。Octave 所有的變量都是浮點型或者字符串。
如:deg=pi/180
注:ans 變量存儲你每次最近運算的結果。
數組和向量
示例:a = [1 4 5] b = [1, 4, 5] c = [1; 4; 5] 在方括號中由空格或者逗號隔開的一組數據被定義為行向量; 而由分號或者回車隔開的一組數據被定義為列向量。
冒號表達式
示例:a = 2: 6 即 a = [2 3 4 5 6]
? a = 2: 0.5: 4 即 a = [2.0000 2.5000 3.0000 3.5000 4.0000]
向量中的元素操作
a=[1:2:6 -1 0] 則 a(3) 為 5
注:向量中的元素通過括號 (),而第一個元素的編號為 1
向量計算
使用 +? 算符,你同樣可以對該向量中的每個元素都加上或者減去一個數值。
兩個向量的相乘遵循矩陣的乘法法則,向量乘法并不是對應元素的相乘。如果要進行對應元素的乘除法,你可以使用
.* 和 ./ (注意前面有個點)
基本畫圖命令: plot(x, y) x為橫軸,y為縱軸
控制語句
判斷語句:if expression ? statements ? elseif ? expression ? statements
? else ? statements ? end
switch語句 :switch x
? case x1 ? statements ? case x2 ? statements ? otherwise ? statements ? end
for 循環:for variable=vector ? statements ? end
while循環:while expression ? statements ? end
函數
示例:function s=sind(x) ? % SIND(x) Calculates sine(x) in degrees ? s=sin(x*pi/180); ? endfunction
矩陣和向量
- 矩陣構建
? 在 Octave 中輸入矩陣與輸入向量相似,逐行輸入: ? octave:##> A= [ 5 7 9 ? -1 3 -2 ]
? 或者使用分號來標定一行的結束,例如: ? octave:##> B=[2 0; 0 -1; 1 0] ? octave:##> B= ? 2 0 ? 0 -1 ? 1 0
? 其他: 單位矩陣創建: I = eye(4)
? 對角矩陣創建: M = diag([-1 7 4]) -1 7 4 為對角的值
-
矩陣轉置符 如:A'
-
提取矩陣元
如: J(1, 3) 1, 3 分別為行號和列號
? J(1:3, 5) 1到3行,第五列
-
賦值
如:J(1, 3) = 4
-
基本矩陣函數
eye 創建單位矩陣 zeros 創建全零矩陣 ones 創建全一矩陣 rand 創建隨機數矩陣 diag 創建一個對角矩陣,或者提取一個矩陣的對角元 inv 求矩陣逆矩陣 trace 求矩陣的跡 rank 求矩陣的秩
3. 吳恩達課程學習
-
機器學習的兩種方式:
-
有監督學習:類似與我知道一個問題的答案,所以我可以從這個答案問題出發設計出一個推理邏輯。
受監督的學習問題分為“回歸”和“分類”問題。在回歸問題中,我們試圖在連續輸出中預測結果,這意味著我們正在嘗試將輸入變量映射到一些連續函數。在分類問題中,我們試圖用離散輸出來預測結果。換句話說,我們正在嘗試將輸入變量映射到離散類別。
示例:?回歸 - 鑒于一個人的照片,我們必須根據給定的圖片來預測他們的年齡
????分類 - 鑒于腫瘤患者,我們必須預測腫瘤是惡性還是良性
-
無監督學習:類似于我給你一堆數據,你也不知道它是干什么用的,但是你或許可以找出這些數據中蘊含的某種規律。無監督學習問題可分為聚類和非聚類兩種。
聚類:收集100萬個不同的基因,并找到一種自動將這些基因組合成不同變量(如壽命,位置,作用等)相似或相關的組。
非聚類:“雞尾酒會算法”,讓您在混亂的環境中找到結構。(即從雞尾酒會的聲音網格中識別個人的聲音和音樂)。
-
-
模型表示
為了更準確地描述監督學習問題,我們的目標是給出一個訓練集,以學習一個函數h:X→Y,使得h(x)是相應的y值的“好”預測因子。由于歷史原因,這個函數h被稱為假設。從形象上看,這個過程是這樣的:
-
成本函數
我們可以通過使用成本函數來衡量假設函數的準確性。這取決于x的輸入和實際輸出y的假設的所有結果的平均差異(實際上是平均值的平均值)。
-
梯度下降
?
上圖中的每個“星”之間的距離表示由我們的參數α確定的步長。較小的α將導致較小的步長,較大的α導致較大的步長。采取步驟的方向由偏導數決定?(i0,θ1)。根據圖上的哪一個開始,人們可能會在不同的地方結束。上圖顯示了兩個不同的起點,最終出現在兩個不同的地方。
下圖展示了梯度向下的算式,當左式恒等于右式之時,找到局部最優解。
-
線性回歸的梯度下降

上面所示的橢圓是二次函數的輪廓。還顯示了由(48,30)初始化的梯度下降所采取的軌跡。圖中的x(由直線連接)標記梯度下降經過的θ的連續值,因為它收斂到最小值。
-
-
特征縮放
們可以通過使我們的每個輸入值在大致相同的范圍內來加快梯度下降。這是因為在較小的范圍內,θ會快速下降,而在較大的范圍內會慢慢下降,因此當變量非常不均勻時,它會低效地擺動到最佳狀態。
防止這種情況的方法是修改輸入變量的范圍,使其大致相同。理想的情況是:
-1 <= X <= 1 或者 -0.5 <= X <= 0.5
計算公式:

? 分母為范圍。。。。
-
學習比率
**調試梯度下降。**在x軸上繪制一個迭代次數的圖?,F在繪制成本函數J(θ)超過梯度下降次數。如果J(θ)增加,那么您可能需要減少α。
如果 一 太小:收斂緩慢
如果 一 太大:每次迭代都不能減少,從而可能不會收斂。
-
特征和多項式回歸
我們可以通過幾種不同的方式改進我們的特征和我們的假設函數的形式。
我們可以將多個功能組合成一個。例如,我們可以結合X1 和 X2 成為新功能 X3 通過服用 X1?X2.
多項式回歸
如果不符合數據,我們的假設函數不需要是線性的(直線)。
我們可以通過使其成為二次,立方或平方根函數(或任何其他形式)來改變假設函數的行為或曲線。
例如,如果我們的假設函數是 H我(x)= θ0+ θ1X1 那么我們可以創建基于的附加功能 X1,得到二次函數 H我(x)= θ0+ θ1X1+ θ2X21 或立方函數 H我(x)= θ0+ θ1X1+ θ2X21+ θ3X31
在立方體版本中,我們創建了新功能 X2 和 X3 哪里 X2= x21 和 X3= x31.
為了使其成為平方根函數,我們可以做: H我(x)= θ0+ θ1X1+ θ2√X1
-
正規方程法
計算公式:θ=(XTX)?1XTy
以下是梯度下降與正態方程的比較:
梯度下降正常方程式 需要選擇alpha 不需要選擇alpha 需要很多次迭代 不需要迭代 T至?2) T?3),需要計算倒數 X?X 當n大時,效果很好 如果n非常大,則慢 -
正態方程不可逆
? 當在八度中實現正態方程時,我們要使用'pinv'函數而不是'inv'。'pinv'功能會給你一個值我 即使 X?X 是不可逆的
? 如果 X?X是**不可逆的,**常見的原因可能是:
- ?冗余特征,其中兩個特征非常密切相關(即它們是線性相關的)
- ? 功能太多(例如m≤n)。在這種情況下,刪除某些功能或使用“正則化”(稍后將講解)。
解決上述問題的方法包括刪除與另一個線性相關的特征或者當具有太多特征時刪除一個或多個特征。
-
邏輯回歸
- 成本函數
我們不能使用與線性回歸相同的成本函數,因為邏輯函數會導致輸出波浪形,導致許多局部最優。換句話說,它不會是一個凸函數。
相反,我們用于邏輯回歸的成本函數如下所示:
-
優化
**"Conjugate gradient", "BFGS", and "L-BFGS" **are more sophisticated, faster ways to optimize θ that can be used instead of gradient descent. We suggest that you should not write these more sophisticated algorithms yourself (unless you are an expert in numerical computing) but use the libraries instead, as they're already tested and highly optimized. Octave provides them.
-
一對多
由于y = {0,1 ... n},我們將問題劃分為n + 1(+1,因為索引從0開始)二進制分類問題; 在每個類中,我們預測'y'是我們其中一個類的成員的概率。
y∈{0,1...n} h(0)θ(x)=P(y=0|x;θ) h(1)θ(x)=P(y=1|x;θ) ? h(n)θ(x)=P(y=n|x;θ) prediction=maxi(h(i)θ(x)) 復制代碼 -
過度擬合
?
圖中左圖為欠擬合,中間的圖片差不多正好,右圖為過擬合
低估或高偏差是當我們的假設函數的形式h映射到數據的趨勢。它通常是由一個功能太簡單或功能太少造成的。在另一個極端,過度擬合或高度變異是由適合可用數據的假設函數引起的,但不能很好地推廣以預測新的數據。這通常是由一個復雜的函數造成的,這個函數會產生大量與數據無關的不必要的曲線和角度。
有兩個主要的選擇來解決過度擬合的問題:
1)減少功能的數量:
- 手動選擇要保留的功能。
- 使用模型選擇算法(在課程后面研究)。
2)正規化
- 保留所有功能,但減少參數的大小 θj.
- 當我們有很多有用的功能時,正則化運作良好。
-
正則化和處罰機制
使用上述成本函數與額外的總和,我們可以平滑我們的假設函數的輸出,以減少過度擬合。如果選擇的lambda太大,可能會使功能過于平滑,導致不足。
-
正規化線性回歸
-
梯度向下
...
-
正規方程
-
是一個矩陣,左上角為0,下角為1,其他地方為0。它應該有尺寸(n + 1)×(n + 1)。直覺上,這是身份矩陣(雖然我們不包括在內)X0)乘以單個實數λ。
回想一下,如果m <n,那么 X?X是不可逆的。但是,當我們添加術語λ?L時,X?X +λ?L變成可逆的。
-
正則化邏輯回歸
邏輯回歸的成本函數:
...
正則化邏輯回歸的成本函數:
...
? -
神經網絡
-
模型表示
讓我們來看看如何使用神經網絡來表示一個假設函數。在一個非常簡單的層面上,神經元基本上是計算單位,它們將輸入(樹突)作為輸入(軸突)的電輸入(稱為“尖峰” )。在我們的模型中,我們的樹突就像輸入的特征X1?x?,輸出是我們假設函數的結果。在這個模型中我們X0輸入節點有時被稱為“偏置單元”。它總是等于1.在神經網絡中,我們使用與分類中相同的邏輯函數,1/(1 + e- θ?X),但我們有時將其稱為sigmoid(邏輯)激活功能。在這種情況下,我們的“theta”參數有時被稱為“權重”。
?
例如:
? Example: If layer 1 has 2 input nodes and layer 2 has 4 activation nodes. Dimension of Θ(1) is going to be 4×3 where sj=2 and sj+1=4, so sj+1×(sj+1)=4×3.
?
?
-
應用
- Examples and Intuitions I
an example of the logical operator 'OR', meaning either x1 is true or x~2~ is true, or both:
Where g(z) is the following:
-
Examples and Intuitions II
here we have the XNOR operator using a hidden layer with two nodes! The following summarizes the above algorithm:
-
多類分類
為了將數據分類到多個類中,我們假設函數返回值的向量。說我們想將我們的數據分為四類。我們將使用下面的例子來看看這個分類是如何完成的。該算法將圖像作為輸入并進行相應的分類:
我們可以將我們的結果類定義為y:
-
代價函數
注意:
- 雙重數額簡單地將輸出層中每個單元格的邏輯回歸成本加起來
- 三元組簡單地將整個網絡中所有單個Θ的平方相加。
- 我在三合一中并不是指訓練示例i
-
反向傳播算法
https://www.coursera.org/learn/machine-learning/supplement/pjdBA/backpropagation-algorithm
https://www.coursera.org/learn/machine-learning/supplement/v5Bu8/backpropagation-intuition
-
梯度檢驗
gradApprox矢量計算方法:
A small value for ? (epsilon) such as ?=10^?4^, guarantees that the math works out properly.
epsilon = 1e-4; for i = 1:n,thetaPlus = theta;thetaPlus(i) += epsilon;thetaMinus = theta;thetaMinus(i) -= epsilon;gradApprox(i) = (J(thetaPlus) - J(thetaMinus))/(2*epsilon) end; 復制代碼一旦我們計算我們的gradApprox矢量,我們可以檢查gradApprox≈deltaVector。
一旦你已經驗證**,一旦**你的BP算法是正確的,則不需要再次計算gradApprox。計算gradApprox的代碼可能非常慢。
-
隨機初始化
將所有的權重初始化為零不適用于神經網絡。反向傳播時,所有節點將重復更新為相同的值。相反,我們可以隨機初始化我們的權重釷 矩陣使用以下方法:
-
培訓一個神經網絡
- 隨機初始化權重
- 實現向前傳播得到hΘ(x(i)) 對于任何y x(i)
- 實施成本函數
- 實施反向傳播以計算偏導數
- 使用梯度檢查來確認您的反向傳播的作品。然后禁用梯度檢查。
- 使用梯度下降或內置的優化功能,以theta中的權重最小化成本函數。
-
4. linux 命令學習
-
cat
- 一次顯示整個文件。$ cat filename
- 從鍵盤創建一個文件。$ cat > filename
-
將幾個文件合并為一個文件: $cat file1 file2 > file
參數:
-n 或 --number 由 1 開始對所有輸出的行數編號 -b 或 --number-nonblank 和 -n 相似,只不過對于空白行不編號 -s 或 --squeeze-blank 當遇到有連續兩行以上的空白行,就代換為一行的空白行
-
創建文件,創建文件后,要以EOF或STOP結束;如:$ cat > linuxsir.org.txt << EOF
-
追加內容 如:$ cat >> linuxsir.txt << EOF
-
一個或多個已存在的文件內容,追加到一個已存在的文件中
如:$ cat sir01.txt sir02.txt sir03.txt >> sir00.txt (與 cat sir01.txt sir02.txt sir03.txt > sir04.txt 區分,此為合并)
? 注:只能創建新文件,不能編輯已有文件.
5. 用戶組和權限
-
文件屬性
- rwx r-x r--
1 234 567 890
1代表問文件名或者目錄, 234代表擁有者的權限,可讀、可寫、可執行(rwx),567代表同用戶組權限,890代表其他用戶權限
改變文件屬性和權限
chgrp: 改變文件所屬用戶組
chown:改變文件所有者 例如: chown [-R] 賬號名稱 文件或者目錄 (-R 遞歸)
chmod:改變文件權限
? 權限分數: r : 4 w: 2 x:1
? 例如: chmod 777 filename (4+2+1=7)
? chmod u =rwx, g=rx, 0=r filename (u-user, g-group, o-others)
? chmod a+x filename 增加權限
? a-x 減少權限
6. 計算機網絡應用層和運輸層
應用層
應用層就定義了位于不同主機中的多個應用進程之間通信的協議。應用層的許多協議都是基于客戶-服務器模式,客戶是服務的請求方,服務器是服務提供方。
HTTP非持續連接和持續連接
-
非持續連接
定義:每個請求/相應對是結果一個單獨的TCP連接發送
我們看看在非持續連接情況下,從服務器向客戶傳送一個Web頁面的步驟。假設該頁面含有一個HTML基本文件和10個JPEG圖形,并且這11個對象位于同一臺服務器上。該HTML文件的URL為:http://www.someSchool.edu/someDepartment/home.index。
我們看看發生了什么情況:
- HTTP客戶進程在端口號80發起一個到服務器www.someSchool.edu的TCP連接,該端口號是HTTP的默認端口。在客戶和服務器上分別有一個套接字與該連接相關聯。
- HTTP客戶經它的套接字向該服務器發送一個HTTP請求報文。請求報文中包含了路徑名/someDepartment/home.index(后面我們會詳細討論HTTP報文)。
- HTTP服務器進程經它的套接字接收該請求報文,從其存儲器(RAM或磁盤)中檢索出對象www.someSchool.edu/someDepartment/home.index,在一個HTTP響應報文中封裝對象,并通過其套接字向客戶發送響應報文。
- HTTP服務器進程通知TCP斷開該TCP連接。(但是直到TCP確認客戶已經完整地收到響應報文為止,它才會實際中斷連接。)
- HTTP客戶接收響應報文,TCP連接關閉。該報文指出封裝的對象是一個HTML文件,客戶從響應報文中提取出該文件,檢查該HTML文件,得到對10個JPEG圖形的引用。
對每個引用的JPEG圖形對象重復前4個步驟。
往返時間計算:粗略地講,總的響應時間就是兩個RTT加上服務器傳輸HTML文件的時間。
-
持續連接
定義:所有請求及其響應經過相同的TCP連接發送
非持續連接有一些缺點。首先,必須為每一個請求的對象建立和維護一個全新的連接。對于每個這樣的連接,在客戶和服務器中都要分配TCP的緩沖區和保持TCP變量,這給Web服務器帶來了嚴重的負擔,因為一臺Web服務器可能同時服務于數以百計不同的客戶的請求。第二,就像我們剛描述的那樣,每一個對象經受兩倍RTT的交付時延,即一個RTT用于創建TCP,另一個RTT用于請求和接收一個對象。
在采用持續連接的情況下,服務器在發送響應后保持該TCP連接打開。在相同的客戶與服務器之間的后續請求和響應報文能夠通過相同的連接進行傳送。特別是,一個完整的Web頁面(上例中的HTML基本文件加上10個圖形)可以用單個持續TCP連接進行傳送。更有甚者,位于同一臺服務器的多個Web頁面在從該服務器發送給同一個客戶時,可以在單個持續TCP連接上進行??梢砸粋€接一個地發出對對象的這些請求,而不必等待對未決請求(流水線)的回答。一般來說,如果一條連接經過一定時間間隔(一個可配置的超時間隔)仍未被使用,HTTP服務器就關閉該連接。HTTP的默認模式是使用帶流水線的持續連接。
HTTP報文格式
-
HTTP請求報文
GET /somedir/page.html HTTP/1.1 HOST: www.someschool.edu Connetion: close User-agent: Mozilla/5.0 Accept-agent: fr 復制代碼 -
HTTP響應報文
HTTP/1.1 200 OK Date: Sat, 31 Dec 2005 23:59:59 GMT Content-Type: text/html;charset=ISO-8859-1 Content-Length: 122 <html> <head> <title>Wrox Homepage</title> </head> <body> <!-- body goes here --> </body> </html> 復制代碼 -
用戶與服務器交互:cookie
由于HTTP是無狀態的,我們可以使用cookie來對用戶進行認證。
-
web緩存器(代理服務器)
請求過程:
-
瀏覽器建立一個到Web緩存器的TCP連接,并向Web緩存器中的對象發送一個HTTP請求。
-
Web緩存器進行檢查,看看本地是否存儲了該對象副本。如果有,Web緩存器就向客戶瀏覽器用HTTP響應報文返回該對象。
-
如果Web緩存器中沒有該對象,它就打開一個與該對象的初始服務器(如www.someschool.edu)的TCP連接。Web緩存器則在這個緩存器到服務器的TCP連接上發送一個對該對象的HTTP請求。在收到該請求后,初始服務器向該Web緩存器發送具有該對象的HTTP響應。
-
當Web緩存器接收到該對象時,它在本地存儲空間存儲一份副本,并向客戶的瀏覽器用HTTP響應報文發送該副本(通過現有的客戶瀏覽器和Web緩存器之間的TCP連接)。
?
web緩存器可以大大減少對客戶端請求的響應時間
-
-
-
FTP相關 一些較為常見的命令如下:
- USER username:用于向服務器傳送用戶標識。
- PASS password:用于向服務器發送用戶口令。
- LIST:用于請求服務器回送當前遠程目錄中的所有文件列表。該文件列表是經一個(新建且非持續連接)數據連接傳送的,而不是在控制TCP連接上傳送。
- RETR filename:用于從遠程主機當前目錄檢索(即get)文件。該命令引起遠程主機發起一個數據連接,并經該數據連接發送所請求的文件。
- STOR filename:用于在遠程主機的當前目錄上存放(即put)文件。
一些典型的回答連同它們可能的報文如下所示:
- 331 Username OK,Password required(用戶名OK,需要口令)。
- 125 Data connection already open;transfer starting(數據連接已經打開,開始傳送)。
- 425 Can’t open data connection(無法打開數據連接)。
- 452 Error writing file(寫文件差錯)。
-
DNS相關
-
DNS層次結構
+?各種DNS服務器交互
-
- 遞歸查詢
? 遞歸查詢是一種DNS 服務器的查詢模式,在該模式下DNS 服務器接收到客戶機請求,必須使用一個準確的查詢結果回復客戶機。如果DNS 服務器本地沒有存儲查詢DNS 信息,那么該服務器會詢問其他服務器,并將返回的查詢結果提交給客戶機。
? 客戶機和服務器之間的查詢是遞歸查詢
? 是遞歸查詢告訴客戶機IP
- 迭代查詢
? DNS 服務器另外一種查詢方式為迭代查詢,DNS 服務器會向客戶機提供其他能夠解析查詢請求的DNS 服務器地址,當客戶機發送查詢請求時,DNS 服務器并不直接回復查詢結果,而是告訴客戶機另一臺DNS 服務器地址,客戶機再向這臺DNS 服務器提交請求,依次循環直到返回查詢的結果為止。
? 服務器之間的查詢是迭代查詢
-
DNS緩存
DNS服務器在一段時間后(通常設置為兩天)將丟棄緩存的信息。
運輸層
-
多路復用和分解
? 將運輸層報文段中的數據交付到正確的套接字的工作稱為多路分解(demultiplexing),在源主機當中從不同的套接字中收集數據塊,并為每一個數據塊封裝上首部信息(用于分解)從而生成報文段,然后將此報文段傳遞到網絡層。所有的這些工作稱為多路復用(multiplexing)。
運輸層多路復用的要求:
套接字有唯一的標識符; 每一個報文段有特殊的字段來指示該報文段所要交付到的套接字。(這些特殊的字段是源端口字段和目的端口字段,端口號是一個16bit的數范圍是0-65535.其中0-1023是周知端口)。
TCP的首部開銷為20個字節,而UDP的首部開銷為8字節 無連接的多路復用與多路分解(UDP)
一個UDP套接字是由一個二元組來全面標志的,該二元組包含一個目的IP地址和一個目的端口號,因此如果兩個UDP報文段有不同的源IP地址和/或源端口號,但是具有相同的目的IP地址和目的端口號,那么這兩個報文段將通過相同的套接字被定向到相同的進程。
UDP報文格式:
? 長度字段:指示了在UDP報文段中的字節數(首部加數據,以字節為單位) ? 檢驗和:接收方使用檢驗和來檢查在該報文段中是否出現差錯
? UDP雖然實現了檢驗和,但是對恢復差錯無能為力,要么它丟棄受損的報文段,要么將受損的報文段交給應用程序并給出警告。
面向連接的多路復用和多路分解(TCP)
? TCP套接字和UDP套接字的細微的差別是,TCP套接字是由一個四元組(源IP地址,源端口號,目的IP地址,目的端口號)來標識的。這樣當一個TCP報文段從網絡到達另外一臺主機時,該主機使用全部的4個值來將報文段定向(分解)到相應的套接字。特別與UDP不同的是,兩個具有不同的IP地址的或者是源端口號的到達TCP報文段將被定向到兩個不同的套接字,除非TCP報文段攜帶了初始創建連接的請求 。服務器主機可以支持很多并行的TCP套接字,每一個套接字和一個進程相聯系,并由其四元組來標識每一個套接字。當一個TCP報文段到達主機時,所有的四個字段(源IP、源端口、目的IP、目的端口)被用來將報文段定向(分解)到相應的套接字。 ? TCP連接總是點對點的,所謂的“多播”,即在一次的發送操作當中從一個發送方將數據傳輸給多個接收方,對于TCP來說是不可能的。
4位首部長度:指示TCP頭部大小(以32bit為單位),指示何處數據開始,由于TCP選項的原因,TCP首部長度是可變的。(但是通常選項為空,TCP頭部典型長度為20字節,所以首部長度通常為5,即1001). 16位窗口大小:用來表示想要收到的每個TCP數據段的大小。TCP的流量控制由連接的每一端通過聲明窗口的大小來提供。窗口的大小為字節數,起始于確認序號字段指明的值,這個值是接收端正期望接收到的字節。窗口的大小是一個16字節字段,因而窗口大小最大為65535字節。 16位檢驗和:16位TCP頭部檢驗和。源主機基于數據內容計算一個數值,目的主機要和源主機計算的結果一致,從而驗證數據的有效性。檢驗和覆蓋的是整個的TCP報文段:這是一個強制性的字段,一定是由發送端計算和存儲,并由接收端進行驗證。
URG:緊急標志,為1時表示有效,緊急數據的最后一個字節由16bit的緊急數據指針字段指出。當緊急數據存在時,
ACK:確認標志。表明確認編號欄有效,大多數情況下該標識位是置位的。TCP報頭內的確認編號欄內包含的確認編號(W+1)為下一個預期接收到的序列編號,同時提示遠端系統已經成功的接收到了所有數據。
PSH:推標志。該標志置位時,接收端不將該數據進行隊列處理,而是盡可能快地將數據轉由應用處理(接收方立即將數據交給上層)。在處理Telnet或rlogin等交互模式的連接時,該標志總是置位的。
RST:復位標志。用于復位(重置)相應的TCP連接。
SYN:同步標志。表明同步序列編號欄有效。該標志僅在三次握手建立TCP連接時有效。它提示TCP連接的服務端檢查序列編號,該序列編號為TCP連接初始端(一般是客戶端)的初始序列編號。
FIN:結束標志。
TCP三次握手建立連接
三次握手(Three-Way Handshake)即建立TCP連接時,需要客戶端和服務端總共發送3個包確認連接的建立。在socket編程中,這一過程由客戶端執行connect()來觸發。流程如下:
TCP三次握手
第一次握手:Client將標志位SYN置為1,隨機產生一個值seq=J,并將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。
第二次握手:Server收到數據包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,并將該數據包發送給Client以確認連接請求,Server進入SYN_RCVD狀態。 第三次握手:Client收到確認后,檢查ack是否為J+1,ACK是否為1,如果正確則將標志位ACK置為1,ack=K+1,并將該數據包發送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨后Client與Server之間可以開始傳輸數據了。(前兩次握手是是不承載"有效載荷"的,而第三次握手是可以承載"有效載荷"的。)
其中有一個半連接狀態:服務器維護一個半連接隊列,該隊列為每個客戶端SYN包開設一個條目,標明服務器已經接到SYN包,并向客戶端發出確認,這些條目表示的連接處于SYN_RECV狀態,得到客戶端的確認后進入ESTABLISHED狀態。
TCP四次揮手斷開連接
四次揮手(Four-Way Wavehand)是指斷開一個TCP連接時需要客戶端和服務器總共發送四個包以確認連接的斷開。在socket()編程中,這一個過程由客戶端或者服務器端的任意一方執行close來觸發。整個流程圖如下:
第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
第二次揮手:Server收到FIN后,發送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進入CLOSE_WAIT狀態。
第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
第四次揮手:Client收到FIN后,Client進入TIME_WAIT狀態,接著發送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態,完成四次揮手。
鏈接:http://www.jianshu.com/p/37d132327724
-
TCP擁塞控制機制
? 擁塞控制(congestion control)是TCP協議的一項重要功能,TCP的擁塞控制機制是從端到端的角度,推測網絡是否發生擁塞,如果推斷網絡發生擁塞,則立即將數據發送速率降下來,以便緩解網絡擁塞。 ? TCP的擁塞控制采用的是窗口機制,通過調節窗口的大小實現對數據發送速率的調整。TCP的發送端維持一個稱為擁塞窗口cwnd的變量,單位為字節,用于表示在未收到接收端確認的情況下,可以連續發送的數據字節數。cwnd的大小取決于網絡的擁塞程度,并且動態地發生變化。擁塞窗口調整的原則是:只要網絡沒有出現擁塞,就可以增大擁塞窗口,以便將更多的數據發送出去,相當于提高發送速率;一旦網絡出現擁塞,擁塞窗口就減小一些,減少注入網絡的數據量,從而緩解網絡的擁塞。 ? 發送端判斷網絡發生擁塞的依據是:發送端設置一個重傳計時器RTO,對于某個已發出的數據報文段,如果在RTO計時到期后,還沒有收到來自接收端的確認,則認為此時網絡發生了擁塞。 TCP的擁塞控制算法包括了慢啟動(slow start)、擁塞避免(congestion avoidance)、快速重傳(fast retransmit)和快速恢復(fast recovery)四部分。 ? 慢啟動算法作用在TCP數據傳輸的開始階段,當主機開始發送數據時,因為不知道網絡中的負荷情況,如果立即發送大量的數據,有可能會引起網絡的擁塞。因此,TCP采用試探的方法,逐漸增大擁塞窗口。通常在剛開始發送數據報文段時,先將擁塞窗口cwnd設置為一個TCP最大段長度MSS的值。而在每收到一個數據報文段的確認后,cwnd就增加一個MSS的數值。這樣就可以逐漸增大發送端的擁塞窗口,使數據注入網絡的速率比較合理。如果定義從發送端發出一個數據報文段到收到這個數據報文段的確認的時間間隔為往返時間RTT,則在慢啟動階段,每經過一個RTT,cwnd的值就加倍。 ? 為了防止擁塞窗口增長過快而引起網絡擁塞,TCP還需要設置一個慢啟動閾值ssthresh,當擁塞窗口的值增加到ssthresh時,就要減緩擁塞窗口的增長速度,具體的做法是每經過一個RTT,擁塞窗口cwnd的值加1(單位為MSS),這樣就可以使cwnd按線性規律緩慢增長,這個過程稱之為“加性增加”(Additive Increase)算法。通常情況下,擁塞窗口cwnd的初值被設置為1,慢啟動閾值ssthresh的初值被設置為16。當擁塞避免算法執行到某個時刻,發送端在規定時間內沒有收到接收端的確認,即發生了網絡超時,則意味著網絡發生了擁塞。此時,發送端首先將ssthresh的值變為發生超時時cwnd值的一半,同時將cwnd的值置為1,重新執行慢啟動算法。這樣做的好處是,當網絡頻繁出現擁塞時,ssthresh下降得很快,可以大大減少注入網絡中的數據報文段。通常稱這個過程為“乘性減小”(MultiplicativeDecrease)算法。TCP中的“加性增加”和“乘性減小”算法合起來稱為AIMD算法。 ? 慢啟動和擁塞避免是1988年提出的擁塞控制算法,1990年在此基礎上又增加了快速重傳和快速恢復兩個算法。 快速重傳算法的基本思想是:接收端每收到一個失序的數據報文段后就立即發出重復確認,以便更早地通知發送端有丟包的情況發生。假設在某個TCP數據傳輸過程中,接收端依次收到發送端發出的1號和2號數據報文段,并對這兩個數據報文段發送確認后,沒有按次序收到3號數據報文段,而是收到了4號,這時就需要立即向發送端發送一個2號數據報文段的確認,稱為重復確認。同理,如果繼續收到5號、6號數據報文段,接收端仍然要向發送端發出2號數據報文段的重復確認。此時,發送端會收到多個2號數據報文段的重復確認,則認為3號數據報文段發生了丟包,需要立即向接收端重傳3號數據報文段,而不需要等待重傳計時器到期再重傳??焖僦貍魉惴ㄖ幸幎ㄈ绻盏侥硵祿笪亩蔚娜齻€重復確認,則立即重傳下一個數據報文段。 ? 快速恢復是配合快速重傳使用的算法,其基本思想是:當發送端連續收到三個重復確認時,就將慢啟動閾值ssthresh減半,以預防網絡擁塞的發生,并且將擁塞窗口cwnd的值置為減半后的ssthresh,然后開始執行擁塞避免算法,使得cwnd緩慢地加性增大。
TCP擁塞控制算法描述如下:
SlowStartPhase( ) //慢啟動算法 {CongWin=1; //擁塞窗口cwnd的初值為1個MSSwhile (CongWin<Threshold&& 無數據丟失) //當擁塞窗口小于慢啟動閾值且沒有發生丟包時{for each ACK CongWin++; //每收到一個確認數據報,擁塞窗口加1}if (CongWin>=Threshold) thenCongestionAvoidancePhase( );//當擁塞窗口大于等于慢啟動閾值時,啟動擁塞避免算法;if (數據丟失) thenDataLoss( ); // 丟包后的處理方法 } CongestionAvoidancePhase( ) // 擁塞避免算法 {while (無數據丟失){for each RTT CongWin=CongWin+1; //每經過一個RTT,擁塞窗口加1}DataLoss( ); } DataLoss( ) //丟包后的處理方法 {if (超時) then{ Threshold=CongWin/2;CongWin=1;SlowStartPhase( );//如果發生超時,慢啟動閾值置為當前擁塞窗口的一半,然后將擁塞窗口置1,開始執行擁塞避免算法。}if (3次重復確認) then{ Threshold=CongWin/2;CongWin=CongWin/2;CongestionAvoidancePhase(); //如果收到3個重復的確認,則執行快速重傳和快速恢復算法,慢啟動閾值減小為擁塞窗口的一半,同時將擁塞窗口減半,開始擁塞避免算法 復制代碼鏈接:http://www.jianshu.com/p/7d59f9292b03
7.網絡安全方面
示例:
sql_login = "SELECT COUNT(*) FROM login WHERE userName= %s AND password=%s" %(userName, password)
此時若 username = 'admin--' 則不論password為什么都能登錄
解決方案:sql_login = "SELECT COUNT(*) FROM login WHERE userName= %s AND password=%s"
? values = (username, password)
? cur.execute(sql_login, values)
學習簡單SQL注入:
-
AND
and 1=1 and 1=2
-
猜表
and 0 < (select count(*) from admin) ---判斷是否存在admin這張表
-
此類類似,通過使用 and來達到自己的查詢目的
-
-
; ;結束之前的SQL語句
-
-- 忽略后面的語句
-
OR 使前面的判斷失效 解決方案: 綁定變量使用預編譯語句是預防SQL注入的最佳方式,使用預編譯的SQL語句語義不會發生改變,在SQL語句中,變量用問號?表示,黑客即使本事再大,也無法改變SQL語句的結構,像上面例子中,username變量傳遞的plhwin' AND 1=1-- hack參數,也只會當作username字符串來解釋查詢,從根本上杜絕了SQL注入攻擊的發生。
DDOS的表現形式主要有兩種,一種為流量攻擊,主要是針對網絡帶寬的攻擊,即大量攻擊包導致網絡帶寬被阻塞,合法網絡包被虛假的攻擊包淹沒而無法到達主機;另一種為資源耗盡攻擊,主要是針對服務器主機的攻擊,即通過大量攻擊包導致主機的內存被耗盡或CPU被內核及應用程序占完而造成無法提供網絡服務。
在網站上輸入 localhost/test之后會顯示一個attacked的彈窗
參考網站:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
防御:服務端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加偽隨機數。
- Cookie Hashing(所有表單都包含同一個偽隨機值):
??這可能是最簡單的解決方案了,因為攻擊者不能獲得第三方的Cookie(理論上),所以表單中的數據也就構造失敗了:>
??這個方法個人覺得已經可以杜絕99%的CSRF攻擊了,那還有1%呢....由于用戶的Cookie很容易由于網站的XSS漏洞而被盜取,這就另外的1%。一般的攻擊者看到有需要算Hash值,基本都會放棄了,某些除外,所以如果需要100%的杜絕,這個不是最好的方法。
- 驗證碼
??這個方案的思路是:每次的用戶提交都需要用戶在表單中填寫一個圖片上的隨機字符串,厄....這個方案可以完全解決CSRF,但個人覺得在易用性方面似乎不是太好,還有聽聞是驗證碼圖片的使用涉及了一個被稱為MHTML的Bug,可能在某些版本的微軟IE中受影響。
+?One-Time Tokens(不同的表單包含一個不同的偽隨機值)
??在實現One-Time Tokens時,需要注意一點:就是“并行會話的兼容”。如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護措施不應該影響到他對任何表單的提交??紤]一下如果每次表單被裝入時站點生成一個偽隨機值來覆蓋以前的偽隨機值將會發生什么情況:用戶只能成功地提交他最后打開的表單,因為所有其他的表單都含有非法的偽隨機值。必須小心操作以確保CSRF保護措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。
8. SQL反模式
-
亂穿馬路
目標:存儲多值屬性
反模式:格式化的逗號分隔列表
壞處:
- 索引顯然是不能用了
- 增加了查詢的難度,這里的難度是說sql語句更難寫了,只有及其少數的操作優化了,是哪個操作就顯而易見了。
- 列表的長度有限制,比如varchar的字段長度是有限的。
?
解決方案:創建一張交叉表
示例:
一個產品可能有多個聯系人。 可以這樣設計:
CREATE TABLE Contacts (product_id BIGINT UNSIGNED NOT NULL,account_id BIGINT UNSIGNED NOT NULL ,PRIMARY KEY (product_id,account_id),FOREIGN KEY (product_id) REFERENCES Products(product_id),FOREIGN KEY (account_id) REFERENCES Accounts(account_id) ); 復制代碼好處:
- 可以添加索引
- 可以添加額外的信息,比如一些操作時間等
- 主要聯系人和次要聯系人等都可以實現
-
單純的樹
? 在樹形結構中,實例被稱為節點。每個節點都有多個子節點與一個父節點。
? 最上層的節點叫做**根(root)節點,**它沒有父節點。
? 最底層的沒有子節點的節點叫做葉(leaf)。
? 中間的節點簡單地稱為非葉節點(nonleaf)。
**目標:**分層存儲與查詢,比如:系統字典、組織機構、省份區域等樹形結構數據或者以層級方式組織的數據。
**反模式:**總是依賴父節點(使用鄰接表)。
? 最簡單的實現方式是添加ParentId字段,引用同一張表的主鍵ID。
? 鄰接表維護樹比較方便,但是查詢很笨拙,如果要找一個節點下的所有子節點,要關聯很多次,這個關聯次數取決于樹的深度,
? 所以,鄰接表不能用于存儲比較深的樹。
**如何識別反模式:**當出現以下情況時,可能是反模式
? (1)我們的數結構要支持多少層
? (2)我們總是很害怕接觸那些管理樹結構的代碼
?? (3)我需要一個腳本來定期的清理樹中的孤立節點數據
**解決方案:**使用其他樹模型
- 路徑枚舉:
????用一個path字段保存當前節點的最頂層的祖先到自己的序列(路徑)
????優點:查詢方便;
????缺點:1、不能保證存儲的值的有效性。
? 2、增、刪時,要考慮對原位置下的子節點如何處理,比較麻煩。
? 3、如果還要維護一個排序path,那就更麻煩了。
- 嵌套集:
????存儲子孫節點的相關信息,而不是節點的直接祖先。用nsleft存儲所有后臺的nsleft中最小的數-1,
? 用nsright存儲所有后臺的nsright中最大的數+1。
CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, nsleft INTEGER NOT NULL, nsright INTEGER NOT NULL, bug_id BIGINT UNSIGNED NOT NULL, author BIGINT UNSIGNED NOT NULL, comment_date DATETIME NOT NULL, comment TEXT NOT NULL, FOREIGN KEY (bug_id) REFERENCES Bugs (bug_id), FOREIGN KEY (author) REFERENCES Accounts(account_id) ); 復制代碼????優點:刪除時,原來子節點的關系自動上移。
????缺點:1、查詢一個節點的直接上級或下級,很困難。
? 2、增、刪,困難。
- 閉包:記錄了樹中所有節點間的關系,而不僅僅是只有那些直接的父子關系。
? 將樹中任何具有**“祖先-后代”關系的節點對**都存儲在TreePath表中的一行,同時增加一行指向節點自己。
CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, bug_id BIGINT UNSIGNED NOT NULL, author BIGINT UNSIGNED NOT NULL, comment_date DATETIME NOT NULL, comment TEXT NOT NULL, FOREIGN KEY (bug_id) REFERENCES Bugs(bug_id), FOREIGN KEY (author) REFERENCES Accounts(account_id) ); CREATE TABLE TreePaths ( ancestor BIGINT UNSIGNED NOT NULL, descendant BIGINT UNSIGNED NOT NULL, PRIMARY KEY(ancestor, descendant), FOREIGN KEY (ancestor) REFERENCES Comments(comment_id), FOREIGN KEY (descendant) REFERENCES Comments(comment_id) ); 復制代碼?
? 優點:1、能快速的查詢給定節點的祖先與后代;
? 2、能更加簡單的維護分層信息;
? 3、如果刪除了TreePath表中的一條記錄,那么并不是真正的刪除具體信息表中的記錄。這樣設計有時候很有用:
比如在產品目錄的分類或者員工組織架構的圖標中,當你改變了節點關系的時候,并不是真的想要刪除一個節點。
? 我們把關系路徑存儲在一個分開獨立的表中,使得設計更加靈活。
? 缺點:查詢直接父節點或子節點,需要在表中增加Path_Length字段來維護。
結論:
? 每種設計各有優劣,如何選擇設計依賴于應用程序中的哪種操作最需要性能上的優化。
? 鄰接表:簡單,但不適用于很深的表;
?? 枚舉路徑:無法保證引用完整性;
?? 嵌套集:無法保證引用完整性,太復雜;
?? 閉包:需要一個額外的表存儲關系;
-
需要ID
目標:建立主鍵規范
反模式:以不變應萬變,即每個數據庫中的表都需要一個偽主鍵Id
? 在表中,需要引入一個對于表的域模型無意義的新列來存儲一個偽值,這一列被用作這張表的主鍵,從而通過它來確定表中的一條記錄,即便其他的列允許出現適當的重復項。這種類型的主鍵列我們通常稱其為“偽主鍵”或者“代理鍵”。
- 冗余鍵值:如果存在一個邏輯上更為自然的主鍵并且也滿足unique約束,那么id就多余了;
- 允許重復項:偽主鍵本身確保了表的數據不會存在重復項,所以也就無法避免表中的其它數據出現重復項;
- 意義不明的關鍵字:主鍵名應該便于理解,所以建議用XxxId,而不都是用Id;
- 使用組合鍵。
- 我覺得這張表不需要主鍵;
- 我怎么能在多對多的表中存儲重復的項;
- 我學過《數據庫設計理論》,里面說我應該把數據移動到一張查詢表中,然后通過ID查找。但是我不想這么做,因為每次我想要獲得真是的數據,都不得不做一次連接查詢。(這在數據庫設計中是一個常見的誤區,稱為“正規化”,然而實際中對于偽主鍵并沒有什么需要做的)
-
直接了當的描述設計,主鍵名應該便于理解,所以建議用XxxId,而不都是用Id;
-
擁抱自然鍵和組合鍵。
?
-
不用鑰匙的入口(外鍵約束)
**目標:**簡化數據庫架構
**反模式:**無視約束,即不使用約束
**如何識別反模式:**當出現以下情況時,可能是反模式
? 1、我要怎么寫這個查詢來檢查一個值是否沒有被同時存在2張表中?
? (通常這樣的需求是為了查找那些孤立的行數據)
? 2、有沒有一種簡單的方法來判斷在一張表中的數據是否也在第二張表中存在?
? (這么做是用來確認父記錄切實存在。外鍵會自動完成這些,并且外鍵會使用這父表的索引盡可能的高效完成)
? 3、有人說不要用外鍵,外鍵影響數據庫效率。
**解決方案:**聲明約束
? 1、通過使用外鍵來確保應用完整性;
? 使用約束時:
? (1)數據庫本身會拒絕所有不合理的改變,無論這個改變是通過什么方式造成的。
? (2)能夠避免編寫不必要的代碼,同時還能確保一旦修改了數據庫中的內容,所有的代碼依舊能夠用同樣的方式執行。
? (3)外鍵的特性:級聯更新,比如:On Update Cascade、On Delete Restrict等。 在執行更新和刪除2個操作中的任意1個是,數據庫都會自動修改多張表中的數據, 外鍵的引用狀態在操作之前和之后都保持完好。
? 2、外鍵約束的確需要多那么一點額外的系統開銷,但相比于其他的一些選擇,外鍵確實更高效一點:
? (1)不需要在更新或刪除記錄前執行Select檢查;
? (2)在同步修改時不需要再鎖住整張表;
? (3)不再需要執行定期監控腳本來修正不可避免的孤立數據。
?
-
實體-屬性-值
**目標:**支持可變屬性
**反模式:**使用泛型屬性表。這種設計成為實體-屬性-值(EAV),也可叫做開放架構、名-值對。
? 優點:通過增加一張額外的表,可以有以下好處
? (1)表中的列很少;
? (2)新增屬性時,不需要新增列。不會影響現有表的結構;
? (3)存儲的字段內容不會為空值。
? 缺點:(1)查詢語句變得更加復雜;
? (2)使用EAV設計后,需要放棄傳統的數據庫設計所帶來的方便之處,比如:無法保障數據完整性;
? (3)無法使用SQL的數據類型,比如對日期、金錢等格式內容都只能保持為字符串類型;
? (4)無法確保引用完整性;
? (5)無法配置屬性名。比如,有可能表中存在兩條記錄,
? 一條的attr_name是sex,一條attr_name是gender,都是表示性別;
? (6)查詢結果中有多個屬性時,查詢非常困難,且查詢性能無法控制。
?
**如何識別反模式:**當出現以下情況時,可能是反模式
??(1)數據庫不需要修改元數據庫(表中的列屬性)就可以擴展。還可以在運行時定義新的屬性。
??(2)查詢是連接數量非常多,且連接的數量可能會達到數據庫的限制時,你的數據庫的設計可能是有問題的。
??(3)普通的報表查詢變的及其復雜甚至不且實際。
**解決方案:**模型化子類型
??1、單表繼承:所有屬性都在一個單表上保存,增加屬性時就擴充這個表。
? 缺點:
? (1)當程序需要加入新對象時,必須修改數據庫來適應這些新對象。又由于這些新對象具有一些和老對象 不用的屬性, 因而必須在原有表里增加新的屬性列,可能會遇到一個實際的問題,就是每張表的列的數量是有限制的。
? (2)沒有任何的元信息來記錄哪個屬性屬于哪個子類型。
? 當數據的子類型很少,以及子類型特殊屬性很少,就可以使用單表繼承。
??2、實體表繼承:為每個子類型創建一張獨立的表,每個表包含哪些屬于基類的共有屬性,同時也包含了子類型特殊化的屬性。
**如何識別反模式:**當出現以下情況時,可能是反模式
解決方案:
? 優點:
? (1)實體繼承類設計相比于但表繼承設計的優勢在于提供了一種方法, 讓你能組織在一行內存儲一些和當前子類型無關的屬性。如果你引用一個并不存在于這張表中的屬性列,數據庫會自動提示你錯誤。
? (2)不用像在單表繼承設計里那樣使用額外的屬性來標記子類型。
? 缺點:很難將通用屬性和子類特有屬性區分開來。因此,如果將一個新的屬性增加到通用屬性中,必須為每個子類表都添加一遍。
? 當你很少需要一次性查詢多有子類型時,實體繼承表設計是最好的選擇。
??3、類表繼承:把表當成面向對象里的類。
? 創建一張基類表,包含所有子類型的公共屬性。對于每個子類型,創建一個獨立的表,通過外鍵和基類表相連。
??4、半結構化數據模型:如果有很多子類型或者必須經常增加新的屬性支持,那么可以用一個BLOB列來存儲數據,用XML或者JSON格式——同事包含了屬性的名字和值。這叫做序列化大對象塊。
?? 這個設計的優勢是擴展性,缺點是,這樣的結構中sql無法獲取某個指定的屬性。你必須或者整個blob字段并通過程序去解釋這些屬性。
?? 當你需要絕對的靈活性時,可以使用這個方案。
? 如果使用了EAV,那么可以先將全部屬性取出,然后再做其他處理。
-
多態關聯
?
-
多列屬性
?
-
元數據分裂
?
9. 數據庫設計的三范式
- 1NF:無重復的列,即每一列都是不可分割的基本數據項
商品表 goods:
| 1 | 10 | red |
| 2 | 20 | blue |
| 3 | 30 | red, blue |
可以拆分為兩個表,價格表和顏色表: 價格表 goods_price:
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
顏色表 goods_color
| 1 | red |
| 2 | blue |
| 3 | red |
| 3 | blue |
-
2NF:屬性完全依賴于主鍵 如下表所示:學分依賴于課程,不依賴于主鍵學號 考試成績表 exam:
學號姓名課程學分成績 1 Tom 數學 4 80 2 Kate 數學 4 90
可以拆分為三個表,學生信息表,課程表和考試成績表:
學生信息表 student:
| 1 | Tom |
| 2 | Kate |
課程表 course:
| 101 | 數學 | 4 |
| 102 | 語文 | 2 |
考試成績表 exam:
| 1 | 101 | 80 |
| 2 | 101 | 90 |
-
3NF:屬性不依賴于其他非主屬性,即不能有冗余
如下表所示:班主任手機依賴于班主任姓名 這個非主屬性
學生信息表 student:
| 1 | Tom | Lily | 138 |
| 2 | Kate | Lily | 138 |
可以拆分為兩個表,學生信息表,班主任信息表:
學生信息表 student:
| 1 | Tom | Lily |
| 2 | Kate | Lily |
班主任信息表 teacher:
| Lily | 138 |
| Cat | 139 |
鏈接:http://www.jianshu.com/p/841573f02f8e
轉載于:https://juejin.im/post/5af30fc9f265da0b8262cab6
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: 笔记:后端 - Redis
- 下一篇: 关于libtorrent库的安装