Redis高級用法


Redis認識誤區

  • 用get/set方式使用Redisphp

做爲一個key value存在,不少開發者天然的使用set/get方式來使用Redis
實際上這並非最優化的使用方法。尤爲在未啓用VM狀況下,Redis所有數據須要放入內存節約內存尤爲重要。

假如一個key-value單元須要最小佔用512字節,即便只存一個字節也佔了512字節。
這時候就有一個設計模式,能夠把key複用,幾個key-value放入一個key中,value再做爲一個set存入
這樣一樣512字節就會存放10-100倍的容量。

這就是爲了節約內存,建議使用hashset而不是set/get的方式來使用Redis
  • 單臺Redis的存放數據必須比物理內存小redis


工具命令

#redis-server:Redis 服務器的 daemon 啓動程序
#redis-cli:Redis 命令行操做工具。固然,你也能夠用 telnet 根據其純文本協議來操做
#redis-benchmark:Redis 性能測試工具,測試 Redis 在你的系統及你的配置下的讀寫性能
$redis-benchmark -n 100000 –c 50
#模擬同時由 50 個客戶端發送 100000 個 SETs/GETs 查詢
#redis-check-aof:更新日誌檢查
#redis-check-dump:本地數據庫檢查

管理命令

# dbsize 返回當前數據庫 key 的數量。
# info 返回當前 redis 服務器狀態和一些統計信息。
# monitor 實時監聽並返回redis服務器接收到的全部請求信息。
# shutdown 把數據同步保存到磁盤上,並關閉redis服務。
# config get parameter 獲取一個 redis 配置參數信息。(個別參數可能沒法獲取)
# config set parameter value 設置一個 redis 配置參數信息。(個別參數可能沒法獲取)
# config resetstat 重置 info 命令的統計信息。(重置包括:keyspace 命中數、
# keyspace 錯誤數、 處理命令數,接收鏈接數、過時 key 數)
# debug object key 獲取一個 key 的調試信息。
# debug segfault 製造一次服務器當機。
# flushdb 刪除當前數據庫中全部 key,此方法不會失敗。當心慎用
# flushall 刪除所有數據庫中全部 key,此方法不會失敗。當心慎用

redis 安全性

  • 添加密碼數據庫

#編輯redis.conf
[root@localhost etc]# vim  /usr/local/redis/etc/redis.conf
#添加密碼 smudge

#保存退出

clipboard.png

  • 重啓redisvim

pkill redis

/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
  • 使用redis-cli命令 受權 -a smudge設計模式

[root@localhost etc]# /usr/local/redis/bin/redis-cli -a smudge
127.0.0.1:6379> 
    
    #若是不使用 -a 受權 能夠單獨受權 
        127.0.0.1:6379> auth smudge
        OK
  • php 代碼中受權緩存

$redis = new Redis();
$redis->connect('192.168.206.128', 6379);
$redis->auth('smudge');
$redis->set('key','TK');

redis 持久化

一般 Redis 將數據存儲在內存中或虛擬內存中, 它是經過如下兩種方式實現對數據的持久化安全

  • 快照方式:(默認持久化方式)服務器

    這種方式就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名爲dump.rdb
       客戶端也可使用 save 或者 bgsave 命令通知 redis 作一次快照持久化
       
       每次快照持久化都是將內存數據完整寫入到磁盤一次,並非增量的只同步增量數據
       若是數據量大的話,寫操做會比較多,必然會引發大量的磁盤 IO 操做,可能會嚴重影響性能
       
       每隔一段時間寫快照,若是redis意外宕機,最後一個寫入快照後全部的更新,數據丟失

clipboard.png

  • 關閉rdb持久化app

config set save ""
  • 日誌追加方式svn

    redis 會將每個收到的寫命令都經過 write 函數追加到文件中(默認appendonly.aof)
    當 redis 重啓時會經過從新執行文件中保存的寫命令來在內存中重建整個數據庫的內容
    弊端:持久化文件會變的愈來愈大
    bgrewriteaof 命令 用於壓縮持久化文件

    配置redis.conf

    vim /usr/local/redis/etc/redis.conf

    appendonly yes
    //啓用日誌追加持久化方式

    appendfsync always

    //每次收到寫命令就當即強制寫入磁盤, 最慢的, 可是保證徹底
    的持久化,不推薦使用
    appendfsync everysec
    //每秒鐘強制寫入磁盤一次, 在性能和持久化方面作了很好的折
    中,推薦

    appendfsync no

    //徹底依賴操做系統,性能最好,持久化沒保證

clipboard.png


主從同步

# Redis 支持將數據同步到多臺從庫上
# 除了多個 slave 連到相同的 master 外,slave 也能夠鏈接其它 slave 造成圖狀結構
  master 能夠有多個 slave。
# 主從複製不會阻塞 master,master能夠同時進行復制和處理客戶端請求
  可是slave初次同步會阻塞客戶端的請求
# 主從複製能夠用來提升系統的可伸縮性 可使用slave 進行讀操做 
  好比 sort 操做可使用 slave 來處理
# master 禁用數據持久化 在slave使用持久化
  • 同步原理

    ^ 當設置好 slave 服務器後,slave 會創建和 master 的鏈接,而後發送 sync 命令。
    不管是第一次同步創建的鏈接仍是鏈接斷開後的從新鏈接,master 都會啓動一個後臺進程,將數據
    庫快照保存到文件中,同時 master 主進程會開始收集新的寫命令並緩存起來。
    後臺進程完成寫文件後,master 就發送文件給 slave,slave 將文件保存到磁盤上,而後加載到內存恢復
    數據庫快照到 slave 上。
    接着 master 就會把緩存的命令轉發給 slave。並且後續 master收到的寫命令都會經過開始創建的鏈接發送 
    給slave。 
    從master到slave的同步數據的命令和從客戶端發送的命令使用相同的協議格式。當 master 和 slave 的連
    接斷開時 slave 能夠自動從新創建鏈接。
    若是 master 同時收到多個 slave 發來的同步鏈接命令,只會啓動一個進程來寫數據庫鏡像
    而後發送給全部 slave
  • 主從配置

    配置 slave 服務器很簡單,只須要在配置文件中加入以下配置
    slaveof 192.168.1.1 6379 #指定 master 的 ip 和端口

    masterauth smudge #主服務器有密碼 因此要設置該項

    clipboard.png

#主服務器是 192.168.206.128 從服務器是 192.168.206.130 
# /usr/local/redis/bin/redis-cli -a smudge #登陸從服務器客戶端
127.0.0.1:6379> info

clipboard.png

值爲up時,則主從配置成功

至此能夠實驗在主服務器存儲 在從服務器獲取

redis 事務性

  • 基礎事務性

    127.0.0.1:6379> mget name age #獲取鍵值
    1) "TK"
    2) "28"
    127.0.0.1:6379> multi # 開啓事務體
    OK
    127.0.0.1:6379> incr name # 命令插入隊列
    QUEUED
    127.0.0.1:6379> incr age # 命令插入隊列
    QUEUED
    127.0.0.1:6379> exec # 執行隊列中的命令
    1) (error) ERR value is not an integer or out of range #name(string型)數值加1執行失敗
    2) (integer) 29 #age數值加1執行成功

    隊列中命令有一個執行失敗 並無回滾,因此 redis不是嚴格的事務 異於RDBS的事務

    127.0.0.1:6379> discard # 清除事務

  • Redis事務樂觀鎖

    多說幾句,咱們平時用的svn就是基於樂觀鎖原理, 如A和B同時改文件C
    A和Bupdate到C到本地的版本是1
    A修改完畢以後提交服務器,C的版本號爲2
    B提交時候,服務器中C的版本號比B本地C版本號大,則提交失敗
    B就要update,將C本地版本更新到2,再次提交

    redis有watch就是svn中的commit命令,每次修改時就要,覈對版本號

    127.0.0.1:6379> watch age # 監視age鍵 記錄當前版本號
    OK
    127.0.0.1:6379> incr age # 非事務更新age ,此時age鍵版本號已經更新
    (integer) 30
    127.0.0.1:6379> multi #開啓事務
    OK
    127.0.0.1:6379> incr age #命令插入隊列
    QUEUED
    127.0.0.1:6379> exec #執行事務
    (nil) # 執行事務失敗,由於watch的版本號已經小於此時鍵age的版本號

  • 總結

    執行exec時,若是監視的key從watch命令執行以來被修改過,則exec執行失敗
    watch與multi exec搭配使用 watch僅對當前鏈接有效 ,斷開鏈接,全部watch也就失效了
    exec unwatch discard 命令 執行後, 監視取消 ,不論以前監視多少個key 全部的watch所有失效了

    127.0.0.1:6379> watch age # 監視age
    OK
    127.0.0.1:6379> watch name # 監視name
    OK
    127.0.0.1:6379> incr age
    (integer) 31
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr age
    QUEUED
    127.0.0.1:6379> exec # 此時全部的watch已經失效了
    (nil)
    127.0.0.1:6379> set name TK1
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set name TK2
    QUEUED
    127.0.0.1:6379> exec # 由於沒有監視了 因此執行成功了
    1) OK

  • PHP代碼

    <?php

    $redis->watch('key');

    監控鍵key 是否被其餘客戶端修改,若是KEY在調用watch()和exec()之間被修改,exec失敗

    $ret = $redis->multi()

    ->incr('x')
    ->exec();
     ?>

發佈訂閱消息

  • subscribe / publish 命令

    在Redis中,一旦一個client發出了SUBSCRIBE命令,它就處於監聽的模式
       此時除了SUBSCRIBE, PSUBSCRIBE,UNSUBSCRIBE,PUNSUBSCRIBE這4條命令以外
       的全部其它命令都不能用。

clipboard.png # publish 發佈 publish tv1 "Hello world" 單通道發佈

clipboard.png # subscribe 訂閱 subscribe tv1 tv2 tv3 訂閱多個平臺

  • php代碼

    配置文件

    $redis = new Redis();
    $redis->pconnect('192.168.206.128', 6379);
    $redis->auth('smudge');

    publish.php

    $redis->publish('chan-1', 'first');
    $redis->publish('chan-2', 'second');
    $redis->publish('chan-3', 'third');

    subscribe.php

    function f($redis, $chan, $msg) { //頻道訂閱

    switch($chan) {
        case 'chan-1':
            echo 'chan-1:'.$msg."\n";
            break;
    
        case 'chan-2':
            echo 'chan-2:'.$msg."\n";
            break;
    
        case 'chan-3':
            echo 'chan-3:'.$msg."\n";
            break;
    }

    }
    $redis->subscribe(array('chan-1', 'chan-2', 'chan-3'),'f');


redis 虛擬內存

若是咱們的存儲的數據老是有少部分數據被常常訪問,大部分數據不多被訪問
對於網站來講確實老是隻有少許用戶常常活躍。
當少許數據被常常訪問時,使用虛擬內存不但能提升單臺redis server數據庫的容量
並且也不會對性能形成太多影響。

# 開啓VM功能
#vim redis.conf

vm-enabled yes                       #開啓vm功能
vm-swap-file /tmp/redis.swap            #交換出來的value保存的文件路徑
vm-max-memory 1000000              #redis使用的最大內存上限
vm-page-size 32                      #每一個頁面的大小32個字節
vm-pages 134217728                  #最多使用多少頁面
vm-max-threads 4                    #用於執行value對象換入換出的工做線程數量

redis 核心配置說明

daemonize:
#是否之後臺守護進程方式運行
pidfile:
#pid 文件位置
port:
#監聽的端口號
timeout:
#請求超時時間
loglevel:
#log 信息級別,總共支持四個級別:debug、verbose、notice、warning,
默認爲 verbose
logfile:
#默認爲標準輸出(stdout) ,若是配置爲守護進程方式運行,而這裏又配
置爲日誌記錄方式爲標準輸出,則日誌將會發送給/dev/null
databases:
#開啓數據庫的數量。使用「SELECT 庫 ID」方式切換操做各個數據庫
save * *:
#保存快照的頻率,第一個*表示多長時間,第二個*表示執行多少次寫操
做。在必定時間內執行必定數量的寫操做時,自動保存快照。可設置多個條件。
rdbcompression:#保存快照是否使用壓縮
dbfilename:
#數據快照文件名(只是文件名,不包括目錄) 。默認值爲 dump.rdb
dir:
#數據快照的保存目錄(這個是目錄)
requirepass:
#設置 Redis 鏈接密碼,若是配置了鏈接密碼,客戶端在鏈接 Redis 時需
要經過 AUTH <password>命令提供密碼,默認關閉
相關文章
相關標籤/搜索