淺談Redis與中間的一些設計策略

簡介

Redis是一個開源的高性能鍵值對數據庫,基於內存且可持久化的日誌,因此一般也說內存數據庫,提供多種鍵值數據類型可以適應不一樣的存儲需求,因此這兩塊構成了Redis強大的基礎,基於內存的高性能和支持多種數據類型的高可用。git

可執行文件

  • redis-server:Redis服務器
  • redis-cli:Redis命令行客戶端
  • redis-benchmark:Redis性能測試工具
  • redis-check-aof:AOF文件修復工具
  • redis-check-dump:RDB文件檢查工具

啓動和中止

  • 直接啓動:適用開發環境 redis-server,默認使用6379端口,能夠經過--port參數指定端口號
  • 初始化腳本啓動:生產環境 Redis源代碼目錄utils文件中有一個redis_init_script的初始化腳本文件,使用腳本啓動須要配置Redis的運行方式和持久化文件、日誌文件的存儲位置等。
  • 中止:強制終止進程可能會致使數據丟失,一般是像Redis發送SHUTDOWN命令,kill進程的PID效果同樣。 redis-cli SHUTDOWN

多數據庫

Redis默認支持16個數據庫,能夠經過配置參數databases來修改。Redis不支持自定義數據庫名字,也不支持爲不一樣庫設置訪問密碼,都是以編號來命名的0~15,因此數據庫之間並不徹底隔離。因此注意不一樣的應用要使用不一樣的Redis實例存儲數據。github

5種數據類型

  • [string] 字符串類型:最基本的數據類型,能存儲任何形式的字符串,包括二進制數據,容許最大容量是512MBredis

  • [string] 經常使用命令算法

    • [set/get] 賦值與取值
    • [incr] 遞增數字
    • [incrby] 增長指定的整數,經過參數增長指定的數值
    • [decr] 減小指定的整數
    • [incrbyfloat] 增長指定的浮點數
    • [append] 向尾部追加值
    • [strlen] 獲取字符串長度
    • [mget/mset] 同時得到/設置多個鍵值
    • [getbit/setbit/bitcount/bitop] 位操做
  • [hash] 散列類型:字典結構以鍵值對的形式存儲數據,能夠包含232-1個字段數據庫

  • [hash] 經常使用命令緩存

    • [hset/hget] 賦值與取值
    • [hexists] 判斷字段是否存在
    • [hsetnx] 當字段不存在時賦值
    • [hincrby] 增長數字
    • [hdel] 刪除字段
    • [hkeys/hvalus] 只獲取字段名或字段值
    • [hlen] 獲取字段數量
  • [list] 列表類型:存儲一個有序的字符串列表,經常使用的操做是向列表兩端添加元素,或者得到列表的某一個片斷,一個列表最多容納232-1個元素安全

  • [list] 經常使用命令性能優化

    • [lpush/rpush] 向列表兩端增長元素
    • [lpop/rpop] 從列表兩端彈出元素
    • [llen] 獲取列表中元素的個數
    • [lrange] 獲取列表片斷
    • [lrem] 刪除列表中指定的值
    • [lindex/lset] 得到/設置指定索引的元素值
    • [ltrim] 只保留列表指定片斷
    • [linsert] 向列表中插入元素
    • [rpoplpush] 將元素從一個列表轉到另外一個列表
  • [set] 集合類型:和列表類型的區別就是無序且去重服務器

  • [set] 經常使用命令網絡

    • [sadd/srem] 增長/刪除元素
    • [smembers] 得到集合中的全部元素
    • [sismember] 判斷元素是否在集合中
    • [sdiff/sinter/sunion] 集合間運算
    • [scard] 得到集合中元素個數
    • [sdiffstore/sinterstore/sunionstore] 進行集合運算並將結果存儲
    • [srandmember] 隨機得到集合中的元素
    • [spop] 從集合中彈出一個元素
  • [sorted set] 有序集合類型:和集合類型的區別就在於有序

  • [sorted set] 經常使用命令

    • [zadd] 增長元素
    • [zscore] 得到元素的分數,也可作爲判斷是否存在
    • [zrange/zreverange] 得到排名在某個範圍的元素列表
    • [zrangebyscore] 得到指定分數範圍的元素
    • [zincrby] 增長某個元素的分數
    • [zcard] 得到集合中元素的數量
    • [zcount] 得到指定分數範圍內的元素個數
    • [zremrangebyrank] 按照排名範圍刪除元素
    • [zremrangebyscore] 按照分數範圍刪除元素
    • [zrank/zrevrank] 得到元素的排名
    • [zinterstore] 計算有序集合的交集

事務

Redis中的事務(transaction)是一組命令的集合,Redis保證一個事務中的全部命令要麼都執行,要麼都不執行。 Redis事務不支持關係數據庫事務提供的回滾(rollback)功能。
過程:mulit-----待執行命令----exec

錯誤處理

  1. 語法錯誤:事務中只要有一個命令有語法錯誤,執行exec後就會直接返回錯誤,語法正確的命令也不會執行。
  2. 運行錯誤:執行時錯誤,如散列類型命令操做集合類型的鍵,這種錯誤執行前redis是沒法發現的,因此出現這類錯誤,事務中其它命令會繼續執行。

WATCH命令 監視一個(或多個) key ,監控一直持續到exec命令(事務中的命令是在exec以後才執行的,因此在mulit命令後能夠修改watch監控的鍵值),若是在事務執行以前這個(或這些) key 被其餘命令所改動,那麼事務將被打斷。

UNWATCH 取消 WATCH命令對全部 key 的監視。若是在執行 WATCH命令以後, exec命令或 discard命令先被執行了的話,那麼就不須要再執行 UNWATCH了。 由於 exec命令會執行事務,而discard取消事務的同時也會取消對全部key的監視。

DISCARD 取消事務,放棄執行事務塊內的全部命令。

EXPIRE生存時間

在Redis中可使用expire命令設置一個鍵的生存時間,到時間後Redis會自動刪除它。
命令格式:expire key seconds,seconds參數表示鍵的生存時間,單位爲秒。
取消使用persist命令

訪問頻率限制

經過使用incr命令遞增鍵值來描述次數,經過設置生存時間來自動刪除,從而達到限制訪問的頻率,同時爲了保證創建鍵和爲鍵設置生存時間一塊兒執行(避免某些問題致使中間推出,避免未能設置生存時間而變成永久鍵),能夠把事務也引用進來。

//僞代碼
isKeyExists = EXISTS limiting:IP
if isKeyExists is 1
   times = INCR limiting:ip
   if times >100
      print 訪問頻率超過限制
      exit
   else
      MULTI
      INCR limiting:ip
      EXPIRE keyName ,60
      exit
複製代碼

實現緩存

上面說到使用expire命令來設置了生存時間,就能夠用來知足緩存實現的要求,可是爲了提升緩存的命用率以及更合理的使用內存資源,須要讓Redis按照必定的規則淘汰不須要的緩存鍵
淘汰規則

規則 說明
volatile-lru 使用LRU算法刪除一個鍵(已設置生存時間的鍵)
allkeys-lru 使用LRU算法刪除一個鍵
volatile-random 隨機刪除一個鍵(已設置生存時間的鍵)
allkeys-random 隨機刪除一個鍵
volatile-ttl 刪除生存時間最近的一個鍵
noeviction 不刪除,只返回錯誤

排序

前面說到了列表類型,有序集合類型都是知足有序的,這裏講講怎麼完成排序。
sort命令
sort命令能夠對列表類型、集合類型和有序集合類型的鍵進行排序,還能夠經過ALPHA參數實現按照字典順序排列,DESC參數倒序等。
by參數
若是提供了by參數,sort命令將再也不依據元素自身的值進行排序,而是對每一個元素使用元素的值替換參考鍵中的第一個「*」並獲取其值,而後依據該值對元素排序

## 鍵名->字段名
sort tag:posts by  post:*->time desc
複製代碼

get參數
get參數不影響排序,它的做用是使sort命令的返回結果再也不是元素自身的值,而是get參數中指定的鍵值。
store參數
默認狀況下sort會直接返回排序結果,若是但願保存結果,須要使用store參數
性能優化
sort是redis種最強大最複雜的命令之一,時間複雜度是O(n+mlogm),n表示排序的元素個數,m表示返回的元素個數。

  1. 儘量減小待排序鍵中元素的數量,n儘量小。
  2. 使用limit參數只獲取須要的數據,m儘量小。
  3. 若是要排序的數據數量較大,儘量使用store參數將結果緩存。

消息

任務隊列
說到隊列一般使用的是Redis的列表類型,使用lpush和rpop命令實現隊列。只須要讓生產者將任務使用lpush命令加入到某個鍵中,另外一邊讓消費者不斷使用rpop命令從該鍵中取出任務便可。
優先級隊列
能夠經過brpop命令來解決,brpop能夠同時接收多個鍵,意義是同時檢測多個鍵,若是全部鍵都沒有元素則阻塞,若是其中有一個鍵有元素則會從該鍵中彈出元素,若是多個鍵都有元素則按照從左到右的順序去第一個鍵中的元素。藉此特性能夠實現區分優先級的任務隊列。
發佈/訂閱
Redis提供了一組命令可讓開發者實現發佈/訂閱(publish/subscribe)模式。該模式包含了兩種角色,發佈者和訂閱者;能夠用來實現消息通知等。 訂閱者能夠訂閱一個或者若干個頻道(channel),而發佈者能夠向指定的頻道發送消息,訂閱該頻道都會收到此消息。
管道
客戶端和Redis使用TCP協議鏈接,不管是發送命令仍是返回執行結果都須要通過網絡傳輸,若是執行的命令較多,延時的累加起來對性能仍是有必定影響。 管道(pipelining)能夠一次性發送多條命令並在執行完後一次性將結果返回。

優化空間

  1. 精簡鍵名和鍵值
  2. 內部編碼優化

持久化

Redis支持兩種方式的持久化,RDB方式、AOF方式,可單獨使用,也可二者結合使用。

  1. RDB:經過快照(snapshotting)完成的,當符合必定條件時Redis自動將內存中的全部數據進行快照並存儲到硬盤。由用戶在配置文件中自定義,兩個參數構成:時間和改動的鍵個數;指定時間內更改的鍵大於這個數值就會進行快照。默認採用這種持久化方式
    缺點是定時持久化
  2. AOF:經過appendonly參數開啓,開啓後每執行一條更改的命令,會將該命令寫入硬盤的AOF文件,AOF方式是將執行過的寫指令記錄下來,在數據恢復時按照從前到後的順序再將指令都執行一遍。AOF文件位置和RDB文件的位置相同,都是經過dir參數設置,將緩存內容同步到硬盤中默認狀況下采用everysec規則,即每秒執行一次同步操做,always表示每次寫入都執行同步,最安全也最慢,no表示不主動進行同步而交由操做系統(默認30秒一次),都是經過appendfsync參數設置

多機數據庫

主要是適用於大型分佈式場景

  1. 複製:簡潔來講就是主從複製,主數據庫(master),從數據庫(slave);主數據庫能夠進行讀寫操做,發生寫操做時候同步給從數據庫,從數據庫通常只負責讀。
  • 使用複製功能很簡單,在配置文件中加入「slaveof 主數據 ip 主數據庫端口」便可。
  • 當從數據庫啓動後,會向主數據庫發送sync命令,主數據庫接收後開始後臺保存快照及期間接收的命令緩存起來,快照完成後,將快照文件和緩存的命令發送給從數據庫。從數據庫接收會載入快照文件及執行緩存命令。不支持斷點續傳。
  • 基於複製能夠實現讀寫分離,以及能夠經過主從切換來提升數據庫的高可用。好比設置主禁用持久化,從開啓持久化,主數據庫掛掉後,能夠把從數據庫提高爲主數據庫,主數據庫重啓後設置爲從數據庫便可將數據同步過來。這樣能保證數據不會丟失。
  1. sentinel:哨兵,Redis的高可用解決方案之一,由一個或多個sentinel實例組成的sentinel系統能夠監視多個主服務器,以及這些主服務器下的全部從服務器,主服務器下線後自動將下屬某個從服務器升級爲新的主服務器。
  2. 集羣:Redis提供的分佈式數據庫方案,集羣經過分片(sharding)來進行數據共享,並提供複製和故障轉移功能。

部分配置參數列表

參數名 默認值 使用config set設置
daemonize no no
pidfile /var/run/redis/pid no
port 6379 no
databases 16 no
save save 900 1/save 300 10/save 60 10000 yes
rdbcompression yes yes
rdbchecksum yes yes
dbfilename dump.rdb yes
dir ./ no
slaveof no
masterauth yes
slave-serve-stale-data yes yes
slave-read-only yes yes
requirepass yes
rename-command no
maxmemory yes
maxmemory-policy volatile-lru yes
maxmemory-samples 3 yes
appendonly no yes
appendfsync everysec yes
auto-aof-rewrite-percentage 100 yes
auto-aof-rewrite-min-size 64mb yes
lua-time-limit 5000 yes
slowlog-log-slower-than 10000 yes
slowlog-max-lan 128 yes
hash-max-ziplist-entries 512 yes
hash-max-ziplist-value 64 yes
list-max-ziplist-entries 512 yes
list-max-ziplist-value 64 yes
set-max-intset-entries 512 yes
zset-max-ziplist-entries 128 yes
zset-max-ziplist-value 64 yes

結語

有不少還不夠完善,未完待續吧~~~
我的博客~
簡書~

相關文章
相關標籤/搜索