Redis初識

安裝與使用

具體使用:php

  • 服務端啓動:將命令 redis-server.exe redis.windows.conf 寫入 .bat 文件,直接運行 StartWithConf.bat 啓動服務端;
  • 客戶端啓動:直接運行 redis-cli.exe 便可;
redis.windows.conf:配置文件
redis-benchmark.exe:Redis讀寫性能測試工具
redis-check-aof.exe:aof修復檢查日誌
redis-check-dump.exe:dump檢查數據庫文件
redis-cli.exe:Redis客戶端程序
redis-server.exe:Redis服務器程序
StartWithConf.bat:啓動Redis

配置文件

redis.windows.conf

Redis服務端的運行參數所有靠配置文件實現,此處詳細介紹Redis配置文件的幾個重要參數:html

// network
bind 127.0.0.1:綁定地址(外網鏈接:0.0.0.0)  
port 6379:默認綁定本機的6379端口;
timeout:鏈接超時時間(秒)
requirepass pass:配置redis鏈接認證密碼

// general
loglevel debug/notice/warning/verbose:日誌級別(開發測試/生產環境/只記錄警告錯誤信息/詳細信息)
logfile ./Logs/redis_log.txt:日誌文件保存路徑
databases 16:數據庫數量,默認0

// snapshotting
save TimeInterval ChangeCnt

// append only mode
appendonly yes:開啓命令日誌模式;

// limits
maxclients 64:最大鏈接數,0爲不限制
maxmemory <bytes>:內存清理臨界值
maxmemory-policy volatile-lru:內存清理採用的默認策略,對設置過時時間的key進行LRU算法刪除 

服務命令

ping:啓動服務鏈接狀況
info:查看server/client配置信息
info commandstats + config resetstat:顯示/清除名次調用統計信息
config get/set:獲取/設置配信息
flushdb/flushall:刪除當前所選/全部數據庫中的全部key
save/bgsave:數據保存到硬盤/異步保存
lastsave: 上次成功保存到磁盤的unix時間戳
dbsize:查看全部key的數目 
get/set和mget/mset:獲取/設置鍵
incr/decr和incrby/decrby:自增/自減
exists/type key:鍵key是否存在/鍵類型
expire key secondTime:設置鍵的過時時間
rename oldKey newKey:重命名
ttl key:鍵key的剩餘存活時間
select db_index:選擇數據庫
move key db_index:將鍵key移動到指定數據庫 

基本概念

Redis是典型的NoSQL數據庫服務器,其License是Apache License、徹底免費。首先看下內存數據庫的基本概念:java

內存數據庫web

In-Memory DataBase,之內存爲主要存儲介質的數據庫.redis

  • 全部的表及索引在內存中、消除I/O瓶頸,爲訪問內存設計最佳訪問方法和索引模式,讀寫速度快、性能好;
  • 內存數據庫的容量大小受物理內存的限制;
  • 安全性問題是硬傷,支持根據策略與磁盤數據庫進行數據同步,以及數據庫的可靠性恢復機制;

Redis算法

REmote DIctionary Server(遠程字典服務),遠程內存數據庫(Memory Database + Data Structure Server),開源的使用ANSI-C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、高性能的key-value數據庫,Redis不預約義且不使用表,適應高併發、海量數據存儲場景sql

  • A persistent key-value database with built-in net interface written in ANSI-C for Posix systems.
  • Redis is an open source, BSD licensed, advanced key-value cache and store.

下面是Redis支持的5種類型數據結構的內部圖解(圖一):數據庫

redisObject 對象是Redis內部的核心對象,用於表示全部的key和valuewindows

typedef struct redisObject {
    unsigned type:4;  // 數據類型
    unsigned encoding:4;  // 編碼方式
    unsigned lru:REDIS_LRU_BITS;   /* lru time (relative to server.lruclock) */
    int refcount;   // 對象的引用計數
    void *ptr;   // 指向真正的存儲結構
} robj;

其中,REDIS_LRU_BITS 表示當內存超限時採用 LRU 算法清除內存中的對象。redisObject對象的建立在object.c文件中:瀏覽器

robj *createObject(int type, void *ptr) {
    robj *o = zmalloc(sizeof(*o));
    o->type = type;
    o->encoding = OBJ_ENCODING_RAW;
    o->ptr = ptr;
    o->refcount = 1;

    /* Set the LRU to the current lruclock (minutes resolution). */
    o->lru = LRU_CLOCK();
    return o;
}    

具體內存結構示意圖(圖二):

參考Redis數據庫入門教程; Redis學習筆記

 

特色

  • 所有數據In-Momory,做爲Memcached的替代者;
  • key-value存儲系統(Key:數據檢索的惟一標識、Value:數據存儲的主要對象),支持多種類型的value(數據結構服務器);
  • redis的起點是cache,緩存,高速緩存;
  • 數據存儲於內存中或被配置爲使用虛擬內存;
  • 持久化特性(Persistence):能夠持久化到磁盤(週期性把更新數據寫入磁盤或把修改操做追加寫入記錄文件);
  • 主從複製特性(Master/Slave Replication):負載均衡,擴展讀性能;
  • 客戶端分片(Client-Side Sharding):數據劃分爲多個部分,擴展寫性能,線性級別的性能提高;
  • 支持各類不一樣方式的排序;
  • 支持簡單的事務(僅實現一次性執行多條命令的功能,不支持回滾);
  • 支持設置數據過時時間;

內存優化

  • string和數字:Redis內部維護一個數字池,能夠節省存儲空間,默認 REDIS_SHARED_INTEGERS = 10000 
  • 複雜類型的存儲優化:Redis內部使用緊湊格式存儲數據(適合集合包含的Entry很少而且每一個Entry包含的Value不是很長的狀況),遍歷複雜度降低爲O(n)、但節省存儲空間。以ZIPMap的數據結構爲例:

  

其中,字段free用於冗餘空間,空間換時間、必定狀況下避免插入操做引發的擴容操做。

  • list、set、hash採用特殊編碼,優化存儲空間;
  • byte、bit級別的操做:getrange/setrange、getbit/setbit以及bitmap高效存儲;

Redis .vs. Memcached

  • 二者均是高性能鍵值緩存服務器,Memcached只提供數據緩存服務,Redis提供數據緩存和持久化;
  • Memcached:多線程服務器;Redis:單線程服務器,部分性能經過多線程實現;
  • Memcached只支持普通字符串鍵;Redis提供豐富的數據存儲結構,同時支持主數據庫(Primary Database)+ 輔助數據庫(Auxiliary Database)使用;
  • Memcached:預分配內存池方式,Redis:現場申請內存的方式存儲數據、且能夠配置虛擬內存

數據類型

string

list

雙向鏈表、容許重複,支持lpush/rpush和lpop/rpop;實現消息隊列等;

set

不容許重複,內部是哈希表實現、查找/刪除/插入均O(1); 集合提供SINTER、SUNION、SDIFF分別支持交集、並集、差集操做。

hash

鍵值對(父鍵+子鍵:值)。存儲鍵key的多個屬性數據,徹底能夠用Json格式存儲、直接看成string類型操做,但對性能有影響,因此Redis提出Hash類型。

 

以下,圖一是普通的key/value結構,須要封裝一個對象保存value的信息;圖二是Redis的Hash類型:

zset

有序鍵值對(父鍵+成員:分值),鍵值對實際是成員和分值(Member-Score)的映射關係(字符串成員member與浮點數分值score之間的有序映射,按分值大小排序),分值必須爲浮點數; 既能夠根據成員訪問元素(同散列),又能夠根據分值按序訪問元素結構。

持久化

內存提供主存儲支持、硬盤做持久性存儲。默認開啓RDB模式,默認優先加載AOF文件。一次性將數據加載到內存中,一次性預熱。

問題:當服務器被關閉時,服務器內存存儲的數據將何去何從?

RDB .vs. AOF

  • RDB方式二進制方式存儲數據,文件較小且格式緊湊(RDB文件的存儲格式和Redis數據在內存中的編碼格式一致)、加載速度快;AOF方式文本文件追加寫操做命令,文件較大、信息冗餘,加載速度慢,但rewrite命令會壓縮aof文件;
  • RDB方式按配置的save策略實現按期批量數據存儲、效率相對較高;AOF方式準實時日誌記錄、效率相對較低;
  • 相比RDB方式,AOF方式可靠性較高、最少的數據丟失和較高的數據恢復能力;

不重啓Redis從RDB模式切換到AOF模式

redis-cli> config set appendonly yes:啓用AOF
redis-cli> config set save "":關閉RDB

==>Redis數據持久化; Redis做者:深度剖析Redis持久化

RDB  

半持久化模式(快照方式:File-Snap-Shotting,即時間點轉儲:Point-in-Time Dump),Redis DataBase,將數據先存儲在內存,當直接調用save/bgsave命令時或數據修改知足設置的save條件時觸發bgsave操做,將內存數據一次性寫入RDB文件。比較適合災難恢復(Disaster Recovery),若Redis異常crash,最近的數據會丟失。

rdbcompression yes:建立快照時對數據進行壓縮  
dbfilename dump.rdb:快照名稱
dir ./saveFile/:快照保存路徑(AOF文件存放目錄)

原理Copy-on-Write(寫時複製)技術

  • Redis forks;
  • 子進程將數據寫到臨時RDB文件中;
  • 當子進程完成寫RDB文件,用新文件替換舊文件;

該原理保證任什麼時候候複製RDB文件都是絕對安全的。

AOF  

全持久化模式(日誌方式),Append-Only-File,將數據存在內存,同時調用fsync將本次寫操做命令進行日誌記錄到aof文件,基於Redis網絡交互協議的由Redis標準命令組成的可識別的純文本文件,只容許追加不容許改寫。

寫策略:默認並推薦 appendfsync everysec ,速度和安全兼顧。

  • appendfsync always:每提交一個修改命令調用fsync刷新到AOF文件,很是慢、但很是安全;
  • appendfsync everysec:每秒調用fsync刷新到AOF文件,很快、但可能會丟失一秒之內的數據;
  • appendfsync no:依靠OS被動刷新、redis不主動刷新AOF,最快、但安全性差;

AOF最關鍵的配置就是關於調用fsync追加日誌文件持久化數據的頻率。磁盤空間滿、斷電等狀況不會影響日誌的完整性和可用性。

保存:支持2種方式

  • 調用flushaofbuf,把aof_buf中的命令寫入aof文件,再清空aof_buf,進入下一次loop;
sds aof_buf;   /* AOF buffer, written before entering the event loop */
  • aof_rewrite:根據現有的數據庫數據反向生成命令,而後把命令寫入aof文件中;

加載

fakeClient = createFakeClient();   // 建立僞客戶端
while(命令不爲空) {
   // 獲取一條命令的參數信息 argc, argv
      . . . 
   // 執行
   fakeClient->argc = argc;
   fakeClient->argv = argv;
   cmd->proc(fakeClient);
}

AOF重寫

bgrewriteAOF從新生成一份AOF文件,新的AOF文件只包含對同一個值的屢次操做的最後一條記錄(能夠恢復數據的最小指令集),過程和RDB相似(Copy-on-Write機制):

  • fork一個子進程,直接遍歷舊的AOF文件,將數據寫入新的AOF臨時文件;
  • 在寫新文件過程當中,全部的新的寫操做日誌記錄在內存緩衝區中、同時會寫入到原有的AOF文件中;
  • 完成寫新文件操做後,發出信號通知父進程將內存緩衝區中的寫指令一次性追加到臨時AOF文件中;
  • 追加完畢,Redis將臨時AOF文件做爲新AOF文件代替舊AOF文件(調用原子性的rename命令用新的AOF文件取代老的AOF文件); 

當同時知足如下2個條件時觸發rewrite操做:

auto-aof-rewrite-percentage 100  // 當前寫入日誌文件的大小佔到初始日誌文件大小的某個百分比時觸發rewrite
auto-aof-rewrite-min-size 64mb   // 本次Rewrite最小的寫入數據量

注意,bgrewriteaof和bgsave不能同時執行,避免兩個Redis後臺進程同時對磁盤進行大量的I/O操做。

修復

Redis提供 redis-check-aof.exe 工具支持日誌修復功能:

  • 備份壞的AOF文件;
  • 運行redis-check-aof –fix修復壞的AOF文件;
  • 用diff -u對比兩個文件的差別,確認問題點;
  • 重啓Redis,加載修復後的AOF文件;

主從機制

master-slave,爲了增強持久化機制,在持久化基礎上Redis提供複製功能:將一個主服務器(master)數據自動同步到多個從服務器(slave),實現主從同步:

  • 純粹的冗餘備份
  • 提高讀性能

具體地:

  • 啓動從服務器,先向主服務器發送SYNC命令;
  • 主服務器收到SYNC命令後fork子進程開始保存快照,期間全部發給主服務器的命令都會被緩存到內存;
  • 快照保存完成後,主服務器把快照和緩存的命令所有發送給從服務器;
  • 從服務器保存收到的快照文件並加載到內存中,而後依次執行收到的緩存命令;

在主從同步過程當中(異步實現),從服務器不會阻塞,期間默認使用同步以前的數據繼續響應客戶端命令。主從機制支持增量同步策略,下降鏈接斷開的恢復成本。

具體應用中一般是:Redis+MySQL

發佈訂閱機制

publish-subscribe,觀察者模式,訂閱者(Subscriber)訂閱頻道(Channel),發佈者(Publisher)將消息發到指定頻道(Channel),經過這種方式將消息的發送者和接收者解耦,能夠實現多個瀏覽器之間的信息同步和實時更新。

  • 消息的傳遞是多對多的;
  • 支持模式匹配;
  • 運行穩定、快速;
publish myChannel 「xxx」:發佈 
subscribe myChannel:訂閱
unsubscribe myChannel:取消訂閱

Redis的Pub/Sub模式容許動態的Subscribe/Unsubscribe,提升系統的靈活性和可擴展性。  

其餘  

排序

問題:數據庫支持排序,爲何要把排序功能放在緩存中實現?

  • 排序會增長數據庫的負載,難以支撐高併發的應用;
  • 在緩存中排序不會遇到表鎖定的問題;
sort key [BY pattern] [LIMIT offset cnt] [GET pattern [GET pattern ...]] [asc | desc] [ALPHA] [STORE destination]
  • by:即order by,指定排序字段,by *->子鍵名;
  • limit:限制排序後返回元素的數量,表示跳過前offset個元素、返回以後的連續cnt個元素,能夠實現分頁功能;
  • get:返回指定的字段值,get *->子鍵名;
  • store:將排序結果存入指定位置;  

事務

Transaction。

  • multi:原子操做,通知Redis,接下來的若干命令屬於同一事務;
  • 輸入若干命令,存儲在命令隊列中而不會被當即執行;
  • exec:原子操做,通知Redis,屬於同一事務的全部命令輸入完成,開始執行事務;

管道

pipilining,容許Redis一次性接收多個命令、執行後一次性返回結果,減小客戶端與Redis服務器的通訊次數、下降往返時延。相似事務,經過原子操做multi/exec完成。

優先級隊列

blpop/brpop

高可用性(High Availability)

  • 哨兵(Sentinel)
  • 自動分區(Cluster)

應用場景

首先,將Redis與SQL Server/MySQL等對比一下:

  • Redis的持久化是附加功能,且其flushdb、flushall命令會直接清空數據庫, SQL Server/MySQL的持久化是核心功能;
  • Redis全量持久數據從內存到磁盤、大數據下影響性能,SQL Server/MySQL增量持久化被修改的數據;

應用場景

 - 在主頁中顯示最新的項目列表;
 - 刪除和過濾:lrem;
 - 排行榜(Leader Board)及相關問題;
 - 按照用戶投票和時間排序;
 - 過時項目處理:unix時間做爲得分;
 - 計數(Counting Stuff):INCR,DECR命令構建計數器系統;
 - 特定時間內的特定項目:Redis特點特性;
 - 實時分析正在發生的狀況,用於數據統計與防止垃圾郵件等;
 - Pub/Sub:發佈訂閱機制;
 - 隊列(Priority Queue);
 - 緩存(Caching);  

而後給出使用Redis中的幾點注意事項:

  • keys * --->  scan
  • 建議使用hash
  • expire設置key的存活時間 + volatile-lru策略;
  • Redis所在機器物理內存使用最好不要超過實際內存總量的3/5;

以及經過閱讀 ALCA in Redis-land 獲得的建議:

參考Redis應用場景; Redis做者談Redis應用場景; Redis應用建議

關於Redis在C#中的輔助工具,具體參見:Redis for C# | sqh

 


相關文章
相關標籤/搜索