日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1 概述

數據結構和內部編碼

華為架構師整理Redis數據結構的大廠最佳實踐

 

無傳統關系型數據庫的 Table 模型

schema 所對應的db僅以編號區分。同一 db 內,key 作為頂層模型,它的值是扁平化的。即 db 就是key的命名空間。
key的定義通常以 : 分隔,如:Article:Count:1
常用的redis數據類型有:string、list、set、map、sorted-set

華為架構師整理Redis數據結構的大廠最佳實踐

 

redisObject通用結構

Redis中的所有value 都是以object 的形式存在的,其通用結構如下

華為架構師整理Redis數據結構的大廠最佳實踐

 

  • type 數據類型
    指 string、list 等類型
  • encoding 編碼方式
    指的是這些結構化類型具體的實現方式,同一個類型可以有多種實現。e.g. string 可以用int 來實現,也可以使用char[] 來實現;list 可以用ziplist 或者鏈表來實現
  • lru
    本對象的空轉時長,用于有限內存下長時間不訪問的對象清理
  • refcount
    對象引用計數,用于GC
  • ptr 數據指針
    指向以 encoding 方式實現這個對象實際實現者的地址。如:string 對象對應的SDS地址(string的數據結構/簡單動態字符串)

單線程

華為架構師整理Redis數據結構的大廠最佳實踐

 

單線程為何這么快?

  • 純內存
  • 非阻塞I/O
  • 避免線程切換和競態消耗
  • 一次只運行一條命令
  • 拒絕長(慢)命令
    keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collection)
  • 其實不是單線程
    fysnc file descriptorclose file descriptor

2 string

Redis中的 string 可表示很多語義

  • 字節串(bits)
  • 整數
  • 浮點數

redis會根據具體的場景完成自動轉換,并根據需要選取底層的實現方式。
例如整數可以由32-bit/64-bit、有符號/無符號承載,以適應不同場景對值域的要求。

  • 字符串鍵值結構,也能是 JSON 串或 XML 結構

內存結構

在Redis內部,string的內部以 int、SDS(簡單動態字符串 simple dynamic string)作為存儲結構

  • int 用來存放整型
  • SDS 用來存放字節/字符和浮點型SDS結構

SDS

typedef struct sdshdr {
    // buf中已經占用的字符長度
    unsigned int len;
    // buf中剩余可用的字符長度
    unsigned int free;
    // 數據空間
    char buf[];
}
  • 結構圖
    存儲的內容為“Redis”,Redis采用類似C語言的存儲方法,使用’’結尾(僅是定界符)。SDS的free 空間大小為0,當free > 0時,buf中的free 區域的引入提升了SDS對字符串的處理性能,可以減少處理過程中的內存申請和釋放次數。

buf 的擴容與縮容

當對SDS 進行操作時,如果超出了容量。SDS會對其進行擴容,觸發條件如下:

  • 字節串初始化時,buf的大小 = len + 1,即加上定界符’’剛好用完所有空間
  • 當對串的操作后小于1M時,擴容后的buf 大小 = 業務串預期長度 * 2 + 1,也就是擴大2倍。
  • 對于大小 > 1M的長串,buf總是留出 1M的 free空間,即2倍擴容,但是free最大為 1M。

字節串與字符串

SDS中存儲的內容可以是ASCII 字符串,也可以是字節串。由于SDS通過len 字段來確定業務串的長度,因此業務串可以存儲非文本內容。對于字符串的場景,buf[len] 作為業務串結尾的’’ 又可以復用C的已有字符串函數。

SDS編碼的優化

value 在內存中有2個部分:redisObject和ptr指向的字節串部分。
在創建時,通常要分別為2個部分申請內存,但是對于小字節串,可以一次性申請。

incr userid:pageview (單線程:無競爭)。緩存視頻的基本信息(數據源在MySQL)

華為架構師整理Redis數據結構的大廠最佳實踐

 

public VideoInfo get(Long id) {
	String redisKey = redisPrefix + id;
	VideoInfo videoInfo e redis.get(redisKey);
	if (videoInfo == null) {
		videoInfo = mysql.get(id);
		if (videoInfo != null) {
			// 序列化
			redis.set(redisKey serialize(videoInfo)):
		}
	}
}			
華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


除此之外,string 類型的value還有一些CAS的原子操作,如:get、set、set value nx(如果不存在就設置)、set value xx(如果存在就設置)。

String 類型是二進制安全的,也就是說在Redis中String類型可以包含各種數據,比如一張JPEG圖片或者是一個序列化的Ruby對象。一個String類型的值最大長度可以是512M。

在Redis中String有很多有趣的用法

  • 把String當做原子計數器,這可以使用INCR家族中的命令來實現:INCR, DECR, INCRBY。
  • 使用AppEND命令來給一個String追加內容。
  • 把String當做一個隨機訪問的向量(Vector),這可以使用GETRANGE和 SETRANGE命令來實現
  • 使用GETBIT 和SETBIT方法,在一個很小的空間中編碼大量的數據,或者創建一個基于Redis的Bloom Filter 算法。

List

可從頭部(左側)加入元素,也可以從尾部(右側)加入元素。有序列表。

像微博粉絲,即可以list存儲做緩存。

key = 某大v

value = [zhangsan, lisi, wangwu]

所以可存儲一些list型的數據結構,如:

  • 粉絲列表
  • 文章的評論列表

可通過lrange命令,即從某元素開始讀取多少元素,可基于list實現分頁查詢,這就是基于redis實現簡單的高性能分頁,可以做類似微博那種下拉不斷分頁的東西,性能高,就一頁一頁走。

搞個簡單的消息隊列,從list頭推進去,從list尾拉出來。

List類型中存儲一系列String值,這些String按照插入順序排序。

5.1 內存數據結構

List 類型的 value對象,由 linkedlist 或 ziplist 實現。
當 List 元素個數少并且元素內容長度不大采用ziplist 實現,否則使用linkedlist

5.1.1 linkedlist實現

鏈表的代碼結構

typedef struct list {
  // 頭結點
  listNode *head;
  // 尾節點
  listNode *tail;
  // 節點值復制函數
  void *(*dup)(void * ptr);
  // 節點值釋放函數
  void *(*free)(void *ptr);
  // 節點值對比函數
  int (*match)(void *ptr, void *key);
  // 鏈表長度
  unsigned long len;  
} list;

// Node節點結構
typedef struct listNode {
	struct listNode *prev;
	struct listNode *next;
	void *value;
} listNode;

linkedlist 結構圖

華為架構師整理Redis數據結構的大廠最佳實踐

 

5.1.2 ziplist實現

存儲在連續內存

華為架構師整理Redis數據結構的大廠最佳實踐

 

  • zlbytes
    ziplist 的總長度
  • zltail
    指向最末元素。
  • zllen
    元素的個數。
  • entry
    元素內容。
  • zlend
    恒為0xFF,作為ziplist的定界符

linkedlist和ziplist的rpush、rpop、llen的時間復雜度都是O(1):

  • ziplist的lpush、lpop都會牽扯到所有數據的移動,時間復雜度為O(N)
    由于List的元素少,體積小,這種情況還是可控的。

ziplist的Entry結構:

華為架構師整理Redis數據結構的大廠最佳實踐

 


記錄前一個相鄰的Entry的長度,便于雙向遍歷,類似linkedlist的prev指針。
ziplist是連續存儲,指針由偏移量來承載。
Redis中實現了2種方式實現:

  • 當前鄰 Entry的長度小于254 時,使用1字節實現
  • 否則使用5個字節

當前一個Entry長度變化時,可能導致后續的所有空間移動,雖然這種情況發生可能性較小。

Entry內容本身是自描述的,意味著第二部分(Entry內容)包含了幾個信息:Entry內容類型、長度和內容本身。而內容本身包含:類型長度部分和內容本身部分。類型和長度同樣采用變長編碼:

  • 00xxxxxx :string類型;長度小于64,0~63可由6位bit 表示,即xxxxxx表示長度
  • 01xxxxxx|yyyyyyyy : string類型;長度范圍是[64, 16383],可由14位 bit 表示,即xxxxxxyyyyyyyy這14位表示長度。
  • 10xxxxxx|yy…y(32個y) : string類型,長度大于16383.
  • 1111xxxx :integer類型,integer本身內容存儲在xxxx 中,只能是1~13之間取值。也就是說內容類型已經包含了內容本身。
  • 11xxxxxx :其余的情況,Redis用1個字節的類型長度表示了integer的其他幾種情況,如:int_32、int_24等。
    由此可見,ziplist 的元素結構采用的是可變長的壓縮方法,針對于較小的整數/字符串的壓縮效果較好
  • LPUSH命令
    在頭部加入一個新元素
  • RPUSH命令
    在尾部加入一個新元素

當在一個空的K執行這些操作時,會創建一個新列表。當一個操作清空了一個list時,該list對應的key會被刪除。若使用一個不存在的K,就會使用一個空list。

LPUSH mylist a   # 現在list是 "a"
LPUSH mylist b   # 現在list是"b","a"
RPUSH mylist c   # 現在list是 "b","a","c" (注意這次使用的是 RPUSH)

list的最大長度是2^32 – 1個元素(4294967295,一個list中可以有多達40多億個元素)。

從時間復雜度的角度來看,Redis list類型的最大特性是:即使是在list的頭端或者尾端做百萬次的插入和刪除操作,也能保持穩定的很少的時間消耗。在list的兩端訪問元素是非常快的,但是如果要訪問一個很大的list中的中間部分的元素就會比較慢了,時間復雜度是O(N)

適用場景

  • 社交中使用List進行時間表建模,使用 LPUSH 在用戶時間線中加入新元素,然后使用 LRANGE 獲得最近加入元素
  • 可以把[LPUSH] 和[LTRIM] 命令結合使用來實現定長的列表,列表中只保存最近的N個元素
  • 做MQ,依賴BLPOP這種阻塞命令

Set

類似List,但無序且其元素不重復。

向集合中添加多次相同的元素,集合中只存在一個該元素。在實際應用中,這意味著在添加一個元素前不需要先檢查元素是否存在。

支持多個服務器端命令來從現有集合開始計算集合,所以執行集合的交集,并集,差集都很快。

set的最大長度是2^32 – 1個元素(一個set中可多達40多億個元素)。

內存數據結構

Set在Redis中以intset 或 hashtable存儲:

  • 對于Set,HashTable的value永遠為NULL
  • 當Set中只包含整型數據時,采用intset作為實現

intset

核心元素是一個字節數組,從小到大有序的存放元素

華為架構師整理Redis數據結構的大廠最佳實踐

 


結構圖

華為架構師整理Redis數據結構的大廠最佳實踐

 


因為元素有序排列,所以SET的獲取操作采用二分查找,復雜度為O(log(N))。

進行插入操作時:

  • 首先通過二分查找到要插入位置
  • 再對元素進行擴容
  • 然后將插入位置之后的所有元素向后移動一個位置
  • 最后插入元素

時間復雜度為O(N)。為使二分查找的速度足夠快,存儲在content 中的元素是定長的。

華為架構師整理Redis數據結構的大廠最佳實踐

 


當插入2018 時,所有的元素向后移動,并且不會發生覆蓋。
當Set 中存放的整型元素集中在小整數范圍[-128, 127]內時,可大大的節省內存空間。
IntSet支持升級,但是不支持降級。

  • Set 基本操作

適用場景

無序集合,自動去重,數據太多時不太推薦使用。
直接基于set將系統里需要去重的數據扔進去,自動就給去重了,如果你需要對一些數據進行快速的全局去重,你當然也可以基于JVM內存里的HashSet進行去重,但若你的某個系統部署在多臺機器呢?就需要基于redis進行全局的set去重。

可基于set玩交集、并集、差集操作,比如交集:

  • 把兩個人的粉絲列表整一個交集,看看倆人的共同好友
  • 把兩個大v的粉絲都放在兩個set中,對兩個set做交集

全局這種計算開銷也大。

  • 記錄唯一的事物
    比如想知道訪問某個博客的IP地址,不要重復的IP,這種情況只需要在每次處理一個請求時簡單的使用SADD命令就可以了,可確保不會插入重復IP
  • 表示關系
    你可以使用Redis創建一個標簽系統,每個標簽使用一個Set表示。然后你可以使用SADD命令把具有特定標簽的所有對象的所有ID放在表示這個標簽的Set中如果你想要知道同時擁有三個不同標簽的對象,那么使用SINTER
  • 可使用SPOP 或 SRANDMEMBER 命令從集合中隨機的提取元素。

Hash/Map

一般可將結構化的數據,比如一個對象(前提是這個對象未嵌套其他的對象)給緩存在redis里,然后每次讀寫緩存的時候,即可直接操作hash里的某個字段。

key=150

value={
  “id”: 150,
  “name”: “zhangsan”,
  “age”: 20
}

hash類的數據結構,主要存放一些對象,把一些簡單的對象給緩存起來,后續操作的時候,可直接僅修改該對象中的某字段的值。

value={
  “id”: 150,
  “name”: “zhangsan”,
  “age”: 21
}

因為Redis本身是一個K.V存儲結構,Hash結構可理解為subkey - subvalue
這里面的subkey - subvalue只能是

  • 整型
  • 浮點型
  • 字符串

因為Map的 value 可表示整型和浮點型,因此Map也可以使用hincrby 對某個field的value值做自增操作。

內存數據結構

hash有HashTable 和 ziplist 兩種實現。對于數據量較小的hash,使用ziplist 實現。

HashTable 實現

HashTable在Redis 中分為3 層,自底向上分別是:

  • dictEntry:管理一個field - value 對,保留同一桶中相鄰元素的指針,以此維護Hash 桶中的內部鏈
  • dictht:維護Hash表的所有桶鏈
  • dict:當dictht需要擴容/縮容時,用戶管理dictht的遷移

dict是Hash表存儲的頂層結構

// 哈希表(字典)數據結構,Redis 的所有鍵值對都會存儲在這里。其中包含兩個哈希表。
typedef struct dict {
    // 哈希表的類型,包括哈希函數,比較函數,鍵值的內存釋放函數
    dictType *type;
    // 存儲一些額外的數據
    void *privdata;
    // 兩個哈希表
    dictht ht[2];
    // 哈希表重置下標,指定的是哈希數組的數組下標
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */
    // 綁定到哈希表的迭代器個數
    int iterators; /* number of iterators currently running */
} dict;

Hash表的核心結構是dictht,它的table 字段維護著 Hash 桶,桶(bucket)是一個數組,數組的元素指向桶中的第一個元素(dictEntry)。

typedef struct dictht { 
    //槽位數組
    dictEntry **table; 
    //槽位數組長度
    unsigned long size; 
    //用于計算索引的掩碼 
    unsigned long sizemask;
    //真正存儲的鍵值對數量
    unsigned long used; 
} dictht;

結構圖

華為架構師整理Redis數據結構的大廠最佳實踐

 


Hash表使用【鏈地址法】解決Hash沖突。當一個 bucket 中的 Entry 很多時,Hash表的插入性能會下降,此時就需要增加bucket的個數來減少Hash沖突。

Hash表擴容

和大多數Hash表實現一樣,Redis引入負載因子判定是否需要增加bucket個數:

負載因子 = Hash表中已有元素 / bucket數量

擴容后,bucket 數量是原先2倍。目前有2 個閥值:

  • 小于1 時一定不擴容
  • 大于5 時一定擴容
  • 在1 ~ 5 之間時,Redis 如果沒有進行bgsave/bdrewrite 操作時則會擴容
  • 當key - value 對減少時,低于0.1時會進行縮容。縮容之后,bucket的個數是原先的0.5倍

ziplist 實現

這里的 ziplist 和List#ziplist的實現類似,都是通過Entry 存放元素。
不同的是,Map#ziplist的Entry個數總是2的整數倍:

  • 第奇數個Entry存放key
  • 下個相鄰Entry存放value

ziplist承載時,Map的大多數操作不再是O(1)了,而是由Hash表遍歷,變成了鏈表的遍歷,復雜度變為O(N)
由于Map相對較小時采用ziplist,采用Hash表時計算hash值的開銷較大,因此綜合起來ziplist的性能相對好一些

哈希鍵值結構

華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


特點:

  • Map的map
  • Small redis
  • field不能相同,value可相同
hget key field O(1)
# 獲取 hash key 對應的 field 的 value

hset key field value O(1)
#  設置 hash key 對應的 field 的 value

hdel key field O(1)
# 刪除 hash key 對應的 field 的 value

實操

127.0.0.1:6379> hset user:1:info age 23
(integer) 1
127.0.0.1:6379> hget user:1:info age
"23"
127.0.0.1:6379> hset user:1:info name JAVAEdge
(integer) 1
127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "23"
3) "name"
4) "JavaEdge"
127.0.0.1:6379> hdel user:1:info age
(integer) 1
127.0.0.1:6379> hgetall user:1:info
1) "name"
2) "JavaEdge"
hexists key field O(1)
# 判斷hash key是否有field
hlen key O(1)
# 獲取hash key field的數量
127.0.0.1:6379> hgetall user:1:info
1) "name"
2) "JavaEdge"
127.0.0.1:6379> HEXISTS user:1:info name
(integer) 1
127.0.0.1:6379> HLEN user:1:info
(integer) 1
hmget key field1 field2... fieldN O(N)
# 批量獲取 hash key 的一批 field 對應的值
hmset key field1 value1 field2 value2...fieldN valueN O(N)
# 批量設置 hash key的一批field value

華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


華為架構師整理Redis數據結構的大廠最佳實踐

 


Redis Hashes 保存String域和String值之間的映射,所以它們是用來表示對象的絕佳數據類型(比如一個有著用戶名,密碼等屬性的User對象)

| `1` | `@cli` |

| `2` | `HMSET user:1000 username antirez password P1pp0 age 34` |

| `3` | `HGETALL user:1000` |

| `4` | `HSET user:1000 password 12345` |

| `5` | `HGETALL user:1000` |

一個有著少量數據域(這里的少量大概100上下)的hash,其存儲方式占用很小的空間,所以在一個小的Redis實例中就可以存儲上百萬的這種對象

Hash的最大長度是2^32 – 1個域值對(4294967295,一個Hash中可以有多達40多億個域值對)

Sorted sets(zset)

有序集合,去重但可排序,寫進去時候給個分數,可以自定義排序規則。比如想根據時間排序,則寫時可以使用時間戳作為分數。

排行榜:將每個用戶以及其對應的什么分數寫進去。

127.0.0.1:6379> zadd board 1.0 JavaEdge
(integer) 1

獲取排名前100的用戶:

127.0.0.1:6379> zrevrange board 0 99
1) "JavaEdge"

用戶在排行榜里的排名:

127.0.0.1:6379> zrank board JavaEdge
(integer) 0
127.0.0.1:6379> zadd board 85 zhangsan
(integer) 1
127.0.0.1:6379> zadd board 72 wangwu
(integer) 1
127.0.0.1:6379> zadd board 96 lisi
(integer) 1
127.0.0.1:6379> zadd board 62 zhaoliu
(integer) 1

# 獲取排名前3的用戶
127.0.0.1:6379> zrevrange board 0 3
1) "lisi"
2) "zhangsan"
3) "wangwu"
4) "zhaoliu"

127.0.0.1:6379> zrank board zhaoliu
(integer) 1

類似于Map的key-value對,但有序

  • key :key-value對中的鍵,在一個Sorted-Set中不重復
  • value : 浮點數,稱為 score
  • 有序 :內部按照score 從小到大的順序排列

基本操作

由于Sorted-Set 本身包含排序信息,在普通Set 的基礎上,Sorted-Set 新增了一系列和排序相關的操作:

  • Sorted-Set的基本操作

內部數據結構

Sorted-Set類型的valueObject 內部結構有兩種:

  1. ziplist
    實現方式和Map類似,由于Sorted-Set包含了Score的排序信息,ziplist內部的key-value元素對的排序方式也是按照Score遞增排序的,意味著每次插入數據都要移動之后的數據,因此ziplist適于元素個數不多,元素內容不大的場景。
  2. skiplist+hashtable
    更通用的場景,Sorted-Set使用sliplist來實現。

8.2.1 zskiplist

和通用的跳表不同的是,Redis為每個level 對象增加了span 字段,表示該level 指向的forward節點和當前節點的距離,使得getByRank類的操作效率提升

  • 數據結構
  • 結構示意圖

每次向skiplist 中新增或者刪除一個節點時,需要同時修改圖標中紅色的箭頭,修改其forward和span的值。

需要修改的箭頭和對skip進行查找操作遍歷并廢棄過的路徑是吻合的。span修改僅是+1或-1。
zskiplist 的查找平均時間復雜度 O(Log(N)),因此add / remove的復雜度也是O(Log(N))。因此Redis中新增的span 提升了獲取rank(排序)操作的性能,僅需對遍歷路徑相加即可(矢量相加)。

還有一點需要注意的是,每個skiplist的節點level 大小都是隨機生成的(1-32之間)。

  • zskiplistNode源碼

8.2.2 hashtable

zskiplist 是zset 實現順序相關操作比較高效的數據結構,但是對于簡單的zscore操作效率并不高。Redis在實現時,同時使用了Hashtable和skiplist,代碼結構如下:

華為架構師整理Redis數據結構的大廠最佳實踐

 


Hash表的存在使得Sorted-Set中的Map相關操作復雜度由O(N)變為O(1)。

Redis有序集合類型與Redis的集合類型類似,是非重復的String元素的集合。不同之處在于,有序集合中的每個成員都關聯一個Score,Score是在排序時候使用的,按照Score的值從小到大進行排序。集合中每個元素是唯一的,但Score有可能重復。

使用有序集合可以很高效的進行,添加,移除,更新元素的操作(時間消耗與元素個數的對數成比例)。由于元素在集合中的位置是有序的,使用get ranges by score或者by rank(位置)來順序獲取或者隨機讀取效率都很高。(本句不確定,未完全理解原文意思,是根據自己對Redis的淺顯理解進行的翻譯)訪問有序集合中間部分的元素也非常快,所以可以把有序集合當做一個不允許重復元素的智能列表,你可以快速訪問需要的一切:獲取有序元素,快速存在測試,快速訪問中間的元素等等。

簡短來說,使用有序集合可以實現很多高性能的工作,這一點在其他數據庫是很難實現的。

應用

  • 在大型在線游戲中創建一個排行榜,每次有新的成績提交,使用[ZADD]命令加入到有序集合中。可以使用[ZRANGE]命令輕松獲得成績名列前茅的玩家,你也可以使用[ZRANK]根據一個用戶名獲得該用戶的分數排名。把ZRANK 和 ZRANGE結合使用你可以獲得與某個指定用戶分數接近的其他用戶。這些操作都很高效。
  • 有序集合經常被用來索引存儲在Redis中的數據。比如,如果你有很多用戶,用Hash來表示,可以使用有序集合來為這些用戶創建索引,使用年齡作為Score,使用用戶的ID作為Value,這樣的話使用[ZRANGEBYSCORE]命令可以輕松和快速的獲得某一年齡段的用戶。zset有個ZSCORE的操作,用于返回單個集合member的分數,它的操作復雜度是O(1),這就是收益于你這看到的hash table。這個hash table保存了集合元素和相應的分數,所以做ZSCORE操作時,直接查這個表就可以,復雜度就降為O(1)了。

而跳表主要服務范圍操作,提供O(logN)的復雜度。

Bitmaps

位圖類型,String類型上的一組面向bit操作的集合。由于 strings是二進制安全的blob,并且它們的最大長度是512m,所以bitmaps能最大設置 2^32個不同的bit。

HyperLogLogs

pfadd/pfcount/pfmerge。
在redis的實現中,使用標準錯誤小于1%的估計度量結束。這個算法的神奇在于不再需要與需要統計的項相對應的內存,取而代之,使用的內存一直恒定不變。最壞的情況下只需要12k,就可以計算接近2^64個不同元素的基數。

GEO


geoadd/geohash/geopos/geodist/georadius/georadiusbymember
Redis的GEO特性在 Redis3.2版本中推出,這個功能可以將用戶給定的地理位置(經、緯度)信息儲存起來,并對這些信息進行操作。

分享到:
標簽:Redis
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定