redis 基礎(一)

Redis 的特點

  • 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
  • Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啓的時候可以再次加載進行使用。
  • Redis支持數據的備份,即master-slave模式的數據備份。
  • 豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作。
  • 原子 – Redis的所有操作都是原子性的,意思就是要麼成功執行要麼失敗完全不執行。單個操作是原子性的。多個操作也支持事務,即原子性,通過MULTI和EXEC指令包起來。
  • 高可用和分佈式:哨兵機制實現高可用,保證redis節點故障發現和自動轉移
  • 豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。

Redis 的五種數據類型

string

string 數據類型是最常用、簡單的key-value類型,普通的key/value 存儲都可以歸爲此類。value不僅可以是字符串,也可以是數字,圖片(base64),對象(序列化);

使用場景 :

  • 做緩存數據的功能 spring-boot-starter-data-redis
  • 存儲 session 信息 spring-session-data-redis
  • 做分佈式鎖 Redisson

    # ex:秒級過期時間,nx:鍵不存在時才能設置成功,xx鍵存在時才能設置成功
    set key value [ex seconds] [px milliseconds] [nx|xx]
  • 全局唯一 Id ,這比使用 uuid 會高效,使用的命令爲

    # key 在每次執行 incr 會增加 1 
    incr key
    # 如果應用系統每次獲取 id 時,都發一次命令,會對 redis 造成很大的壓力,一般的做法是應用系統每次取一定量的 id ,然後存儲在本地內存,然後內部使用鎖或原子數來增加 
    incrby key count 
  • 計數,也是使用 incr 命令;常見的場景有點贊數,閱讀數
  • 接口防刷,比如驗證碼,如果有人用程序不停的調用的你的驗證碼接口,可以用 redis 的 key 的過期時間解決

    # 驗證碼,單個手機號,一分鐘過期 ,一分鐘之內只能發送一次
    set shortMsg:checkCode:${phoneNum} ex 60 nx 

hash

使用場景 :

  • hash 可以用來存儲結構化數據,比如用戶信息
  • 非業務表可以使用 hash 來做數據緩存,比如字典表就很符合 hash 的數據結構

list

list 在 redis 中的實現是雙向鏈表,可以在兩端進行插入和彈出,還可以在一定範圍內取出元素,列表中的元素有序,可重複,是一種比較靈活的數據結構。

使用場景 :

  • 列表數據緩存;

    一個項目中的真實案例,有 100 萬個裝在車上的設備,然後設備的每一段里程都會上報,由另一個部門數據部門進行統計,我們業務部門有一個統計報表需要知道車輛一個時間段內的里程信息,會調用數據部門的接口,由於數據部門的數據是每一小時會保存一份(考慮到最小統計單位是小時),所以如果時間跨度比較大的話,數據部門會有大量的統計比較耗時,當時使用的是 list 做數據緩存,用查詢時間段做爲 key

  • 阻塞隊列

    brpop 命令有個特性,可以在有消息的時候彈出,在沒有消息的時候阻塞

  • 可以使用 lpush 和 lpop 實現棧
  • 可以使用 lpush 和 rpop 實現隊列

set

集合是一種無序,不允許重複元素,很類似於數學中的集合,可以用它來求交集,並集,差集,補集等問題; 相比於 org.apache.commons.collections.CollectionUtils 來說,它對於更大數據量的交集運算會更合適一點。

使用場景 :常用在社交軟件中

  • 共同關注,共同愛好
  • 可能認識的人

zset

排序的集合,不能有重複的元素,而且還可以排序,它和列表使用索引下標作爲排序依據不同的是,它給每個元素設置一個分數(score)作爲排序的依據,我們可以使用自定義的規則計算一個分值,並分配給元素。

使用場景 :

  • 博客排名 ,像 csdn 的排名
  • 排行榜,計算統合得分

持久化 AOF 和 RDB

RDB 方式指生成快照的方式,以二進制形式存儲全部數據。

AOF 會定時將寫入命令追加到 aof_buf 緩衝區,然後使用 sync 異步刷到磁盤。

RDB 持久化方式

執行 bgsave 命令時,redis 進程執行 fork 創建子進程完成持久化,是 save 命令的優化,save 會阻塞當前進程

在 redis-cli 執行 shutdown 命令時,如果沒有啓 aof ,將自動執行 bgsave

優點:適合於做數據冷備,恢復速度快,文件體積小

缺點:如果兩臺服務器的 redis 版本不一致,存在兼容性問題,無法實時持久化

相關配置

# 表示在多少秒內,有幾次改變,將執行 rdb 持久化; 如果只配置了 save "" 將關閉 rdb 持久化
save <seconds> <changes>
# 是否啓用壓縮,一般都需要啓用
rdbcompression yes
# 數據庫文件,默認就行
dbfilename dump.rdb
# 數據文件目錄,自已玩默認就行
dir ./

AOF 持久化方式

需要打開配置 appendonly yes

寫入命令會追加到一個緩衝區,然後定時向磁盤做 sync 同步

當文件越來越大時需要優化重寫 aof 文件來壓縮,使用 bgrewriteaof 機制,fork 子進程來進行 aof 文件的重寫

redis 重啓時可加載 aof 文件進行數據恢復。

優點:實時持久化,可儘可能的恢復數據

缺點:文本格式,體積過大,恢復速度慢

相關配置

# 開啓 aof 
appendonly yes
# aof 文件名,默認就行
appendfilename "appendonly.aof"
# 每秒一次 flush 操作,默認就行
appendfsync everysec

# 在 aof 文件重寫的時候是否不刷數據到磁盤,而是留在緩存區
no-appendfsync-on-rewrite  yes 
# aof 文件大小比上次重寫增加 100% 進行重寫
auto-aof-rewrite-percentage 100 
# 超過 64m 時進行重寫
auto-aof-rewrite-min-size 64mb

AOF 文件格式

下面是一個命令的例子,簡單的在0 庫的一個 set 命令 set sanri mm

*2
$6
SELECT
$1
0
*3
$3
set
$5
sanri
$2
mm
  • 數據或指令都會獨佔一行
  • * 表示一個命令的開始 ,*2 表示接下來的命令有 2 個佔位,select 0
  • $6 表示接下來的數據或指令有 6 個字符

基於 aof 的文件格式,可以從數據庫導數據到 redis

其實就是拼接成 aof 的文件格式的數據,然後恢復進 redis 庫

  1. 寫好拼裝的 sql 腳本,比如 vehicle.sql
  2. 執行 sql ,插入redis 的 2 號數據庫 ,使用 pipe 方式

    mysql -uroot -p123456 newgps --skip-column-names --default-character-set=utf8 --raw < vehicle.sql | redis-cli -a hhxredis --pipe -n 2

具體實現可以參照我的另一篇文章 導出 mysql 數據到 redis

Redis 重啓時恢復加載 AOF 和 RDB 的順序及流程

  1. 當 AOF 和 RDB 文件同時存在時,優先加載 AOF
  2. 若關閉了 AOF ,加載 RDB 文件
  3. 加載AOF/RDB成功,redis重啓成功
  4. AOF/RDB存在錯誤,redis啓動失敗並打印錯誤信息

Springboot 整合 Redis

引入 maven 依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置 redis 和連接池

spring.redis.host=192.168.163.100
spring.redis.port=6379
#spring.redis.password=
spring.redis.database=0
# 連接超時時間(毫秒)
spring.redis.timeout=5000

# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.pool.max-active=1000
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.pool.max-idle=10
# 連接池中的最小空閒連接
spring.redis.pool.min-idle=2

配置序列化工具

默認情況下,SpringBoot 已經配置好了兩個模板工具

  • RedisTemplate 鍵和值都使用 Jdk 序列化
  • StringRedisTemplate 鍵和值都使用 String 序列化

jdk 序列化存在體積大,還容易因爲修改了類的屬性而存在反序列化異常,需要一個 serialVersionUID 等問題,一般都自定義序列化工具,常見的序列化工具可以是 fastjsonkryoHessianProtostuff,見文章 序列 化工具性能對比

看網上大多是重新定義 RedisTemplate 類來修改序列化,但個人不建議這麼做,你可能把別人用的給打亂了,或者項目已經有舊數據在 redis 上,用的 jdk 序列化,如果改動會造成很大的影響,應該新建一個類,重新在 IOC 容器註冊一個新類的實例,來使用新的序列化。相關源碼

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