- 基礎(√)
- 集合(√)
- 多線程(√)
- JVM(√)
- Redis(√)
- Mysql(√)
- MongoDB
- 計網+操作系統(tǒng)
- Spring
1. Redis
- 什么是Redis:非關系型的鍵值對數據庫,數據存在內存中,讀寫速度快,一般用于緩存數據
- 項目為什么使用mongoDB:(https://blog.csdn.net/dog_flying/article/details/100052831)(https://zhuanlan.zhihu.com/p/670763653)
-
為什么不使用Redis緩存+Mysql存數據的方式
- 要維護Redis緩存跟Mysql數據的一致性問題
- 業(yè)務開發(fā)時要維護Mysql的表結構,比如有新業(yè)務要新增表字段,開發(fā)起來很麻煩
-
為什么選擇mongoDB
- MongoDB自身有一個緩存層,這樣就可以用一個MongoDB就能實現緩存+存儲數據的功能
- MongoDB的是文檔型,玩家的某個系統(tǒng)的數據是以文檔形式保存在mongoDB中,讀取數據時,從庫中讀取,放到內存中,更新數據時,先更新內存的數據,然后定義一定的時間間隔,再把內存的數據寫回數據庫(項目一般是5分鐘執(zhí)行一次,也可以手動調用update()方法更新,一般在玩家下線或者停服的時候update()玩家數據和全服玩家的數據
- MongoDB最大的特點就是表結構靈活,像游戲這種經常有新需求需要新增字段的,使用mongoDB直接在表里加字段就行了,不需要考慮表的結構
- 對數據的操作一般都是在業(yè)務代碼中進行,不需要在SQL層面進行復雜的查詢操作和事務操作
-
- Redis優(yōu)缺點
-
優(yōu)點:
- 基于內存,讀寫速度快
- 單線程,避免了線程切換的開銷和多線程的競爭。執(zhí)行命令是由單線程執(zhí)行
- 支持持久化,RDB和AOF兩種持久化方式,可以將數據保存到磁盤,避免數據丟失
- 支持事務
- 支持主從復制,主節(jié)點自動將數據同步到從節(jié)點
-
缺點:
- 因為是將數據放在內存,因此會受到服務器內存大小的限制,不支持大量數據的存放
-
- 為什么快
- 基于內存,數據讀寫在內存進行,速度快
- 單線程執(zhí)行命令,避免了線程切換的開銷和多線程競爭
- io多路復用
- 數據結構簡單,kv鍵值對形式
- Redis是單線程還是多線程
- redis6.0之前是單線程的,redis6.0之后引入多線程技術,只是用來解決網路IO讀寫的問題,執(zhí)行命令還是單線程的
- Redis數據類型
-
String:鍵值對,key和value都是字符串
- 指令
- 設置kv,可設置存活時間:set key value [ex second][millseconds]
- 獲取key:get key
- 自增:incr key
- 自減:decr key
- 應用
- 緩存
- 計數器:粉絲數
- 指令
Hash:key-field,常用于存儲對象
Set:存儲無序不重復單獨字符串,最多MAX_VALUE個,支持并集、交集??捎糜诖鎯餐P注
-
List:存儲有序可重復的字符串,最多MAX_VALUE個,可以兩端彈出插入
- 指令:lpop、lpush、rpop、rpush
ZSet:存儲有序不重復的字符串,zrange指令可做排行榜
-
- Redis事務
- multi開啟事務、exec執(zhí)行事務、discard取消事務
- redis事務無法保證原子性,單條命令是原子性的,但是整個事務不是原子性,如果事務中某條命令出錯,不影響其他命令的執(zhí)行,事務也不會回滾
- redis事務沒有隔離級別,multi開啟事務后,exec執(zhí)行事務前,輸入的命令會先進入隊列,先不執(zhí)行。也就不存在事務內的某條查詢命令會看到其他事務的更新,其他事務的查詢也無法看到本事務內的更新
- 持久化機制
-
RDB:redis默認的持久化機制,將數據庫快照保存到dump.rdb文件中
- 觸發(fā)
- save命令:是同步命令,阻塞客戶端請求,直到保存成功
- bgsave命令:異步命令,fork一個子進程來進行數據保存,不會阻塞客戶端請求
- 通過配置文件,自動保存:save 60 1000:指的是當60秒內有1000個key被改動時,觸發(fā)自動保存
- 優(yōu)點:數據恢復快
- 缺點:如果是用主動輸入命令進行保存,耗時、耗性能。
如果是自動保存,又不一定能觸發(fā)保存機制
- 觸發(fā)
-
AOF:
- 需要在配置文件中開啟:appendonly yes
- 原理:開啟AOF后,當redis執(zhí)行一個命令后,這個命令就會被追加到AOF文件的末尾
- 策略
- always:每次有新命令追加到AOF文件時就執(zhí)行一次fsync,非常慢,但非常安全。
- everySec:每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),并且在故障時只會丟失 1 秒鐘的數據。推薦(并且也是默認)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。
- no:由操作系統(tǒng)執(zhí)行,不安全
-
- Redis集群
-
為什么要部署集群:
- 單機情況下,一旦服務器宕機,數據不可用
- 單機的內存容量有限,可緩存的數據有限
-
主從復制:主節(jié)點負責讀寫,從節(jié)點只負責讀,主節(jié)點修改后的數據會同步到從節(jié)點
- 配置主從模式
- 從服務器節(jié)點的配置文件,將slaveOf的port端口改成主服務器的port,然后進入主服務器,通過info replication命令查看是否配置成功
- 在從服務器節(jié)點使用slaveOf 主服務器port
- 優(yōu)點:
- 高可用,當主節(jié)點宕機后,從節(jié)點接替主節(jié)點的工作
- 讀寫分離,主節(jié)點負責讀寫,從節(jié)點只負責讀
- 缺點:主節(jié)點宕機后無法恢復,只能由從節(jié)點全權接替工作
- 配置主從模式
-
哨兵模式:為了解決主從復制模式下主節(jié)點宕機后只剩下從節(jié)點的問題,引入了哨兵模式,在哨兵模式下,當主節(jié)點宕機后,從節(jié)點會通過競爭,選取一個從節(jié)點升級為主節(jié)點
- 配置哨兵模式:
- 配置sentinel.conf配置文件,sentinel monitor 主機名 主機ip 主機port 觸發(fā)切換的哨兵數量
- 使用redis-sentinel命令啟動哨兵服務
- 哨兵的作用
- 監(jiān)視和提醒,當服務器節(jié)點出現問題時,報告
- 自動故障遷移,當主節(jié)點宕機后,哨兵之間會選取一個從節(jié)點升級為主節(jié)點,原來的主節(jié)點重連后,只能作為從節(jié)點
- 優(yōu)點:解決了主從復制模式的主節(jié)點缺失問題
- 配置哨兵模式:
集群:配置多個主從復制+哨兵模式
-
- 過期策略:惰性刪除、定期刪除、定時刪除
expire設置key存活時間、set key value []- 定期刪除:每隔一段時間對一些key進行檢查,刪除已經過期的key
- 定時刪除:為每個設置過期時間的key開一個定時器進行清理
- 惰性刪除:訪問這個key的時候才檢查是否已過期,過期就清除
- 緩存擊穿
- 原因:一個被大量訪問的key突然過期了,導致大量的查詢請求要去到數據庫查詢
- 解決:熱點key不設置過期時間
- 緩存穿透
- 原因:大量的惡意請求查詢一個不存在的key,因為緩存里找不到,要去到數據庫中查詢,導致數據庫壓力增大
- 解決:使用布隆過濾器,其原理相當于在緩存跟數據庫之間再加了一層緩存,在初始化時,從數據庫中把已有的key拿出來,放到布隆過濾器中,如果key在布隆過濾器中找不到,則說明在數據庫中也沒有,可以攔截惡意請求打到數據庫
- 緩存雪崩
- 原因:同一時間有大量的key同時失效,導致大量請求打到數據庫上
- 解決:設置key過期時間時,用隨機數,避免大量的key同時過期
2. Mysql
- mysql是關系型數據庫,redis和mongoDB是非關系型數據庫,什么時候用
- 數據量小的時候用關系型數據庫,因為是將數據存放在磁盤,讀寫數據要進行磁盤IO,速度慢
- 數據量大的時候用非關系型數據庫,將數據讀取到內存,內存讀寫速度快
- 用非關系型數據庫做緩存,用關系型數據庫存數據
- 事務四大特性:ACID
- 原子性:事務包括的操作要么全部成功,要么失敗回滾
- 一致性:事務執(zhí)行前后保持一致。比如a和b賬戶共有1000塊,兩人之間的轉賬無論是成功還是失敗,總數都是1000
- 隔離性:事務進行的修改在最終提交之前,其他事務不能見其修改結果
- 持久性:事務對數據的修改一旦提交,就會保存到數據庫中
- 臟讀、不可重復讀、幻讀
- 臟讀:一個事務處理過程中讀取了另一個未提交事務的數據
- 不可重復讀:同一個事務內,多次查詢同一個記錄,返回了不同的數據,這是因為在兩個查詢間隔,另一個事務修改了數據并提交了結果
- 幻讀:事務在讀取某個范圍內的記錄時(記錄的范圍區(qū)間),有另一個事務在該范圍區(qū)間插入或刪除了一條記錄,導致讀取到的記錄條數不一致
- 事務隔離級別
- 串行化:加鎖處理,強制事務按照順序執(zhí)行??山鉀Q上面三個問題
- 可重復讀:同一個事務中多次讀取的數據是一致的,是mysql的默認隔離級別??山鉀Q不可重復讀和臟讀問題。
- 讀已提交:事務只能看到已經提交事務的修改結果,可解決臟讀問題。
- 讀未提交:所有事務都可以看到其他未提交事務的執(zhí)行結果
- 隔離級別如何實現
- 讀已提交和可重復讀通過MVCC實現,串行化通過鎖實現
- MVCC機制
- 當前讀:讀取的是數據庫的最新版本的數據,并且在讀取時要求其他事務不會修改當前的記錄,所以是對讀取的記錄進行了加鎖處理
- 快照讀:不加鎖,通過MVCC版本號讀取UNDO LOG快照日志讀取中的數據
- 什么是索引:索引是加快數據表的訪問速度的一種數據結構
- 為什么索引可以加快檢索速度
索引的作用就像一本書的目錄,可以快速定位數據在表中的位置。如果沒有索引就要遍歷全部數據逐個查找
索引的底層是B+樹,在B+樹中,節(jié)點的key按值的大小從左到右升序排序,數據存在葉子節(jié)點。在進行查找時,首先在根節(jié)點進行二分查找,找到key所在的指針,然后在指針指向的節(jié)點區(qū)域進行查找,找到葉子節(jié)點,得到key對應的數據
3. B+樹的索引又可以分為聚簇索引和非聚簇索引
1. 主索引為聚簇索引,輔助索引為非聚簇索引。
2. 聚簇索引是以主鍵作為鍵值,聚簇索引的葉子節(jié)點存放著完整的數據。非聚簇索引是以非主鍵作為鍵值,葉子節(jié)點存放著主鍵值,所以非聚簇索引在查找時,要先找到主鍵,然后根據聚簇索引找到主鍵對應的數據(回表操作)
3. 聚簇索引使用場景:
select id from test where id = 10; //搜索id索引樹
4. 非聚簇索引使用場景
select * from test where name = "123"; //非主鍵查詢,先搜索name字段,得到name="123"對應的主鍵id值,再搜索聚簇索引,找到對應id值的數據
select name from test where name = "123"; //如果非聚簇索引上有name的值等于123,那么它就不用回表
4. 為什么B+樹比B樹更適合
1. B樹每個節(jié)點都要存key和data,而B+樹的data都存在葉子節(jié)點,非葉子節(jié)點存key。這樣就使得B+樹的一個節(jié)點可以存放更多的索引,樹的高度更低,磁盤IO次數更少,數據檢索速度更快
2. B+樹的葉子節(jié)點是按照key的值升序相連的,范圍查找更快
3. B+樹的數據都在葉子節(jié)點,查詢更穩(wěn)定,每次查詢都是從根節(jié)點到葉子節(jié)點
- 什么時候要建索引,什么時候不用建索引
- 用索引:經常查詢的字段、主鍵必須加索引、排序字段使用索引可以加快檢索速度、聯表查詢
- 不用索引:經常增刪數據的字段、有大量重復數據的字段、表數據太少時沒必要用索引
- 索引有哪些類型
- 主鍵索引:數據不能重復,不能為null,一張表只能有一個主鍵索引
- 唯一索引:數據不能重復,可以為null
- 普通索引
- 組合索引:由多個數據列組成的索引
- 全文索引:對文本內容進行搜索
- 創(chuàng)建索引和刪除索引
- CREATE INDEX在已創(chuàng)建的指定的表和列上創(chuàng)建一個普通索引:CREATE INDEX (INDEX_NAME) ON (TABLE_NAME)(COLUNM_LIST)
- 建表時指定數據列
- ALTER TABLE創(chuàng)建索引
- ALTER TABLE DROP刪除索引
- 組合索引
-
為什么使用組合索引
- 一個索引能夠覆蓋多個索引字段可以減少空間的開銷。
- 減少回表次數,比如有1000W的數據,搜索3個字段,不使用聯合索引執(zhí)行select操作,每次都要進行回表操作。而使用聯合索引時,如果3個字段能夠全部覆蓋,則不進行回表(覆蓋索引情況)
如:select col1,col2,col3 from table where col1 = 1 and col2 = 2 and col3 = 3; //每個條件可以篩選出10%的數據 不使用聯合索引:先查詢col1的10%,即1000W*10%=100W,然后回表從100W條數據中再查詢符合col2數據,100W*10%,再回表查詢符號col3的數據,10W*10%。 使用聯合索引,直接搜索:1000W*10%*10%*10%=1W -
最左匹配原則:從SQL語句的左邊開始,當遇到范圍查詢(>、<、between、like>)等就會停止匹配,后面的字段不會使用索引
比如:對abc三個列建立聯合索引- 當查詢a/ab/abc時會走索引,查詢bc時不會走索引
- 當查詢a=1 and b>2 and c=3時,c就不會走索引
-
什么情況下索引會失效
- 組合索引,在不符合最左匹配原則時,索引失效
- 以%或者like開頭的查詢
- 查詢條件以or連接
- 在索引上進行計算
-
- mysql的數據結構:數值、日期、字符串
- 數值:整數int、浮點型float、double
- 日期:date
- 字符串:varchar、char
- mysql的鎖
并發(fā)事務時,保證數據訪問順序的機制叫鎖
-
鎖跟隔離級別的關系
- 串行化:鎖住整個事務范圍,直到事務結束
- 可重復讀:讀取數據時加共享鎖,事務結束后才釋放共享鎖
- 讀已提交:讀取數據時加共享鎖,讀取完之后釋放鎖
- 讀未提交:不加鎖
鎖的類型:表鎖、頁鎖、行鎖。innodb默認采用表鎖
共享鎖:讀鎖,一個事務對一個數據加了共享鎖,只能進行讀取操作,不能更新該數據,其他事務也不能對該數據加排他鎖
排他鎖:寫鎖,一個事務對一個數據加了排他鎖,可以對該數據進行讀取和更新,期間其他事務不能對該數據加共享鎖和排他鎖