Mysql
mysql事務
共享鎖與排他鎖
共享鎖:允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。(讀都允許讀,但我在讀不允許你去改)
排他鎖:允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。(我在修改數據,別的操作都被禁止)
事務特性
事務四個特性:ACID
- 原子性(Atomicity):指事務是一個不可分割的最小工作單位,事務中的操作只有都發生和都不發生兩種情況
- 一致性(Consistency):數據庫總是從一個一致性的狀態轉換到另外一個一致性的狀態。
- 隔離性(Isolation):一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的數據對并發的其他事務是隔離的,并發執行的各個事務之間不能互相干擾。
- 持久性(Durability):一個事務一旦提交成功,它對數據庫中數據的改變將是永久性的,接下來的其他操作或故障不應對其有任何影響。
如何實現這些特性
- 原子性:靠Undo log實現,即如果一個事務異常或執行失敗后進行回滾
- 當事務對數據庫進行修改時,InnoDB會生成對應的 undo log;
- 如果事務執行失敗或調用了 rollback,導致事務需要回滾,便可以利用 undo log 中的信息將數據回滾到修改之前的樣子。
- undo log 屬于邏輯日志,它記錄的是sql執行相關的信息。
- 當發生回滾時,InnoDB 會根據 undo log 的內容做與之前相反的工作
- 一致性:事務的最終目的,即需要數據庫層面保證,又需要應用層面進行保證,并且MySQL底層通過兩階段提交事務保證了事務持久化時的一致性。
- 隔離性:靠鎖和MVCC實現
- 鎖:
- 在 InnoDB 事務中,行鎖通過給索引上的索引項加鎖來實現。
- 只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則將使用表鎖。
- 行級鎖定同樣分為兩種類型:共享鎖和排他鎖
- 使用Record Lock和Gap Lock(解決幻讀)
- MVCC:多版本并發控制
- DB_TRX_ID:事務 ID,是根據事務產生時間順序自動遞增的
- DB_ROLL_PTR:回滾指針,本質上就是一個指向記錄對應的undo log的一個指針,InnoDB 通過這個指針找到之前版本的數據
- MVCC在事務開啟時會為事務生成一個ID,并且在查詢時生成一個快照,能看到當前活躍的事務,然后通過比較快照的生成時間和活躍事務的提交時間進行對比,判斷讀取哪個版本的數據。
- 鎖:
- 持久性:靠Redo log實現
- mysq|修改數據的時候會在redo log中記錄一份日志數據,就算數據沒有保存成功,只要日志保存成功了,數據仍然不會丟失
- 當一條數據需要更新時,InnoDB會先將數據更新,然后記錄redoLog 在內存中,然后找個時間將redoLog的操作執行到磁盤上的文件上。
mysql隔離級別
mysql具有四種隔離級別
隔離級別 | 說明 |
---|---|
讀未提交 | 一個事務還沒提交時,它做的變更就能被別的事務看到 |
讀已提交 | 一個事務提交之后,它做的變更才會被其他事務看到 |
一個事務提交之后,它做的變更才會被其他事務看到 | 一個事務中,對同一份數據的讀取結果總是相同的,無論是否有其他事務對這份數據進行操作,以及這個事務是否提交。InnoDB默認級別 |
串行化 | 事務串行化執行,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞,隔離級別最高,犧牲系統并發性。 |
不同的隔離級別是為了解決不同的問題。也就是臟讀、幻讀、不可重復讀。
問題 | 說明 |
---|---|
臟讀 | 讀到了其他事務未提交的數據 |
不可重復讀 | 在一個事務內,最開始讀到的數據和事務結束前的任意時刻讀到的同一批數據出現不一致的情況 |
幻讀 | 在一個事務中,后續讀取的數據,在最開始讀取的數據中不存在 |
隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
讀未提交 | 可以出現 | 可以出現 | 可以出現 |
讀已提交 | 不允許出現 | 可以出現 | 可以出現 |
一個事務提交之后,它做的變更才會被其他事務看到 | 不允許出現 | 不允許出現 | 可以出現 |
串行化 | 不允許出現 | 不允許出現 | 不允許出現 |
Mysql和MangoDB的比較
Mysql:
- 關系數據庫系統,相關信息可能存儲在單獨的表中,但通過使用關聯查詢來關聯。通過使用這種方式,使得數據重復量被最小化。
- 關系型數據庫的最大特點就是事務的一致性
- 為了維護一執行需要消耗大量的性能
MangoDB:
- 少量數據時,數據存在內存中。當內存不夠時,只將熱點數據放在內存,其他存入磁盤
- 數據存儲在類似JSON的文檔中,并且文檔中每個json串結構可能有所不同
- 使用動態模式,這意味著您可以在不首先定義結構的情況下創建記錄,例如字段或其值的類型
- 支持多種存儲格式(mysql只支持基本類型)
- 設計了高可用性和可擴展性,并提供了即用型復制和自動分片功能。
- 簡化了開發,因為 MongoDB 文檔自然映射到現代的面向對象編程語言。使用 MongoDB 可以避免將代碼中的對象轉換為關系表的復雜對象關系映射(ORM)層。
sql優化
select *
浪費資源,減少使用,且不走索引union all
比union
更快(但是不去重)- 小表驅動大表:大表
in
小表 ; 小表exists
大表; - 批量插入數據盡量使用
insertBatch
,而不是循環(循環會多次請求數據庫) - 多使用
limit
,減少內存消耗 - 海量數據查詢分頁,使用條件查詢結合
limt size
,去替代limit start size
- 使用連接查詢代替子查詢(子查詢會為子查詢額外創建一個表)
join
的表不能太多,否則容易選錯索引- 索引不宜太多,因為在增刪改查的時候都需要更新索引表(使用聯合索引)
- 將
group by
后接的having
條件適當提到前面的where
中
Spring
maven中版本 版本沖突
maven依賴中不允許存在兩個不同版本的同名依賴。(添加<exclusion>
標簽來解決沖突)
Kafka
Kafka和其他消息隊列對比
對比 | Kafka | RocketMQ | RabbitMQ |
---|---|---|---|
優先級隊列 | 不支持 | 通過建立不同的隊列 | 通過建立不同的隊列 |
延遲隊列 | 不支持 | 基于隊列的延遲 | 基于隊列的延遲 |
死信隊列 | 不支持 | 支持 | 支持 |
消費模式 | pull | pull/push | pull/push |
廣播模式 | 發布訂閱 | 發布訂閱 | 點對點 (但可以由交換機實現發布訂閱模式) |
消息回溯 | offset和timestamp | 按時間回溯 | 不支持 |
消息堆積&持久化 | 磁盤堆積:所有消息都存在磁盤 每個partition對應一個或多個segment file | 基于磁盤存儲 使用commit Log存儲消息(順序寫到文章末尾) 后臺異步線程同步到consumerQueue 使用內存映射文件加速消息讀取 | 內存堆積(換頁操作存儲到磁盤) (或使用惰性隊列將消息持久化到磁盤) |
流量控制 | 支持client和user級別 | 多種維度的流量控制 | 流量控制基于credit-base算法,是內部被動觸發的保護機制,作用于生產者層面 |
順序性消息 | 同分區內有序 | Broker消息隊列鎖(分布式鎖) Consumer消息隊列鎖(本地鎖) Consumer消息處理隊列消費鎖(本地鎖) | 無法保證全局有序 |
性能 | 最快 | 中等 | 最慢 |
高可用和容錯 | 包含Leaer和Follower Leader失效后隨機選舉Leader | Master和Slave | cluster(集群),federation(聯盟),shovel |
定時消息 | 不支持 | 支持 | 支持 |
負載均衡 (三者都是軟件負載均衡) | consumer端實現 每個消費者組都有指定一個broker為coordinator(群組協調器) | consumer端實現 所有的consumer都能得到consumer的訂閱表,每個consumer自己做負載均衡 | 設置Prefetch count來限制Queue每次發送給每個消費者的消息數 |
刷盤策略 | 異步刷盤 每3s鐘調用1次fsync 支持同步刷盤 | CommitRealTimeService 異步刷盤 && 開啟內存字節緩沖區 第一 FLushRealTimeService 異步刷盤 && 關閉內存字節緩沖區 第二 GroupCommitService 同步刷盤 第三 | 優先內存存儲,Buff不夠再刷盤 |
消息中間件 | Kafka | RocketMQ | RabbitMQ |
---|---|---|---|
特點 | 高吞吐量 持久性 分布式 發布訂閱 | 高可用性 順序消息 分布式事務 高擴展性 | 靈活路由 點對點+發布訂閱+請求響應 可靠性 插件擴展 |
適用場景 | 流式處理(日志收集 實時分析) 大數據集成 可靠性(持久化)要求高 | 異步消息處理 順序消息 分布式事務 | 復雜路由 靈活消息模式 異步任務處理 |
Redis
緩存穿透、擊穿、雪崩
緩存穿透
指訪問一個緩存和數據庫中都不存在的key,由于這個key在緩存中不存在,則會到數據庫中查詢,數據庫中也不存在該key,無法將數據添加到緩存中,所以每次都會訪問數據庫導致數據庫壓力增大。
解決辦法
將訪問過的key設置為空key,加入到緩存中
緩存擊穿
指大量請求訪問緩存中的一個key時,該key過期了,導致這些請求都去直接訪問數據庫,短時間大量的請求可能會將數據庫擊垮。
解決辦法
添加互斥鎖或分布式鎖,讓一個線程去訪問數據庫,將數據添加到緩存中后,其他線程直接從緩存中獲取。
熱點數據key不過期,定時更新緩存
緩存雪崩
指在系統運行過程中,緩存服務宕機或大量的key值同時過期,導致所有請求都直接訪問數據庫導致數據庫壓力增大
解決辦法
將key的過期時間打散,避免大量key同時過期。
對緩存服務做高可用處理。
加互斥鎖,同一key值只允許一個線程去訪問數據庫,其余線程等待寫入后直接從緩存中獲取。
緩存不一致
數據庫中的數據和Redis緩存中的數據不一致的問題
出現原因:
緩存和數據庫中都需要更新數據,對二者的操作無法保證原子性的情況下,就會出現不一致問題
解決辦法:
- 重試機制:使用消息隊列暫存要操作的數據,操作失敗再從消息隊列取回
- 延遲雙刪:先刪除緩存數據 ->再執行update更新數據表 ->最后(延遲N秒)再刪除緩存
Redis的優勢
數據存在內存中,直接與內存相連,讀寫速度很快。
使用單線程模型,無多線程 競爭 鎖 等問題
支持數據持久化
支持數據備份 master-slave模式數據備份(需要多個redis實例)
操作均為原子性的
Redis持久化
- AOF:采用日志的形式來記錄每個寫操作,追加到AOF文件的末尾(默認情況是不開啟AOF)重啟時再重新執行AOF文件中的命令來恢復數據(AOF是執行完命令后才記錄日志的)
- RDB:把內存數據以快照的形式保存到磁盤上。RDB持久化,是指在指定的時間間隔內,執行指定次數的寫操作
Redis面對大量訪問時的處理辦法
Redis是單線程服務,所有指令都是順序執行,當某一指令耗時很長時,就會阻塞后續的指令執行。當被積壓的指令越來越多時,Redis服務占用CPU將不斷升高,最終導致Redis實例崩潰甚至服務器宕機。
處理辦法:
- 使用Redis連接池
- 批量操作,使用Redis管道機制
- 使用合適的數據結構和命令
- 使用Reids集群
Redis面對大量數據存儲
- 數據分片,將數據存儲到多個Redis節點上
- 使用合適的數據結構
- 合理設置過期時間
- 使用持久化機制
Redis鍵的設計
- 遵循基本格式:[業務名稱]:[數據名]:[id]
長度不超過44字節 - 拒絕BigKey
- 恰當的數據格式
對象格式的數據可以采用json存儲,但是更好的是采用hash格式存儲 - 將集合類型中數據量大的進行拆分
Redis中各類型的底層結構
String:簡單動態字符串
List:雙向鏈表或壓縮鏈表(ziplist)
- 雙向鏈表:列表長度較長或包含較多元素
- 壓縮鏈表:在一定程度上減少內存使用,存儲在連續的內存區域中
Set:哈希表(Hash Table)和跳躍表(Skip List)
- 哈希表:集合元素較多或元素大。將集合的元素作為哈希表的鍵,值被設為固定的空值
- 跳躍表:有序的數據結構,支持快速查找、插入和刪除(因此也被用于ZSet)
ZSet:使用跳躍表存儲元素,使用哈希表存儲 元素:分值
Hash:哈希表和壓縮鏈表
- 哈希表:hash類型的字段數量較多,或字段大小較大時
- 壓縮鏈表:字段的順序是按照插入的先后順序進行存儲的
Elasticsearch
es的數據格式怎么規定的
通過mapping進行定義,可以查看我的相關文檔 ElasticSearch 其中的mapping映射屬性
為什么使用es
- 分布式實時文件存儲,可將每一個字段存入索引,使其可以被檢索到
- 實時分析的分布式搜索引擎
- 索引分拆成多個分片,每個分片可以有多個副本存儲在不同的節點上,負載均衡等
- 可以擴展到上百臺服務器
- 支持插件機制,分詞插件、同步插件、Hadoop插件、可視化插件等
Docker
Docker鏡像
Docker參考文章
Docker 容器的運行是基于宿主機的內核,通過linux的namespaces來實現隔離,相對于虛擬機而言降低了硬件資源的性能損耗,且具備一定程度上的應用隔離效果。
鏡像是一種輕量級,可執行的獨立軟件包,用來打包軟件運行環境和基于運行環境開發的軟件,它包含運行某個軟件所需的所有內容,包括代碼、運行時、庫、環境變量和配置文件。
Java基礎
Hash沖突的解決方式
- 鏈表法(HashMap)+ 紅黑樹(默認鏈表長度超過8)
- 再哈希法
- 開放定址法
- 建立公共溢出區
HashMap和CurrentHashMap的對比
HashMap線程不同步,底層使用鏈表和紅黑樹的方式處理沖突
CurrentHashMap:
- JDK 1.7 :使用segment數組,每個segment中存儲一定量的HashEntry,HashEntry用鏈表處理沖突;線程安全通過鎖被操作的segment
- JDK 1.8 :直接使用Node結點,使用Synchronized和CAS的方式實現線程安全
紅黑樹的特性,以及保持平衡的方式
- 每個結點不是紅色就是黑色
- 根節點是黑色的
- 如果一個節點是紅色的,則它的子結點必須是黑色的(沒有連續的紅色節點)
- 對于每個結點,從該結點到其所有可到達的葉結點的路徑中,均包含相同數目的黑色結點
- 每個 NIL 葉子結點都是黑色的(此處的葉子結點指的是空結點)
保持平衡:
- 插入:
- 插入新節點涂紅色
- 如果父節點為黑色不用操作
- 如果父節點為紅色
- 父節點無兄弟節點或父節點的兄弟節點為黑色,直接旋轉操作
- 父節點有兄弟結點,且兄弟結點也為黑色,直接上溢:將父節點和叔都涂為黑色,將祖父節點涂為紅色,然后在上溢部分繼續判斷是否需要處理
- 刪除:
- 刪除結點都在B樹的最后一層,可以理解為都在紅黑樹的最下面2層
- 刪除最后一層的紅色結點沒有影響
- 刪除最后一層的黑色節點:
- 如果黑色節點有2個子節點,不允許刪除
- 如果黑色結點只有一個子節點,刪除黑色結點,并用子節點取代該位置,同時染成黑色
- 如果黑色結點為葉子節點:
- 該節點沒有兄弟節點(只能是根節點),直接刪除
- 該節點的兄弟結點為黑色,旋轉兄弟結點
- 該節點的兄弟結點為紅色,旋轉兄弟和父節點
線程
自定義線程池有哪些參數,分別是什么
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
參數 | 參數意義 | 參數名稱 | 參數要求 |
---|---|---|---|
參數一 | 指定線程池的線程數量(核心線程) | corePoolSize | 不能小于0 |
參數二 | 指定線程池可支持的最大線程數 | maximumPoolSize | 最大數量 >= 核心線程數量 |
參數三 | 指定臨時線程的最大存活時間 | keepAliveTime | 不能小于0 |
參數四 | 指定存活時間的單位(秒、分、時、天) | unit | 時間單位 |
參數五 | 指定任務隊列 | workQueue | 不能為null |
參數六 | 指定用哪個線程工廠創建線程 | threadFactory | 不能為null |
參數七 | 指定線程忙,任務滿的時候,新任務來了怎么辦 | handler | 不能為null |
volitail關鍵字
保證了不同線程之間對共享變量操作的可見性
- 每個線程都能從主內存中獲取volitail修飾的屬性,并緩存在本地工作內存中
- 一旦有線程修改了該值,會自動刷新到主內存中,同時其他內存中的該值失效,再次訪問需要重新到主內存中獲取
禁止對指令進行重排序操作。
- 保證該指令前的所有指令都執行,該指令后的所有指令都未執行
鎖
AQS
AQS
( Abstract Queued Synchronizer )是一個抽象的隊列同步器,通過維護一個共享資源狀態( Volatile Int State )和一個先進先出( FIFO )的線程等待隊列來實現一個多線程訪問共享資源的同步框架。
原理:
AQS 為每個共享資源都設置一個共享資源鎖,線程在需要訪問共享資源時首先需要獲取共享資源鎖,如果獲取到了共享資源鎖,便可以在當前線程中使用該共享資源,如果獲取不到,則將該線程放入線程等待隊列(先進先出),等待下一次資源調度
使用:
在使用AQS創建自定義鎖時,AQS一般是被內部類去繼承實現的。需要去重寫幾個方法:tryAcquire(int)
,tryRelease(int)
,tryAcquireShared(int)
,tryReleaseShared(int)
,isHeldExclusively()
(最后一個方法一般在需要使用condition時才需要重寫,即當某線程需要放到條件隊列中,遇到某條件才喚醒時使用)
在使用時可以在tryAcquire(int)
和tryRelease(int)
中使用getState()
,setState(int)
,compareAndSetState(int,int)
去獲取和改變AQS的狀態碼,AQS的狀態碼默認情況下是:0代表鎖可用,1代表鎖被占有;使用setExclusiveOwnerThread()設置獨占資源的線程;因此可以在tryAcquire(int)
獲取狀態碼,為0的情況下置為1,并返回true,在tryRelease(int)
將狀態碼置為0,完成鎖的釋放。在繼承AQS類并重寫完這些方法后,就可以調用其本身的acquire和release方法獲取和釋放鎖了。
CAS如何實現
CAS:CompareAndSwep,其中包括幾個參數:①對象本身②值的內存偏移地址③期望更新的值(舊值)④更新的值(新值),只有當目前的值和期望更新的值相同時,才會去完成更新操作,否則會自旋或者不操作。
但作為樂觀鎖,可能會遇到ABA問題,可用版本號和時間戳來解決
共享鎖
mysql的行鎖中的讀鎖即是共享鎖。即:多個線程如果都對某一行數據發起讀請求,就會嘗試獲取該行數據的共享鎖,可由多個線程或事務獲取到該共享鎖,即讀操作可同時發生。
與此相對的就是排他鎖/互斥鎖,一旦獲取了一行數據的排他鎖/互斥鎖,其他事務或線程就不能獲取該數據的任何鎖;并且如某行數據被獲取了共享鎖,也不能再被獲取排他鎖/互斥鎖。
讀可共享-讀寫不共享-寫寫不共享
分布式鎖
分布式鎖用于解決分布式系統中控制共享資源的訪問
Redis的分布式鎖:
- 使用setnx添加鎖(setnx保證原子性,且只有在key不存在時才能成功,即多個系統并發獲取鎖,也只有一個系統能成功獲取到鎖)
set <lock.key> <lock.value> nx ex <expireTime>
同時用ex能設置過期時間 - 可使用del主動釋放鎖,即直接刪除該鍵值對
- 可重入鎖的實現方式:hash類型設置可重入鎖,
HSETNX
,然后通過獲取其中的字段判斷是否可重入,并且能夠設置重入的次數。 - 使用Redission的看門狗機制或者自定義守護線程維護獲取鎖的業務的鎖過期時間
ReentrantLock和Synchronized
ReentrantLock | Synchronized | |
---|---|---|
鎖實現機制 | 依賴AQS | 監視器模式 |
靈活性 | 支持響應中斷、超時、嘗試獲取鎖 | 不靈活 |
釋放形式 | 必須顯式調用unlock() | 自動釋放監視器 |
鎖類型 | 公平鎖&非公平鎖 | 非公平鎖 |
條件隊列 | 可關聯多個條件隊列 | 關聯一個條件隊列 |
可重入性 | 可重入 | 可重入 |
JVM
JVM有哪些垃圾回收器
垃圾回收器 | 版本 | 適用范圍 | 特點 | 算法 |
---|---|---|---|---|
Serial(串行收集器) | jdk1.1 | 新生代 | 只會使用一個CPU或者一條GC線程進行垃圾回收 并且在垃圾回收過程中暫停其他工作線程 | 標記-復制-清除 |
ParNew | jdk1.3 | 新生代 | Serial的多線程版本 | 標記-復制-清除 |
Parallel Scavenge | jdk1.4 | 新生代 | 追求CPU吞吐量的優化 能在較短的時間內完成指定的任務 | 標記-復制-清除 |
Serial Old | jdk1.3 | 老年代 | 單線程 暫停應用程序執行 | 標記-整理 |
Parallel Old | jdk1.5 | 老年代 | 多線程 和用戶線程并發 | 標記-整理 |
CMS(concurrent mark sweep) | jdk1.4 | 老年代 | 初始標記(停) 并發標記(運) 重新標記(運) 并發清除 | 標記-清除 |
G1 | jdk1.7引入 jdk1.9默認 | 老年代 | 重新標記階段停止業務線程 軟實時 內存劃分變為Region并評估每個region價值 首先清除垃圾最多的區域 | 標記-整理 |
類加載機制
java源碼經過javac編譯后形成class字節碼文件,jvm將字節碼文件加載進內存,經過字節碼驗證器驗證,為類變量進行內存分配和初始化零值,字節碼解釋器解釋執行字節碼指令轉換為底層機器代碼并執行。
雙親委派
如果一個類加載器收到了類加載的請求,他首先不會自己去嘗試加載這個類,而是把這個請求委派父類加載器去完成。每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個請求時,子加載器才會嘗試自己去加載。
當發現在某一步該類已經被加載過時,會直接返回已加載的類,避免重復加載
反射
反射通過類加載器加載class字節碼文件實現,可通過一個類的字節碼獲取該類的所有信息,包括屬性、方法等
獲取類對象:
Class<?> clazz = MyClass.class;
通過類字面常量獲取類對象Class<?> clazz = Class.forName("com.example.MyClass");
通過Class.forName()方法獲取MyClass object = new MyClass(); Class<?> clazz = obj.getClass();
通過對象的getClass()獲取Class<?> clazz = getClass().getClassLoader().loadClass("com.example.MyClass");
根據類對象生成對象實例:Object object = (Object)clazz.newInstance();
根據類對象獲取屬性和方法:
getFields()
:獲取所有public的屬性getDeclaredFields()
:獲取所有(不限修飾符的)屬性getType
:以Class形式返回類型getName
:返回屬性名setAccessible(true)
:使用
getMethods()
:獲取所有pubic的方法getDeclaredMethods()
:獲取所有(不限修飾符的)方法getReturnType
:以Class形式獲取返回類型getName
:返回方法名getParameterTypes
:以Class[]返回參數類型數組invoke(obj, param1, ...)
:調用方法
getConstructors()
:獲取所有public的構造方法getDeclaredConstructors()
:獲取所有(不限修飾符的)構造方法getModifiers
:以int形式返回修飾符.getName
:返回構造器名(全類名).getParameterTypes
:以Class[]返回參數類型數組
異常
異常的分類,以及有什么區別
Error(錯誤):是程序無法處理的錯誤,表示代碼運行時JVM出現的問題。例如:OutOfMemoryError
、NullPointerException
Exception(異常):是程序本身可以處理的異常。
- RuntimeException:運行時異常,不受檢查異常,表示JVM常用操作引發的錯誤,編譯時能通過,但會在后期代碼的執行過程中暴露出來
- 其他異常:受檢查異常,在編譯時不能被忽略,程序必須對它有相應的處理
計算機網絡
Https為什么安全
- 瀏覽器發起 HTTPS 請求
- 服務端返回 HTTPS 證書
- 客戶端驗證證書是否合法,如果不合法則提示告警
- 當證書驗證合法后,在本地生成隨機數
- 通過公鑰加密隨機數,并把加密后的隨機數傳輸到服務端
- 服務端通過私鑰對隨機數進行解密
- 服務端通過客戶端傳入的隨機數構造對稱加密算法,對返回結果內容進行加密后傳輸
數據傳輸是用對稱加密:非對稱加密的加解密效率非常低
- https協議需要到ca申請證書,一般免費證書較少,因而需要一定費用。
- http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
- http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
- http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。
TCP擁塞控制
- 慢啟動
- 最初擁塞控制窗口cwnd的初始值為一個小值,推薦為2個MSS(MSS通常為536字節或1460字節)
- MSS:Maximum Segment Size ,最大報文段長度,TCP提交給IP層最大分段大小
- 當收到一個ACK后,
cwnd = cwnd*2
- 最初擁塞控制窗口cwnd的初始值為一個小值,推薦為2個MSS(MSS通常為536字節或1460字節)
- 擁塞避免
- 擁塞窗口cwnd值等于慢開始門限值后,
cwnd = cwnd+1
- 擁塞窗口cwnd值等于慢開始門限值后,
- 快速恢復
- 擁塞時,將慢開始門限修改為cwnd/2,并且將
cwnd = cwnd/2
- 擁塞時,將慢開始門限修改為cwnd/2,并且將
- 快速重傳
- 連續收到3條對某報文段的重傳確認,就需要快速重傳該報文段
地址框輸入url后經歷了什么
- DNS解析
- 在自己的DNS高速緩存中查找
- 權限域名服務器->頂級域名服務器->根域名服務器
- TCP連接
- TCP三次握手
- 發送HTTP請求
- 服務端處理請求:根據路徑查找對應的資源(服務),然后返回數據報
- 瀏覽器收到返回的數據,進行渲染,形成頁面
- TCP斷開
- 四次揮手