[TOC]
## redis的使用場景
(1)緩存
毫無疑問這是Redis當今最為人熟知的使用場景。再提升服務器性能方面非常有效;
一些頻繁被訪問的數據,經常被訪問的數據如果放在關系型數據庫,每次查詢的開銷都會很大,而放在redis中,因為redis 是放在內存中的可以很高效的訪問。
(2)排行榜
在使用傳統的關系型數據庫(mysql oracle 等)來做這個事兒,非常的麻煩,而利用Redis的SortSet(有序集合)數據結構能夠簡單的搞定;
(3)計算器/限速器
Redis中原子性的自增操作,我們可以統計類似用戶點贊數、用戶訪問數等,這類操作如果用MySQL,頻繁的讀寫會帶來相當大的壓力;限速器比較典型的使用場景是限制某個用戶訪問某個API的頻率,常用的有搶購時,防止用戶瘋狂點擊帶來不必要的壓力;
(4)好友關系
利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同愛好之類的功能。
(5)簡單消息隊列
除了Redis自身的發布/訂閱模式,我們也可以利用List來實現一個隊列機制,比如:到貨通知、郵件發送之類的需求,不需要高可靠,但是會帶來非常大的DB壓力,完全可以用List來完成異步解耦;
(6)Session共享
以PHP為例,默認Session是保存在服務器的文件中,如果是集群服務,同一個用戶過來可能落在不同機器上,這就會導致用戶頻繁登陸;采用Redis保存Session后,無論用戶落在那臺機器上都能夠獲取到對應的Session信息。
(7)分布式鎖
分布式場景下,無法使用單機環境下的鎖來對多個節點上的進程進行同步。可以使用 Redis 自帶的 SETNX 命令實現分布式鎖,除此之外,還可以使用官方提供的 RedLock 分布式鎖實現。
鏈接地址:https://mp.weixin.qq.com/s/r9_0xpRsp2ubgyvpiyMfuw
## String
### 常規計數

### 分布式鎖
SET?lock\_key?unique\_value?NX?PX?10000
還是不安全
## List
### 常用命令

### 應用場景
#### 消息隊列
List 可以使用 LPUSH + RPOP (或者反過來,RPUSH+LPOP)命令實現消息隊列。
* 生產者使用`LPUSH key value[value...]`將消息插入到隊列的頭部,如果 key 不存在則會創建一個空的隊列再插入消息。
* 消費者使用`RPOP key`依次讀取隊列的消息,先進先出。
建議使用BRPOP ,**BRPOP命令也稱為阻塞式讀取,客戶端在沒有讀到隊列數據時,自動阻塞,直到有新的數據寫入隊列,再開始讀取新數據**。和消費者程序自己不停地調用RPOP命令相比,這種方式能節省CPU開銷。
* 消息保序:使用 LPUSH + RPOP;
* 阻塞讀取:使用 BRPOP;
* 重復消息處理:生產者自行實現全局唯一 ID;(eg:LPUSH?mq?"111000102:stock:99")
* 消息的可靠性:使用 BRPOPLPUSH(讀出來之后放到另一個list,作為備份)
缺點:不能多消費者,在redis5.0 之后增加了stream ,可以使用消費者組,進行消費
## Hash
### 常用命令

### 應用場景
#### 緩存對象
1、hset key feild value,可以單獨取出key的某項信息去操作

#### 購物車

涉及的命令如下:
* 添加商品:`HSET cart:{用戶id} {商品id} 1`
* 添加數量:`HINCRBY cart:{用戶id} {商品id} 1`
* 商品總數:`HLEN cart:{用戶id}`
* 刪除商品:`HDEL cart:{用戶id} {商品id}`
* 獲取購物車所有商品:`HGETALL cart:{用戶id}`
當前僅僅是將商品ID存儲到了Redis 中,在回顯商品具體信息的時候,還需要拿著商品 id 查詢一次數據庫,獲取完整的商品的信息。
## Set
### 常用命令
Set常用操作:

Set運算操作:

### 應用場景
集合的主要幾個特性,無序、不可重復、支持并交差等操作。
**Set 的差集、并集和交集的計算復雜度較高,在數據量較大的情況下,如果直接執行這些計算,會導致 Redis 實例阻塞**。
#### 點贊
```
//uid:1?用戶對文章?article:1?點贊
SADD?article:1?uid:1
//uid:1`取消了對 article:1 文章點贊。
SREM?article:1?uid:1
//獲取 ?article:1 文章所有點贊用戶
?SMEMBERS?article:1
//獲取 article:1 文章的點贊用戶數量:
SCARD?article:1
//判斷用戶`uid:1`是否對文章 article:1 點贊了:
SISMEMBER?article:1?uid:1
```
#### 關注
Set 類型支持交集運算,所以可以用來計算共同關注的好友、公眾號等。
key 可以是用戶id,value 則是已關注的公眾號的id。
`uid:1`用戶關注公眾號 id 為 5、6、7、8、9,`uid:2`?用戶關注公眾號 id 為 7、8、9、10、11。


#### 抽獎
key為抽獎活動名,value為員工名稱,把所有員工名稱放入抽獎箱 :
~~~
SADD?lucky?Tom?Jerry?John?Sean?Marry?Lindy?Sary?Mark
~~~
如果允許重復中獎,可以使用 SRANDMEMBER 命令

如果不允許重復中獎,可以使用 SPOP 命令。

## Zset
### 常用命令
Zset 常用操作:

Zset 運算操作(相比于 Set 類型,ZSet 類型沒有支持差集運算):

### 應用場景
#### 排行榜


#### 電話、姓名排序
使用有序集合的`ZRANGEBYLEX`或`ZREVRANGEBYLEX`可以幫助我們實現電話號碼或姓名的排序,我們以`ZRANGEBYLEX`(返回指定成員區間內的成員,按 key 正序排列,分數必須相同)為例。
**注意:不要在分數不一致的 SortSet 集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因為獲取的結果會不準確。**
##### 電話排序


##### 姓名排序


## Bitmap
### 簡介
Bitmap,即位圖,是一串連續的二進制數組(0和1),可以通過偏移量(offset)定位元素。BitMap通過最小的單位bit來進行`0|1`的設置,表示某個元素的值或者狀態,時間復雜度為O(1)。
由于 bit 是計算機中最小的單位,使用它進行儲存將非常節省空間,特別適合一些數據量大且使用**二值統計的場景**。

### 內部實現
Bitmap 本身是用 String 類型作為底層數據結構實現的一種統計二值狀態的數據類型。
String 類型是會保存為二進制的字節數組,所以,Redis 就把字節數組的每個 bit 位利用起來,用來表示一個元素的二值狀態,你可以把 Bitmap 看作是一個 bit 數組。
### 常用命令
bitmap 基本操作:

bitmap 運算操作:

### 應用場景
#### 簽到統計
簽到統計時,每個用戶一天的簽到用 1 個 bit 位就能表示,一個月(假設是 31 天)的簽到情況用 31 個 bit 位就可以,而一年的簽到也只需要用 365 個 bit 位,根本不用太復雜的集合類型。


#### 判斷用戶登陸態
Bitmap 提供了`GETBIT、SETBIT`操作,通過一個偏移值 offset 對 bit 數組的 offset 位置的 bit 位進行讀寫操作,需要注意的是 offset 從 0 開始。
只需要一個 key = login\_status 表示存儲用戶登陸狀態集合數據, 將用戶 ID 作為 offset,在線就設置為 1,下線設置 0。通過`GETBIT`判斷對應的用戶是否在線。50000 萬 用戶只需要 6 MB 的空間。

#### 連續簽到用戶總數
如何統計出這連續 7 天連續打卡用戶總數呢?
我們把每天的日期作為 Bitmap 的 key,userId 作為 offset,若是打卡則將 offset 位置的 bit 設置成 1。
key 對應的集合的每個 bit 位的數據則是一個用戶在該日期的打卡記錄。
一共有 7 個這樣的 Bitmap,如果我們能對這 7 個 Bitmap 的對應的 bit 位做 『與』運算。同樣的 UserID offset 都是一樣的,當一個 userID 在 7 個 Bitmap 對應對應的 offset 位置的 bit = 1 就說明該用戶 7 天連續打卡。
結果保存到一個新 Bitmap 中,我們再通過`BITCOUNT`統計 bit = 1 的個數便得到了連續打卡 3 天的用戶總數了。
Redis 提供了`BITOP operation destkey key [key ...]`這個指令用于對一個或者多個 key 的 Bitmap 進行位元操作。
* `opration`可以是`and`、`OR`、`NOT`、`XOR`。當 BITOP 處理不同長度的字符串時,較短的那個字符串所缺少的部分會被看作`0`。空的`key`也被看作是包含`0`的字符串序列。

## HyperLogLog
### 簡介
Redis HyperLogLog 是 Redis 2.8.9 版本新增的數據類型,是一種用于「統計基數」的數據集合類型,基數統計就是指統計一個集合中不重復的元素個數。但要注意,HyperLogLog 是統計規則是基于概率完成的,不是非常準確,標準誤算率是 0.81%。
所以,簡單來說 HyperLogLog**提供不精確的去重計數**。
HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的內存空間總是固定的、并且是很小的。
在 Redis 里面,**每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近`2^64`個不同元素的基數**,和元素越多就越耗費內存的 Set 和 Hash 類型相比,HyperLogLog 就非常節省空間。
### 常用命令

### 應用場景
#### 百萬級網頁 UV 計數

HyperLogLog 的統計規則是基于概率完成的,所以它給出的統計結果是有一定誤差的,標準誤算率是 0.81%。
這也就意味著,你使用 HyperLogLog 統計的 UV 是 100 萬,但實際的 UV 可能是 101 萬。雖然誤差率不算大,但是,如果你需要精確統計結果的話,最好還是繼續用 Set 或 Hash 類型。
## Geo
### 簡介
GEO 本身并沒有設計新的底層數據結構,而是直接使用了 Sorted Set 集合類型。
GEO 類型使用 GeoHash 編碼方法實現了經緯度到 Sorted Set 中元素權重分數的轉換,這其中的兩個關鍵機制就是「對二維地圖做區間劃分」和「對區間進行編碼」。一組經緯度落在某個區間后,就用區間的編碼值來表示,并把編碼值作為 Sorted Set 元素的權重分數。
這樣一來,我們就可以把經緯度保存到 Sorted Set 中,利用 Sorted Set 提供的“按權重進行有序范圍查找”的特性,實現 LBS 服務中頻繁使用的“搜索附近”的需求。
### 常用命令
```
#?存儲指定的地理空間位置,可以將一個或多個經度(longitude)、緯度(latitude)、位置名稱(member)添加到指定的 key 中。
GEOADD?key?longitude?latitude?member?[longitude?latitude?member?...]
#?從給定的 key 里返回所有指定名稱(member)的位置(經度和緯度),不存在的返回 nil。
GEOPOS?key?member?[member?...]
#?返回兩個給定位置之間的距離。
GEODIST?key?member1?member2?[m|km|ft|mi]
#?根據用戶給定的經緯度坐標來獲取指定范圍內的地理位置集合。
GEORADIUS?key?longitude?latitude?radius?m|km|ft|mi?[WITHCOORD]?[WITHDIST]?[WITHHASH]?[COUNT?count]?[ASC|DESC]?[STORE?key]?[STOREDIST?key]
```
### 應用場景

- 消息隊列
- 為什么要用消息隊列
- 各種消息隊列產品的對比
- 消息隊列的優缺點
- 如何保證消息隊列的高可用
- 如何保證消息不丟失
- 如何保證消息不會重復消費?如何保證消息的冪等性?
- 如何保證消息消費的順序性?
- 基于MQ的分布式事務實現
- Beanstalk
- PHP
- 函數
- 基礎
- 基礎函數題
- OOP思想及原則
- MVC生命周期
- PHP7.X新特性
- PHP8新特性
- PHP垃圾回收機制
- php-fpm相關
- 高級
- 設計模式
- 排序算法
- 正則
- OOP代碼基礎
- PHP運行原理
- zavl
- 網絡協議new
- 一面
- TCP和UDP
- 常見狀態碼和代表的意義以及解決方式
- 網絡分層和各層有啥協議
- TCP
- http
- 二面
- TCP2
- DNS
- Mysql
- 鎖
- 索引
- 事務
- 高可用?高并發?集群?
- 其他
- 主從復制
- 主從復制數據延遲
- SQL的語?分類
- mysqlQuestions
- Redis
- redis-question
- redis為什么那么快
- redis的優缺點
- redis的數據類型和使用場景
- redis的數據持久化
- 過期策略和淘汰機制
- 緩存穿透、緩存擊穿、緩存雪崩
- redis的事務
- redis的主從復制
- redis集群架構的理解
- redis的事件模型
- redis的數據類型、編碼、數據結構
- Redis連接時的connect與pconnect的區別是什么?
- redis的分布式鎖
- 緩存一致性問題
- redis變慢的原因
- 集群情況下,節點較少時數據分布不均勻怎么辦?
- redis 和 memcached 的區別?
- 基本算法
- MysqlNew
- 索引new
- 事務new
- 鎖new
- 日志new
- 主從復制new
- 樹結構
- mysql其他問題
- 刪除
- 主從配置
- 五種IO模型
- Kafka
- Nginx
- trait
- genergtor 生成器
- 如何實現手機掃碼登錄功能
- laravel框架的生命周期