menu
1 數據庫 2 jvm 3 redis 4 Mq 5 springcloud 6 系統解決方案 7 多線程 8 網絡
為什么說B+比B樹更適合實際應用中操作系統的文件索引和數據庫索引?
1、B+的磁盤讀寫代價更低。
B+的內部結點並沒有指向關鍵字具體信息的指針,因此其內部結點相對B樹更小。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。
2、B+-tree的查詢效率更加穩定。
所有的記錄都存儲在葉子節點上面。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
3、葉子節點都是有序鏈表存儲的,更利於范圍存儲
MySQL InnoDB、Mysaim的特點?
Innodb是聚集索引,支持事務,支持外鍵 ,支持行鎖,必須有唯一索引,適合修改刪除多的,回表查詢指的是innodb里面非聚集索引的查詢。
Myisam是非聚集索引,葉子節點保存指向數據的指針。不支持事務。
Mysql默認隔離級別
可重復讀(RR),由於之前mysql的binlog同步模式為statement,RC會產生數據不一致。當前binlog已經支持row的格式,可以選擇RC+ROW,作為mysql的隔離級別和日記格式
數據庫隔離級別是什么?
A原子性(undo log)、C一致性(AID來保證)、I隔離性(加鎖、mvcc)、D持久性(redo log)
讀已提交(臟讀)、可重復讀(讀未提交)、序列化(幻讀)
MySQL主備同步的基本原理。 當slave連接到master的時候,master機器會為slave開啟binlog dump線程。當master 的 binlog發生變化的時候,binlog dump線程會通知slave,並將相應的binlog內容發送給slave
如何優化數據庫性能(索引、分庫分表、批量操作、分頁算法、升級硬盤SSD、業務優化、主從部署)
SQL什么情況下不會使用索引( select *、索引列上有函數、字段類型錯誤、like%、or、not in、not exist、order by 不加where,加了limit)
exists和in 如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in
MVCC
InnoDB中的實現主要是為了提高數據庫並發性能,用更好的方式去處理讀-寫沖突,做到即使有讀寫沖突時,也能做到不加鎖,非阻塞並發讀
通過readview 機制和 undo log 實現了讀不被阻塞,而且在一定程度上實現RC和RR,並且RR級別在大部分時候可以解決幻讀
快照讀(select ...)的幻讀是用MVCC解決的,當前讀(select ... for update; update; delete)的幻讀是用間隙鎖解決的。
數據庫事務的幾種粒度
表鎖、行鎖(通過索引來加鎖)只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖
如何解決高並發減庫存問題
如何從一張表中查出name字段不包含“XYZ”的所有行?
not in where name LIKE "%XYZ%"
mysql主從同步延時分析 1.業務的持久化層的實現采用分庫架構,mysql服務可平行擴展,分散壓力。
2.單個庫讀寫分離,一主多從,主寫從讀,分散壓力。這樣從庫壓力比主庫高,保護主庫。
3.服務的基礎架構在業務和mysql之間加入memcache或者redis的cache層。降低mysql的讀壓力。
4.使用比主庫更好的硬件設備作為slave,mysql壓力小,延遲自然會變小。
加鎖原則
拿MySql的InnoDB引擎來說,對於insert、update、delete等操作。會自動給涉及的數據加排他鎖;
對於一般的select語句,InnoDB不會加任何鎖,事務可以通過以下語句給顯示加共享鎖或排他鎖。
共享鎖:SELECT ... LOCK IN SHARE MODE;
排他鎖:SELECT ... FOR UPDATE;
索引的優缺點:優點,提高查詢速度;缺點,更新數據時效率低,因為要同時更新索引
Eureka的源碼分析服務注冊和服務發現以及心跳機制和保護機制,對比eureka與zookeeper,什么是CAP原則?
服務注冊,客戶端啟動后向服務端發送一個心跳,如果返回404,證明未注冊,發起注冊
服務發現 客戶端定時拉去服務列表,保存在本地,使用時調用本地
心跳機制 客戶端每30s會向服務端發送一個心跳,如果90s沒有收到心跳,服務端會剔除客戶端
自我保護機制 服務端在發現一定時間內剔除的節點過多,就會觸發自我保護,不再剔除節點
Eureka支持AP 1、自我保護機制 2、server端低位平等,只要一個server存在就可以正常工作
Zookeeper支持CP 哨兵模式,需要選主,選舉過程停止服務,中心化思想
Nacos
Ribbon源碼分析和客服端負載均衡,客戶端負載均衡?服務端負載均衡? Ribbon核心組件IRule以及重寫IRule
客戶端負載均衡,Ribbon實現IRule接口來自定義負載均衡策略
Fegin源碼分析和聲明式服務調用,Fegin負載均衡,Fegin如何與Hystrix結合使用? 有什么問題?
給feigin類寫一個實現類fallback,里面定義一些方法,在feigin調用的時候,在類上引入fallback
Hystrix實現服務限流、降級,大型分布式項目服務雪崩如何解決? 服務熔斷到底是什么?一線公司的解決方案
服務降級:返回一個友好提示,場景:程序運行異常、超時、服務熔斷、服務限流
服務熔斷:當失敗達到一定閾值之后,停止服務調用,直接降級。等待一個時間窗口之后,繼續重試
服務限流:采用線程池和信號量的方式對服務調用進行限流
Zuul統一網關詳解、服務路由、過濾器使用等,從源頭來攔截掉一些不良請求
路由 : 網關的基本模塊,有ID,目標URI,一組斷言和一組過濾器組成
斷言:就是訪問該路由的訪問規則,可以用來匹配來自http請求的任何內容,例如headers或者參數
過濾器:這個就是我們平時說的過濾器,用來過濾一些請求的,gateway有自己默認的過濾器,我們也可以自定義過濾器,但是要實現兩個接口,ordered和globalfilter
分布式鏈路跟蹤詳解,串聯調用鏈,,讓Bug無處可藏,如何厘清微服務之間的依賴關系?如何跟蹤業務流的處理順序?
2、 持久化:RDB、AOF
3、 緩存擊穿:1、查詢之后將數據刷新到redis中 2、避免一些熱點數據在同一時間失效、
緩存雪崩:同時失效或者redis掛掉。1、分散過期時間,2、通過hystrix進行訪問降級或者限流 3、redis進行分布式部署
緩存穿透:1、增加查詢限制條件 2、在特殊值加載到緩存里面 3布隆過濾器
5、 使用場景:1、會話緩存 2、熱點數據緩存 3、搜索歷史記錄 4、分布式鎖
6、單線程,I/O多路復用, 通過數組的方式同時處理多個I/O
7、高可用方案:主從、哨兵、cluster(hash槽)https://blog.csdn.net/u014209205/article/details/82113258
8、redis如何實現多寫入,通過事務中添加watch來檢測,要修改的key是否已經被其他客戶端修改
9、redis腦裂:出現了兩個master節點,clientA繼續往舊的master寫入,舊master降級成為slave節點,會進行全量同步,會把clientA寫入的數據清空。解決方案:參數配置,min-slave-to-write 2、min-slaves-max-lag 5:至少2個slave對master的同步復制延遲不能超過5秒,如果達不到要求,master停止接受請求
10、redis主從節點是長連接
11、redis如何判斷某個節點是否正常工作?通過心跳檢測機制,主節點10秒發送一次心跳檢測從節點 ,從節點1秒發送一次心跳給主節點同步自己的復制偏移量
12、主從如何判斷全量同步還是增量同步?從節點slave到主節點之后,如果是首次直接全量同步,如果存在偏移量,比較偏移量和主節點的緩沖區大小,如果比緩存區小,那么可以進行增量同步,不然進行全量同步
13、redis不同數據類型的作用
- String:緩存,限流,計數器,分布式鎖,分布式Session
- Hash:儲存用戶信息,用戶主頁訪問量,組合查詢
- List:微博關注人時間軸列表,簡單隊列
- Set:贊,踩,標簽,好友關系
- Zset:排行榜
14.Redis為什么這么快?官方使用的基准測試結果表明,單線程的Redis可以達到10W/S的吞吐量。
a.基於內存操作:Redis的所有數據都存在內存中,因此所有的運算都是內存級別的,所以它的性能比較高。
b.數據結構簡單:Redis的數據結構比較簡單,是為Redis專門設計的,而這些簡單的數據結構的查找和操作的時間復雜度都是O(1)。
c.多路復用和非阻塞IO:Redis使用IO多路復用功能來監聽多個socket連接的客戶端,這樣就可以使用一個線程來處理多個情況,從而減少線程切換帶來的開銷,同時也避免了IO阻塞操作,從而大大提高了Redis的性能。
d.避免上下文切換:因為是單線程模型,因此就避免了不必要的上下文切換和多線程競爭,這就省去了多線程切換帶來的時間和性能上的開銷,而且單線程不會導致死鎖的問題發生。
Redis在4.0之前單線程依然快的原因:基於內存操作、數據結構簡單、IO多路復用和非阻塞IO、避免了不必要的線程上下文切換。並且在Redis4.0開始支持多線程,主要體現在大數據的異步刪除方面,例如:unlink key、flushdb async、flushall async等。而Redis6.0的多線程則增加了對IO讀寫的並發能力,用於更好的提升Redis的性能
1、notify喚醒哪一個線程?
notify方法只喚醒一個等待(對象的)線程並使該線程開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於操作系統對多線程管理的實現。
notifyAll會喚醒所有等待(對象的)線程,盡管哪一個線程將會第一個處理取決於操作系統的實現。如果當前情況下有多個線程需要被喚醒,推薦使用notifyAll方法。
2、如何停止一個線程的運行
stop()、interrupt() 設置一個標志位,在run方法內部進行判斷。
https://www.nowcoder.com/discuss/740580?source_id=discuss_experience_nctrack&channel=-1
3、線程如何同、進程如何同步
1、Mq如何保證消息不丟失 : 1、生產者:采用confirm機制(同步、異步) 2、mq本身:消息持久化,可以結合confirm機制 3、消費者:關閉自動的ack
2、消息隊列機制 https://blog.csdn.net/h2604396739/article/details/81136527
3、消息堆積:會阻塞生產者,必須提高消費端能力,還可以增加隊列容量,
tcp如何保證傳輸可靠性,tcp的報文頭包含什么
https: 1、非對稱+對稱:先用非對稱瀏覽器將對稱秘鑰傳給服務器,之后服務器和瀏覽器通過對稱加密傳輸 2、防止公鑰被篡改,采用證書
java對象內存分布
1,對象頭 2,實例數據 3,對齊填充字節
對象頭:1,Mark Word 2,指向類的指針 3,數組長度(只有數組對象才有)
mark word :鎖、分代年齡、gc標記
JVM一般是這樣使用鎖和Mark Word的:
1,當沒有被當成鎖時,這就是一個普通的對象,Mark Word記錄對象的HashCode,鎖標志位是01,是否偏向鎖那一位是0。
2,當對象被當做同步鎖並有一個線程A搶到了鎖時,鎖標志位還是01,但是否偏向鎖那一位改成1,前23bit記錄搶到鎖的線程id,表示進入偏向鎖狀態。
3,當線程A再次試圖來獲得鎖時,JVM發現同步鎖對象的標志位是01,是否偏向鎖是1,也就是偏向狀態,Mark Word中記錄的線程id就是線程A自己的id,表示線程A已經獲得了這個偏向鎖,可以執行同步鎖的代碼。
4,當線程B試圖獲得這個鎖時,JVM發現同步鎖處於偏向狀態,但是Mark Word中的線程id記錄的不是B,那么線程B會先用CAS操作試圖獲得鎖,這里的獲得鎖操作是有可能成功的,因為線程A一般不會自動釋放偏向鎖。如果搶鎖成功,就把Mark Word里的線程id改為線程B的id,代表線程B獲得了這個偏向鎖,可以執行同步鎖代碼。如果搶鎖失敗,則繼續執行步驟5。
5,偏向鎖狀態搶鎖失敗,代表當前鎖有一定的競爭,偏向鎖將升級為輕量級鎖。JVM會在當前線程的線程棧中開辟一塊單獨的空間,里面保存指向對象鎖Mark Word的指針,同時在對象鎖Mark Word中保存指向這片空間的指針。上述兩個保存操作都是CAS操作,如果保存成功,代表線程搶到了同步鎖,就把Mark Word中的鎖標志位改成00,可以執行同步鎖代碼。如果保存失敗,表示搶鎖失敗,競爭太激烈,繼續執行步驟6。
6,輕量級鎖搶鎖失敗,JVM會使用自旋鎖,自旋鎖不是一個鎖狀態,只是代表不斷的重試,嘗試搶鎖。從JDK1.7開始,自旋鎖默認啟用,自旋次數由JVM決定。如果搶鎖成功則執行同步鎖代碼,如果失敗則繼續執行步驟7。
7,自旋鎖重試之后如果搶鎖依然失敗,同步鎖會升級至重量級鎖,鎖標志位改為10。在這個狀態下,未搶到鎖的線程都會被阻塞。
2,指向類的指針
該指針在32位JVM中的長度是32bit,在64位JVM中長度是64bit。Java對象的類數據保存在方法區。
3,數組長度
只有數組對象保存了這部分數據。該數據在32位和64位JVM中長度都是32bit。
GCRoots的對象包括下面幾種:
(1). 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中引用的對象。
(2). 方法區中的類靜態屬性引用的對象。
(3). 方法區中常量引用的對象。
(4). 本地方法棧中JNI(Native方法)引用的對象。
sychronized底層實現邏輯、
volatile 內存屏障
防重放:1、增加時間戳,請求超時后端不處理 2、請求攜帶uuid
大文件下載
token機制、spring注解原理、、cpu彪高處理、數據庫慢排查方式、索引失效、CDN刷新不一致