詳解Redis核心數據結構和高性能原理分析(一)


一、Redis介紹

1、Redis是什麼

Remote Dictionary Server(Redis)是一個開源的使用 ANSI C 語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value 數據庫,並提供多種語言的 API。
它通常被稱爲數據結構服務器,因爲值(value)可以是 字符串(String), 哈希(Map),列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。

2、Redis的優缺點

  1. 支持多種數據結構,如 string(字符串)、 list(雙向鏈表)、dict(hash 表)、set(集合)、
    zset(排序 set)、hyperloglog(基數估算)
  2. 支持持久化操作,可以進行 aof 及 rdb 數據持久化到磁盤,從而進行數據備份或數
    據恢復等操作,較好的防止數據丟失的手段。
  3. 支持通過 Replication 進行數據複製,通過 master-slave 機制,可以實時進行數據的
    同步複製,支持多級複製和增量複製,master-slave 機制是 Redis 進行 HA 的重要手段。
  4. 單進程請求,所有命令串行執行,併發情況下不需要考慮數據一致性問題。

二、Redis的安裝(若需要docker版,請看我其他文章)

redis安裝

三、Redis 數據類型

總圖:
redis基本類型

1、string(字符串)

1.1、定義

Redis 字符串是字節序列。Redis 字符串是二進制安全的,這意味着他們有一個已知的
長度沒有任何特殊字符終止,所以你可以存儲任何東西,512 兆爲上限

1.2、常用命令

字符串常用操作
	SET  key  value 					//存入字符串鍵值對
	MSET  key  value [key value ...] 	//批量存儲字符串鍵值對
	SETNX  key  value 					//存入一個不存在的字符串鍵值對
	GET  key 							//獲取一個字符串鍵值
	MGET  key  [key ...]	 			//批量獲取字符串鍵值
	DEL  key  [key ...] 				//刪除一個鍵
	EXPIRE  key  seconds 				//設置一個鍵的過期時間(秒)
	原子加減
	INCR  key 							//將key中儲存的數字值加1
	DECR  key 							//將key中儲存的數字值減1
	INCRBY  key  increment 				//將key所儲存的值加上increment
	DECRBY  key  decrement 				//將key所儲存的值減去decrement

1.3、應用場景

1、單值緩存
	SET  key  value 	
	GET  key
2、分佈式鎖
	SETNX  product:10001  true 					//返回1代表獲取鎖成功
	SETNX  product:10001  true 					//返回0代表獲取鎖失敗
	。。。執行業務操作
	DEL  product:10001							//執行完業務釋放鎖
	SET product:10001 true  ex  10  nx			//防止程序意外終止導致死鎖
3、計數器
	INCR article:readcount:{
   
    文章id}  	
	GET article:readcount:{
   
    文章id} 
4、Web集羣session共享
	spring session + redis實現session共享
5、分佈式系統全局序列號	
	INCRBY  orderId  1000						//redis批量生成序列號提升性能
6、對象緩存
	1) SET  user:1  value(json格式數據)
	2) MSET  user:1:name  zhz   user:1:balance  1888
    	MGET  user:1:name   user:1:balance 

2、list(鏈表)

2.1、定義

Redis 的鏈表是簡單的字符串列表,排序插入順序。您可以添加元素到 Redis 的列表的
頭部或尾部。
在這裏插入圖片描述

2.2、常用命令

1、List常用操作
	LPUSH  key  value [value ...] 		//將一個或多個值value插入到key列表的表頭(最左邊)
	RPUSH  key  value [value ...]	 	//將一個或多個值value插入到key列表的表尾(最右邊)
	LPOP  key							//移除並返回key列表的頭元素
	RPOP  key							//移除並返回key列表的尾元素
	LRANGE  key  start  stop			//返回列表key中指定區間內的元素,區間以偏移量start和stop指定
	
	BLPOP  key  [key ...]  timeout		//從key列表表頭彈出一個元素,若列表中沒有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
	BRPOP  key  [key ...]  timeout 		//從key列表表尾彈出一個元素,若列表中沒有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待

2.1、應用場景

1、常用數據結構
	Stack() = LPUSH + LPOP
	Queue(隊列)= LPUSH + RPOP
	Blocking MQ(阻塞隊列)= LPUSH + BRPOP
2、微博和微信公號消息流
3、微博消息和微信公號消息
	/**
	* 事例
	**/
	A關注了MacTalk,備胎說車等大V
	1)MacTalk發微博,消息ID爲10018
	LPUSH  msg:{
   
    A-ID}  10018
	2)備胎說車發微博,消息ID爲10086
	LPUSH  msg:{
   
    A-ID} 10086
	3)查看最新微博消息
	LRANGE  msg:{
   
    A-ID}  0  4

3、 Hash(hash表)

3.1、定義

Redis 的哈希是鍵值對的集合。 Redis 的哈希值是字符串字段和字符串值之間的映射,
因此它們被用來表示對象。
在這裏插入圖片描述

3.2、常用命令

Hash常用操作
	HSET  key  field  value 					//存儲一個哈希表key的鍵值
	HSETNX  key  field  value 					//存儲一個不存在的哈希表key的鍵值
	HMSET  key  field  value [field value ...] 	//在一個哈希表key中存儲多個鍵值對
	HGET  key  field 							//獲取哈希表key對應的field鍵值
	HMGET  key  field  [field ...] 				//批量獲取哈希表key中多個field鍵值
	HDEL  key  field  [field ...] 				//刪除哈希表key中的field鍵值
	HLEN  key									//返回哈希表key中field的數量
	HGETALL  key								//返回哈希表key中所有的鍵值
	HINCRBY  key  field  increment 				//爲哈希表key中field鍵的值加上增量increment

3.3、應用場景

對象緩存
	HMSET  user  {
   
    userId}:name  zhz  {
   
    userId}:balance  1888
	HMSET  user  1:name  zhz1:balance  1888
	HMGET  user  1:name  1:balance 
電商購物車
	1)以用戶id爲key
	2)商品id爲field
	3)商品數量爲value
購物車操作
	添加商品->hset cart:1001 10088 1
	增加數量->hincrby cart:1001 10088 1
	商品總數->hlen cart:1001
	刪除商品->hdel cart:1001 10088
	獲取購物車所有商品->hgetall cart:1001

3.4、優缺點

  • 優點
    1)同類數據歸類整合儲存,方便數據管理
    2)相比string操作消耗內存與cpu更小
    3)相比string儲存更節省空間


  • 缺點
    過期功能不能使用在field上,只能用在key上
    Redis集羣架構下不適合大規模使用

4、set(集合)

4.1、定義

Redis 的集合是字符串的無序集合。
在這裏插入圖片描述

4.2、常用命令

1、Set常用操作
	SADD  key  member  [member ...]				//往集合key中存入元素,元素存在則忽略,若key不存在則新建
	SREM  key  member  [member ...]				//從集合key中刪除元素
	SMEMBERS  key								//獲取集合key中所有元素
	SCARD  key									//獲取集合key的元素個數
	SISMEMBER  key  member						//判斷member元素是否存在於集合key中
	SRANDMEMBER  key  [count]					//從集合key中選出count個元素,元素不從key中刪除
	SPOP  key  [count]							//從集合key中選出count個元素,元素從key中刪除

2、Set運算操作
	SINTER  key  [key ...] 						//交集運算
	SINTERSTORE  destination  key  [key ..]		//將交集結果存入新集合destination中
	SUNION  key  [key ..] 						//並集運算
	SUNIONSTORE  destination  key  [key ...]	//將並集結果存入新集合destination中
	SDIFF  key  [key ...] 						//差集運算
	SDIFFSTORE  destination  key  [key ...]		//將差集結果存入新集合destination中

4.3、應用場景

1、微信抽獎小程序
	1)點擊參與抽獎加入集合
	SADD key {
   
    userlD}
	2)查看參與抽獎所有用戶
	SMEMBERS key	  
	3)抽取count名中獎者
	SRANDMEMBER key [count] / SPOP key [count]
2、微信微博點贊,收藏,標籤
	1) 點贊
	SADD  like:{
   
    消息ID}  {
   
    用戶ID}
	2) 取消點贊
	SREM like:{
   
    消息ID}  {
   
    用戶ID}
	3) 檢查用戶是否點過贊
	SISMEMBER  like:{
   
    消息ID}  {
   
    用戶ID}
	4) 獲取點讚的用戶列表
	SMEMBERS like:{
   
    消息ID}
	5) 獲取點贊用戶數 
	SCARD like:{
   
    消息ID}
3、集合操作
	SINTER set1 set2 set3 -> {
   
     c }
	SUNION set1 set2 set3 -> {
   
     a,b,c,d,e }
	SDIFF set1 set2 set3  -> {
   
     a }
4、集合操作實現微博微信關注模型
	1) A關注的人: 
	ASet-> {
   
    B, C}
	2) D老師關注的人:
	 DSet--> {
   
    A, E, B, C}
	3) B老師關注的人: 
	BSet-> {
   
    A, D, E, C, F)
	4) 我A和D老師共同關注: 
	SINTER ASet DSet--> {
   
    B, C}
	5) 我A關注的人也關注他(D老師): 
	SISMEMBER BSet D
	SISMEMBER CSet D
	6) 我可能認識的人: 
	SDIFF DSet ASet->(A, E}
5、集合操作實現電商商品篩選
	SADD  brand:huawei  P40
	SADD  brand:xiaomi  mi-10
	SADD  brand:iPhone iphone12
	SADD os:android  P40  mi-10
	SADD cpu:brand:intel  P40  mi-10
	SADD ram:8G  P40  mi-10  iphone12
	SINTER  os:android  cpu:brand:intel  ram:8G ->  {
   
    P40,mi-10}

5、zset(sorted set->有序集合)

5.1、定義

Redis 的有序集合類似於 Redis 的集合,字符串不重複的集合。

5.2、常用命令

ZSet常用操作
	ZADD key score member [[score member]]		//往有序集合key中加入帶分值元素
	ZREM key member [member …]					//從有序集合key中刪除元素
	ZSCORE key member 							//返回有序集合key中元素member的分值
	ZINCRBY key increment member				//爲有序集合key中元素member的分值加上increment 
	ZCARD key									//返回有序集合key中元素個數
	ZRANGE key start stop [WITHSCORES]			//正序獲取有序集合key從start下標到stop下標的元素
	ZREVRANGE key start stop [WITHSCORES]		//倒序獲取有序集合key從start下標到stop下標的元素
Zset集合操作
	ZUNIONSTORE destkey numkeys key [key ...] 	//並集計算
	ZINTERSTORE destkey numkeys key [key …]		//交集計算

5.3、應用場景

Zset集合操作實現排行榜
	1)點擊新聞
	ZINCRBY  hotNews:20190819  1  守護香港
	2)展示當日排行前十
	ZREVRANGE  hotNews:20190819  0  9  WITHSCORES 
	3)七日搜索榜單計算
	ZUNIONSTORE  hotNews:20190813-20190819  7 
	hotNews:20190813  hotNews:20190814... hotNews:20190819
	4)展示七日排行前十
	ZREVRANGE hotNews:20190813-20190819  0  9  WITHSCORES

6、其他高級命令

1、keys:
	全量遍歷鍵, 用來列出所有滿足特定正則字符串規則的key,當redis數據量比較大時,性能比較差,要避免使用

2、SCAN cursor [MATCH pattern] [COUNT count]
	scan 參數提供了三個參數,第一個是 cursor 整數值(hash桶的索引值),第二個是 key 的正則模式,
	第三個是一次遍歷的key的數量(參考值,底層遍歷的數量不一定),並不是符合條件的結果數量。第
	一次遍歷時,cursor 值爲 0,然後將返回結果中第一個整數值作爲下一次遍歷的 cursor。一直遍歷
	到返回的 cursor 值爲 0 時結束。
	注意:但是scan並非完美無瑕, 如果在scan的過程中如果有鍵的變化(增加、 刪除、 修改) ,那
	麼遍歷效果可能會碰到如下問題: 新增的鍵可能沒有遍歷到, 遍歷出了重複的鍵等情況, 也就是說
	scan並不能保證完整的遍歷出來所有的鍵,開發市需要考慮
3、Info:
	查看redis服務運行信息,分爲 9 大塊,每個塊都有非常多的參數,這 9 個塊分別是:
4、Server 
	服務器運行的環境參數
5、Clients 
	客戶端相關信息
6、Memory 
	服務器運行內存統計數據
7、Persistence 
	持久化信息
8、Stats 
	通用統計數據
9、Replication 
	主從複製相關信息
10、CPU CPU 
	使用情況
11、Cluster 
	集羣信息
12、KeySpace 
	鍵值對統計數量信息

四、基本數據結構總結

在這裏插入圖片描述

五、Redis的單線程和高性能

1、Redis是單線程嗎?

Redis 的單線程主要是指 Redis 的網絡 IO 和鍵值對讀寫是由一個線程來完成的,這也是 Redis 對外提供鍵值存儲服務的主要流程。但 Redis 的其他功能,比如持久化、異步刪除、集羣數據同步等,其實是由額外的線程執行的。

2、Redis 單線程爲什麼還能這麼快?

  • 它所有的數據都在內存中,所有的運算都是內存級別的運算,而且單線程避免了多線程的切換性能損耗問題。因爲 Redis 是單線程,所以要小心使用 Redis 指令,對於那些耗時的指令(比如
    keys),一定要謹慎使用,一不小心就可能會導致 Redis 卡頓。
  • Redis完全基於內存,絕大部分請求是純粹的內存操作,非常迅速,數據存在內存中。
  • 數據結構簡單,對數據操作也簡單。
  • 採用單線程,避免了不必要的上下文切換和競爭條件,不存在多線程導致的CPU切換,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有死鎖問題導致的性能消耗。
  • 使用多路複用IO模型,非阻塞IO。

3、Redis 單線程如何處理那麼多的併發客戶端連接?

Redis的IO多路複用:redis利用epoll來實現IO多路複用,將連接信息和事件放到隊列中,依次放到
文件事件分派器,事件分派器將事件分發給事件處理器。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章