成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

牛逼!Redis的字符串是這樣實現的…

開發 后端 Redis
Redis雖然是用C語言寫的,但卻沒有直接用C語言的字符串,而是自己實現了一套字符串。目的就是為了提升速度,提升性能,可以看出Redis為了高性能也是煞費苦心。

之前本人在找工作面試時在Redis相關問題上可栽了跟頭。

在面試前按常規套路準備了一下,比如 Redis 的常用5種數據結構,Redis持久化策略,Redis實現分布式鎖,簡單發布訂閱等等都準備了,當時不知天高地厚以為十拿九穩了,可是萬萬沒想到我終究還是在Redis的被問的第一個問題上翻船了~~

面試官 : 看你簡歷上寫了熟悉常用數據結構,都有哪些說說

本人 : 常用有5種,string,list,set,zset,hash(內心很得意)

面試官 : 那你說說都用過哪些數據結構_  

本人 : 用的最多的是string,通常會把json字符串存進去_

面試官 : 那你知道Redis內部是怎么實現它的string的么?_  

本人 : 呃~,我了解Redis是用C語言寫的,至于具體實現就不清楚了~

到此一面卒~~~

有相同經歷的朋友么?

回去后惡補了一下Redis有關原理性的知識點,恰好最近在最總結面試經歷于是有了今天這篇文章。

本篇會講以下內容:

  •  Redis字符串的實現
  •  Redis字符串的性能優勢

Redis字符串的實現

Redis雖然是用C語言寫的,但卻沒有直接用C語言的字符串,而是自己實現了一套字符串。目的就是為了提升速度,提升性能,可以看出Redis為了高性能也是煞費苦心。

Redis構建了一個叫做簡單動態字符串(Simple Dynamic String),簡稱SDS

1.SDS 代碼結構 

  1. struct sdshdr{    
  2.     //  記錄已使用長度    
  3.     int len;    
  4.     // 記錄空閑未使用的長度    
  5.     int free;    
  6.     // 字符數組    
  7.     char[] buf;    
  8. };   

SDS ?什么鬼?可能對此陌生的朋友對這個名稱有疑惑。只是個名詞而已不必在意,我們要重點欣賞借鑒Redis的設計思路。下面畫個圖來說明,一目了然。

Redis的字符串也會遵守C語言的字符串的實現規則,即最后一個字符為空字符。然而這個空字符不會被計算在len里頭。關注微信公眾號:Java技術棧,在后臺回復:redis,可以獲取我整理的 N 篇 Redis 教程,都是干貨。

2.SDS 動態擴展特點

SDS的最厲害最奇妙之處在于它的Dynamic。動態變化長度。舉個例子

如上圖所示剛開始s1 只有5個空閑位子,后面需要追加' world' 6個字符,很明顯是不夠的。那咋辦?Redis會做以下三個操作:

  1.  計算出大小是否足夠
  2.  開辟空間至滿足所需大小
  3.  開辟與已使用大小len相同長度的空閑free空間(如果len < 1M)開辟1M長度的空閑free空間(如果len >= 1M)

看到這兒為止有沒有朋友覺得這個實現跟Java的列表List實現有點類似呢?看完后面的會覺得更像了。推薦閱讀:Redis 為什么這么快?

Redis字符串的性能優勢

  • 快速獲取字符串長度
  •  避免緩沖區溢出
  •  降低空間分配次數提升內存使用效率

1.快速獲取字符串長度

再看下上面的SDS結構體: 

  1. struct sdshdr{    
  2.     //  記錄已使用長度    
  3.     int len;    
  4.     // 記錄空閑未使用的長度    
  5.     int free;    
  6.     // 字符數組    
  7.     char[] buf;    
  8. };   

由于在SDS里存了已使用字符長度len,所以當想獲取字符串長度時直接返回len即可,時間復雜度為O(1)。如果使用C語言的字符串的話它的字符串長度獲取函數時間復雜度為O(n),n為字符個數,因為他是從頭到尾(到空字符'\0')遍歷相加。

2.避免緩沖區溢出

對一個C語言字符串進行strcat追加字符串的時候需要提前開辟需要的空間,如果不開辟空間的話可能會造成緩沖區溢出,而影響程序其他代碼。如下圖,有一個字符串s1="hello" 和 字符串s2="baby",現在要執行strcat(s1,"world"),并且執行前未給s1開辟空間,所以造成了緩沖區溢出。

而對于Redis而言由于每次追加字符串時都會檢查空間是否夠用,所以不會存在緩沖區溢出問題。每次追加操作前都會做如下操作:

  1.  計算出大小是否足夠
  2.  開辟空間至滿足所需大小

3.降低空間分配次數提升內存使用效率

字符串的追加操作會涉及到內存分配問題,然而內存分配問題會牽扯內存劃分算法以及系統調用所以如果頻繁發生的話影響性能,所以對于性能至上的Redis來說這是萬萬不能忍受的。推薦:Redis 內存滿了怎么辦?

所以采取了以下兩種優化措施

  •  空間與分配
  •  惰性空間回收

1. 空間預分配

對于追加操作來說,Redis不僅會開辟空間至夠用而且還會預分配未使用的空間(free)來用于下一次操作。至于未使用的空間(free)的大小則由修改后的字符串長度決定。

當修改后的字符串長度len < 1M,則會分配與len相同長度的未使用的空間(free)

當修改后的字符串長度len >= 1M,則會分配1M長度的未使用的空間(free)

有了這個預分配策略之后會減少內存分配次數,因為分配之前會檢查已有的free空間是否夠,如果夠則不開辟了~

2. 惰性空間回收

與上面情況相反,惰性空間回收適用于字符串縮減操作。比如有個字符串s1="hello world",對s1進行sdstrim(s1," world")操作,執行完該操作之后Redis不會立即回收減少的部分,而是會分配給下一個需要內存的程序。當然,Redis也提供了回收內存的api,可以自己手動調用來回收縮減部分的內存。

到此為止結束了~

下次在遇到這個問題可以侃侃而談了,哈哈哈~ 

 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2013-08-22 10:59:00

手勢操控iOS

2023-02-26 22:33:32

字符串排列算法

2010-11-26 10:43:48

MySQL分割字符串

2011-05-25 09:58:46

C#

2015-09-17 09:25:56

Win 10開發

2021-02-18 07:45:09

redis 字符串SDS

2021-02-23 09:35:33

redis字符串數據庫

2021-04-27 10:53:58

Redis數據庫SDS

2021-02-07 21:16:04

字節跳動面試字符串

2010-09-09 11:48:00

SQL函數字符串

2010-06-17 16:00:59

SQL Server

2020-06-08 17:35:27

Redis集群互聯網

2023-02-26 00:00:02

字符串分割String

2020-12-10 11:18:47

Redis搜索引擎Java

2016-12-30 13:32:24

字符串算法代碼

2017-03-07 15:25:51

2020-09-29 06:45:49

JDK

2017-06-13 12:40:47

Python字符串對象

2009-11-30 18:46:51

PHP字符串顛倒順序

2021-03-08 08:23:24

Java字符串截取
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一级α片 | 欧美日韩高清 | 精品欧美乱码久久久久久1区2区 | 欧美jizzhd精品欧美巨大免费 | 国产精品久久久久久久久久久久久久 | 久久精品一级 | 伊人网综合 | 国产精品久久久久久久久久久新郎 | 羞羞视频网站免费看 | 一区二区影院 | 国产精品一区二区三 | 九九精品视频在线 | 久久噜噜噜精品国产亚洲综合 | 国产在线观看 | 欧美日韩在线观看视频网站 | 久久99精品久久久久久 | 成人黄色a| 亚洲精品电影网在线观看 | 精品一区二区免费视频 | 91精品国产色综合久久 | 欧美精品一区在线发布 | 日本不卡一区二区三区 | 国产精品3区 | 欧美一区二区三区在线观看 | 欧美日韩黄色一级片 | 久草网址| 二区av| 国产良家自拍 | 国产高清一区二区三区 | 91精品国产欧美一区二区 | 中文二区 | 欧美一级欧美三级在线观看 | 亚洲成人网在线播放 | 欧美日韩在线一区二区三区 | com.色.www在线观看 | 综合色在线| 成人影院一区二区三区 | 久久国产精品一区二区三区 | 在线观看欧美日韩视频 | 特黄毛片| 亚洲va在线va天堂va狼色在线 |