1.在無數的簡歷中見過「精通Redis」的技能描述,當問其一些原理性的東西時候都是磕磕絆絆毫無頭緒及思路,
大部分面試者停留在使用的階段,可是若是單純的使用,不知其原理,
在某些逼死麪試者的面試場景中就會真的被逼死~
3.鞏固自身姿式~
複製代碼
接下來將直入主題html
能夠簡單的認爲底層實現就是SDS(Simple Dynamic String)。Redis中,默認以SDS做爲本身的字符串表示,
只有在一些字符串不可能出現變化的地方使用C字符串。
複製代碼
SDS | C字符串 |
---|---|
獲取字符串長度的複雜度爲O(1) | 獲取字符串長度的複雜度爲O(N) |
API是安全的,不會形成緩衝區溢出 | API是不安全的,可能會形成緩衝區溢出 |
修改字符串長度N次最多須要執行N次內存重分配 | 修改字符串長度N次必然須要執行N次內存重分配 |
能夠保存文本或者二進制數據 | 只能保存文本數據 |
可使用一部分庫的函數 | 可使用全部庫中的函數 |
接下來是比較結果的原理介紹面試
struct sdshdr {
// 用於記錄buf數組中使用的字節的數目
// 和SDS存儲的字符串的長度相等
int len;
// 用於記錄buf數組中沒有使用的字節的數目
int free;
// 字節數組,用於儲存字符串
char buf[]; //buf的大小等於len+free+1,其中多餘的1個字節是用來存儲’\0’的。
};
複製代碼
1.獲取字符串長度的複雜度redis
C語言中: 字符串只是簡單的字符的數組,當使用strlen獲取字符串長度的時候,
內部實際上是直接順序遍歷數組的內容,找到對應的’\0’對應的字符,從而計算出字符串的長度。
即O(N)
S D S : 只須要訪問SDS的len屬性就能獲得字符串的長度,複雜度爲O(1)。
複製代碼
2.杜絕緩衝區溢出數據庫
Redis是C語言編寫的,並無方便的數據類型來進行內存的分配和釋放(C++ STL String),
必須手動進行內存分配和釋放。
對於字符串的拼接、複製等操做,C語言開發者必須確保目標字符串的空間足夠大,否則就會出現溢出的狀況。
當使用SDS的API對字符串進行修改的時候,
1. API內部第一步會檢測字符串的大小是否知足。
若是空間已經知足要求,那麼就像C語言同樣操做便可。若是不知足,則拓展buf的空間
2. 以後再進行操做。每次操做以後,len和free的值會作相應的修改。
擴展buf空間策略:
1. 修改以後總長度len<1MB: 總空間爲2*len+1;
2. 修改以後總長度len>=1MB: 總空間爲len+1MB+1。
換句話說,預分配的空間上限是1MB,儘可能爲len。
複製代碼
3.減小修改字符串時帶來的內存重分配次數segmentfault
Redis主要經過如下兩種策略來處理內存問題。
字符串長度增長操做時,進行空間預分配
字符串長度減小操做時,惰性空間釋放
當執行字符串長度縮短的操做的時候,SDS並不直接從新分配多出來的字節,
而是修改len和free的值(len相應減少,free相應增大,buf的空間大小不變化),避免內存重分配。
SDS也提供直接釋放未使用空間的API,在須要的時候,也能真正的釋放掉多餘的空間。
複製代碼
4.二進制安全數組
C字符串除了末尾以外不能出現空字符,不然會被程序認爲是字符串的結尾。
這就使得C字符串只能存儲文本數據,而不能保存圖像,音頻等二進制數據。
使用SDS就不須要依賴控制符,而是用len來指定存儲數據的大小,
全部的SDS API都會以處理二進制的方式來處理SDS的buf的數據。
程序不會對buf的數據作任何限制、過濾或假設,數據寫入的時候是什麼,讀取的時候依然不變。
複製代碼
5.兼容部分C字符串函數緩存
SDS的buf的定義(字符串末尾爲’\0’)和C字符串徹底相同,所以不少的C字符串的操做都是適用於SDS->buf的。
好比當buf裏面存的是文本字符串的時候,大多數經過調用C語言的函數就能夠。
複製代碼
喵耳朵 redis基本操做-string原理 (原文地址404)安全
SDS底層結構 segmentfault.com/p/121000000…session
string類型爲基本簡單類型也是最經常使用的緩存數據類型,字符串單key長度最長爲512MB,
一般作法是能夠將簡單對象序列化後存入。但建議根據業務及業務數據選擇最優的數據結構,
不建議全部數據均序列化存入string,固然這樣開發很快,可是有一點點low。智者見智。
複製代碼
當string結構中存儲的是數字時,可進行incr、decr操做,可是注意:此時string內部存儲的便再也不是SDS了,同時string方法中setBit及getRange的實現也會有所不一樣(TODO)
複製代碼
用戶從新刷新一次界面,可能須要訪問一下數據進行從新登陸,或者訪問頁面緩存Cookie,
可是能夠利用Redis將用戶的Session集中管理,在這種模式只須要保證Redis的高可用,
每次用戶Session的更新和獲取均可以快速完成。大大提升效率。(這段是抄的)
複製代碼
copy from www.cnblogs.com/DswCnblog/p…數據結構
命令原型 | 時間複雜度 | 命令描述 |
---|---|---|
APPEND | O(1) | 若是該Key已經存在,APPEND命令將參數Value的數據追加到已存在Value的末尾。若是該Key不存在,APPEND命令將會建立一個新的Key/Value。 |
DECR | O(1) | 將指定Key的Value原子性的遞減1。若是該Key不存在,其初始值爲0,在decr以後其值爲-1。若是Value的值不能轉換爲整型值,如Hello,該操做將執行失敗並返回相應的錯誤信息。注意:該操做的取值範圍是64位有符號整型。 |