Redis高性能內存數據庫

(一)什麼是Redis?

Redis是一個key-value存儲系統。和Memcached相似,它支持存儲的value類型相對更多,包括string(字符串)list(鏈表)set(集合)zset(sorted set --有序集合)hash(哈希類型)。與Memcached同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave(主從)同步。html

Redis 是一個高性能的key-value數據庫。Redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部分場合能夠對關係數據庫起到很好的補充做用。它提供了JavaC/C++C#PHPJavaScriptPerlObject-CPythonRubyErlang等客戶端,使用很方便。[1] java

Redis支持主從同步。數據能夠從主服務器向任意數量的從服務器上同步,從服務器能夠是關聯其餘從服務器的主服務器。node

 

 

(二)RedisMemcached的區別

u 持久化:redis

l Redis能夠用來作緩存,也能夠作存儲;支持ADFRDB兩種持久化方式數據庫

l Memcached只能緩存數據緩存

 

u 數據結構:服務器

l Redis有豐富的數據類型:字符串、鏈表,Hash、集合,有序集合數據結構

l Memcached通常就是字符串和對象架構

 

(三)Redis的安裝與配置

1.解壓:tar -zxvf redis-3.0.5.tar.gz併發

2.make

3.make PREFIX=/root/training/redis install

4.cp ~/tools/redis-3.0.5/redis.conf /root/training/redis/etc/

 

Redis的核心配置文件:redis.conf

 

 

 

Redis的命令腳本:

  redis-benchmark  性能測試工具

  redis-check-aof  檢查AOF日誌

  redis-check-dump 檢查RDB日誌

  redis-cli        啓動命令行客戶端

  redis-sentinel  

  redis-server     啓動Redis服務

 

啓動Redis

  ./redis-server ../etc/redis6379.conf

  ./redis-server ../etc/redis6380.conf

 

這樣就在63796380端口上,各自啓動了一個Redis實例;也能夠經過ps命令查看:

 

啓動Redis的客戶端:redis-cli

默認鏈接6739端口,也能夠經過-p指定鏈接的端口號:
 

l ./redis-cli --help顯式幫助信息

 

(四)Redis的操做
http://www.redis.cn/commands.html

key操做
redis key 是以 string 儲存的,redis 對於 key 經常使用的操做指令以下:

1.select db_name 使用指定數據庫    select 1          # 使用數據庫 1

2.exits key_name 檢查指定的 key 是否存在

3.get key_name 獲取指定 key value

4.mget key1 [key2 ..] 獲取指定多個 key value

5.randomkey 隨機獲取一個 key

6.set key_name key_value 設置 key-value

7.getset key_name key_value 設置 key-value,並返回 key 的舊值

8.setnx key_name value 只有在 key 不存在時,才設置 key

9.mset key1 val1[ key1 val2...] 同時設置多個 key-value

10.del key_name 刪除指定的 key

11.rename key_name new_key_name 重命名指定key

12.type key_name 返回指定 key value 的類型

13.dump key_name  序列化指定 key,並返回該 key 序列化後的 value

14.keys pattern 查找全部符合給定 pattern key,支持使用 * 做爲通配符;

15.keys a*      # 查找全部以 ‘a’ 開頭的 key

16.keys *        # 查找全部 key

17.move key_name db_name 將指定 key-value 移動到指定數據庫

18.expire key_name seconds   pexpire key_name milliseconds
給指定key設置過時時間,單位分別爲秒,毫秒

19.expireat key_name timestamp 設置指定的key 在指定的UNIX時間戳過時

20.ttl key_name pttl key_name
返回 key TTLTime to Live)生存時間,分別以 秒,毫秒爲單位;

21.persist key_name 移除指定 key 的過時時間,該 key 將持久保存

22.flushdb 刪除當前數據庫的全部 key

23.flushall 刪除全部數據庫的 key

其餘操做可進入連接查看

數據類型

① 字符串
 

② 鏈表

③ Hash

  

④ 無序集合
 

⑤ 有序集合
 

⑥ Redis數據類型案例分析:網站統計用戶登陸的次數

  1. 1億個用戶,有常常登陸的,也有不常常登陸的
  2. 如何來記錄用戶的登陸信息
  3. 如何查詢活躍用戶:好比:一週內,登陸3次的

  解決方案一:採用關係型數據庫

     解決方案二:採用Redis存儲登陸信息

可使用Redissetbit,登陸與否:有10就能夠表示

25.Java客戶端

① 基本操做
 

② 鏈接池

③ 使用Redis實現分佈式鎖

使用Maven搭建工程:

<dependency>

    <groupId>redis.clients</groupId>

    <artifactId>jedis</artifactId>

    <version>2.9.0</version>

</dependency>

(五)Redis的事務和消息機制

1.Redis的事務

Redis對事務的支持目前還比較簡單。redis只能保證一個client發起的事務中的命令能夠連續的執行,而中間不會插入其餘client的命令。 因爲redis是單線程來處理全部client的請求的因此作到這點是很容易的。通常狀況下redis在接受到一個client發來的命令後會當即處理並 返回處理結果,可是當一個client在一個鏈接中發出multi命令有,這個鏈接會進入一個事務上下文,該鏈接後續的命令並非當即執行,而是先放到一個隊列中。當今後鏈接受到exec命令後,redis會順序的執行隊列中的全部命令。並將全部命令的運行結果打包到一塊兒返回給client.而後此鏈接就 結束事務上下文。

 

Oracle數據庫中的事務和Redis的事務對比

 

Oracle

Redis

開啓事務的方式

自動開啓事務

multi

操做

DML語句

Redis命令

提交事務

commit

exec

回滾事務

rollback

discard

 

2.Redis的事務示例:銀行轉帳

  從Tom100塊錢給Mike

  • set tom 1000
  • set mike 1000
  • multi
  • decrby tom 100
  • incrby mike 100
  • exec

3.Redis的鎖機制:watch

l 舉例:買票

4.Java應用程序中的事務和鎖

① 事務
 

② 鎖

5.Redis的消息機制:消息的發佈與訂閱,適合作在線聊天

  publish:發佈消息

    格式:publish channel名稱 「消息內容」

 

  subscribe: 訂閱消息

    格式:subscribe channel名稱

 

  psubscribe: 使用通配符定義消息

    格式:psubscribe channel*名稱

 

  使用Java程序實現消息的發佈與訂閱,須要繼承JedisPubSub
 

(六)Redis的持久化

Redis 提供了多種不一樣級別的持久化方式:

  •   RDB 持久化能夠在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。
  •   AOF Append-only file持久化記錄服務器執行的全部寫操做命令,並在服務器啓動時,經過從新執行這些命令來還原數據集。 AOF 文件中的命令所有以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還能夠在後臺對 AOF 文件進行重寫(rewrite),使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。
  •   Redis 還能夠同時使用 AOF 持久化和 RDB 持久化。 在這種狀況下, 當 Redis 重啓時, 它會優先使用 AOF 文件來還原數據集, 由於 AOF 文件保存的數據集一般比 RDB 文件所保存的數據集更完整。
  •   你甚至能夠關閉持久化功能,讓數據只在服務器運行時存在。

一、RDB

  工做原理:每隔必定時間給內存照一個快照,將內存中的數據寫入文件(rdb文件)配置參數:redis.conf文件(在conf文件中找到對應位置)

  • RDB示例測試:可使用redis-benchmark進行壓力測試
  1.  ./bin/redis-benchmark -n 100000  表示執行100000個操做
  • RDB的缺點:
  1. 在兩次快照之間,若是發生斷電,數據會丟失
  2. 舉例:在生成rdb後,插入新值。忽然斷電,數據可能會丟失

二、AOF:經過日誌的方式

  • 工做原理:記錄操做的命令
  • 配置參數:
  • 什麼是AOF的重寫:rewrite
  1. 將內存中的key逆向生成命令,如同一個能夠,反覆操做了100次,aof文件會記錄100次操做,這樣會致使AOF文件過大

例如:

set age 0

incr age

incr age

... 100

  最後 age的值是100

  通過重寫後,直接執行: set age 100

  2.能夠經過觀察aof日誌文件的大小

 

三、Redis持久化注意的問題

  • RDB恢復的速度快
  • 若是RDBAOF都有,默認使用AOF進行恢復

 

(七)Redis的集羣

1.集羣的做用

主從備份 防止主機宕機

讀寫分離,分擔master的任務

任務分離,如從服分別分擔備份工做與計算工做

2.Redis 集羣的兩種部署方式

3.Redis主從服務的通訊原理

4.配置Redis的集羣(主從模式)

  • 主節點:關閉rdbaof便可
  • 從節點:slaveof localhost 6379  開啓rdb和aof

5.Redis集羣的高可用性

  • Redis 2.4+自帶了一個HA實現Sentinel
  • 配置文件:sentinel.conf
     
  • redis-sentinel ../etc/sentinel.conf
  • 查看日誌:
     

6.實現Redis的代理分片

  • Twemproxy是一種代理分片機制,由Twitter開源。
  • Twemproxy做爲代理,可接受來自多個程序的訪問,按照路由規則,轉發給後臺的各個Redis服務器,再原路返回。該方案很好的解決了單個Redis實例承載能力的問題。

 

  • 安裝

    ./configure --prefix=/root/training/proxy

    make

    make install 

  • 配置文件
  • 檢查配置文件是否正確
    ./nutcracker -t conf/nutcracker.yml
  • 啓動代理服務器
    ./nutcracker -d -c conf/nutcracker.yml

(八)Redis Cluster分佈式解決方案 

1.什麼是Redis Cluster

    Redis ClusterRedis的分佈式解決方案,在Redis 3.0版本正式推出的,有效解決了Redis分佈式方面的需求。當遇到單機內存、併發、流量等瓶頸時,能夠採用Cluster架構達到負載均衡的目的。

  • redis使用中遇到的瓶頸

    咱們平常在對於redis的使用中,常常會遇到一些問題:

    (1) 高可用問題,如何保證redis的持續高可用性。

    (2) 容量問題,單實例redis內存沒法無限擴充,達到32G後就進入了64位世界,性能降低。

    (3) 併發性能問題,redis號稱單實例10萬併發,但也是有盡頭的。

  • redis-cluster的優點 

    (1) 官方推薦,毋庸置疑。

    (2) 去中心化,集羣最大可增長1000個節點,性能隨節點增長而線性擴展。

    (3) 管理方便,後續可自行增長或摘除節點,移動分槽等等。

    (4) 簡單,易上手。

2.數據分佈理論與Redis的數據分區

  分佈式數據庫首要解決把整個數據集按照分區規則映射到多個節點的問題,即把數據集劃分到多個節點上,每一個節點負責整個數據的一個子集。常見的分區規則有哈希分區和順序分區。Redis Cluster採用哈希分區規則

  虛擬槽分區巧妙地使用了哈希空間,使用分散度良好的哈希函數把全部的數據映射到一個固定範圍內的整數集合,整數定義爲槽(slot)。好比Redis Cluster槽的範圍是0 16383。槽是集羣內數據管理和遷移的基本單位。

  Redis Cluster採用虛擬槽分區,全部的鍵根據哈希函數映射到0 16383,計算公式:slot = CRC16(key)&16383。每個節點負責維護一部分槽以及槽所映射的鍵值數據。

3.Redis Cluster的體系架構

  咱們6個節點爲例,來介紹Redis Cluster的體系架構。其中:三個爲master節點,另外三個爲slave節點。
 

4.安裝與部署(方式一:使用配置文件)

① Redis的編譯安裝

  • 安裝Linux操做系統和GCC編譯
  • 編譯安裝Redis

    解壓:tar -zxvf redis-3.0.5.tar.gz

    make

    make PREFIX=/root/training/redis install

    cp ~/tools/redis-3.0.5/redis.conf /root/training/redis/etc/

② 安裝Ruby環境和Ruby Redis接口

  因爲建立和管理須要使用到redis-trib 工具,該工具位於 Redis 源碼的 src 文件夾中, 它是一個 Ruby 程序, 這個程序經過向實例發送特殊命令來完成建立新集羣,檢查集羣,或者對集羣進行從新分片(reshared)等工做,因此須要安裝Ruby環境和相應的Redis接口

  下面是可使用yum來安裝Ruby

[media]

name=Red Hat Enterprise Linux 7.4

baseurl=file:///cdroom

enabled=1

gpgcheck=1

gpgkey=file:///cdroom/RPM-GPG-KEY-redhat-release

③ 6個節點爲例,安裝和部署Redis Cluster

  • 主節點:637963806381
  • 從節點:638263836384
  • 須要修改的參數以下:其中紅色字體部分須要每一個實例修改。

    daemonize yes

    port 6379

    cluster-enabled yes

    cluster-config-file nodes/nodes-6379.conf

    cluster-node-timeout 15000

    dbfilename dump6379.rdb

    appendonly yes

    appendfilename "appendonly6379.aof"

  • 配置文件一共六個:

    redis6379.conf

    redis6380.conf

    redis6381.conf

    redis6382.conf

    redis6383.conf

    redis6384.conf

④ 啓動Redis 實例

bin/redis-server conf/redis6379.conf

bin/redis-server conf/redis6380.conf

bin/redis-server conf/redis6381.conf

bin/redis-server conf/redis6382.conf

bin/redis-server conf/redis6383.conf

bin/redis-server conf/redis6384.conf

經過ps命令查看進程:

⑤ 使用redis-trib.rb自動部署方式

bin/redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384

 

注意:redis-trib.rb位於 Redis 源碼的 src 文件夾中,拷貝到bin目錄下。

其中:replicas 1 表示咱們但願爲集羣中的每一個主節點建立一個從節點。
 

開始配置集羣:

⑥ 測試Redis Cluster

  • 使用客戶端登陸:bin/redis-cli -c -p 6379

    -c表示:登陸集羣

                可使用:cluster nodes命令查看集羣中的節點 

 

5.安裝與部署(方式二:使用create-cluster命令)

 

將源碼的utils/create-cluster目錄下,將create-cluster拷貝到安裝目錄的bin目錄下

修改create-cluster命令的路徑



  • 啓動和建立Redis集羣
  1. bin/create-cluster start
  2. bin/create-cluster create
  • 使用客戶端測試集羣

6.使用Java程序測試Redis Cluster
  jar包:commons-pool2-2.3.jar   jedis-2.7.0.jar  

import java.util.HashSet;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class TestRedisCluster {

    public static void main(String[] args) throws Exception {
        // 指定集羣的節點
        HashSet<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.56.72", 6379));
        nodes.add(new HostAndPort("192.168.56.72", 6380));
        nodes.add(new HostAndPort("192.168.56.72", 6381));
        nodes.add(new HostAndPort("192.168.56.72", 6382));
        nodes.add(new HostAndPort("192.168.56.72", 6383));
        nodes.add(new HostAndPort("192.168.56.72", 6384));

        // 建立集羣
        JedisCluster cluster = new JedisCluster(nodes);

        // 插入3*16383條數據
        for (int i = 0; i < 3 * 16383; i++) {
            System.out.println("插入數據:" + i);
            cluster.set("mykey" + i, "myvalue:" + i);
        }

        // 關閉集羣客戶端
        cluster.close();
        System.out.println("完成");
    }
}
View Code 

7.基本的Redis Cluster管理

  使用cluster <command> 命令來管理Redis Cluster

命令

說明

info

打印集羣的信息。

nodes

列出集羣當前已知的全部節點(node)的相關信息。

meet <ip> <port>

ipport所指定的節點添加到集羣當中。

addslots <slot> [slot ...]

將一個或多個槽(slot)指派(assign)給當前節點。

delslots <slot> [slot ...]

移除一個或多個槽對當前節點的指派。

slots

列出槽位、節點信息。

slaves <node_id>

列出指定節點下面的從節點信息。

replicate <node_id>

將當前節點設置爲指定節點的從節點。

saveconfig

手動執行命令保存保存集羣的配置文件,集羣默認在配置修改的時候會自動保存配置文件。

keyslot <key>

列出key被放置在哪一個槽上。

flushslots

移除指派給當前節點的全部槽,讓當前節點變成一個沒有指派任何槽的節點。

countkeysinslot <slot>

返回槽目前包含的鍵值對數量。

getkeysinslot <slot> <count>

返回count個槽中的鍵。

setslot <slot> node <node_id>

將槽指派給指定的節點,若是槽已經指派給另外一個節點,那麼先讓另外一個節點刪除該槽,而後再進行指派。  

setslot <slot> migrating <node_id>

將本節點的槽遷移到指定的節點中。

setslot <slot> importing <node_id>

node_id 指定的節點中導入槽 slot 到本節點。

setslot <slot> stable

取消對槽 slot 的導入(import)或者遷移(migrate

failover

手動進行故障轉移。

forget <node_id>

從集羣中移除指定的節點,這樣就沒法完成握手,過時時爲60s60s後兩節點又會繼續完成握手。

reset [HARD|SOFT]

重置集羣信息,soft是清空其餘節點的信息,但不修改本身的idhard還會修改本身的id,不傳該參數則使用soft方式。

count-failure-reports <node_id>

列出某個節點的故障報告的長度。

SET-CONFIG-EPOCH

設置節點epoch,只有在節點加入集羣前才能設置。

 

   命令詳解:cluster info

  命令詳解:cluster nodes(可使用excel 導入命令輸出,方便查看)

  幾點說明:

  • ping-sent: 最近一次發送ping的時間,這個時間是一個unix毫秒時間戳,0表明沒有發送過.
  • pong-recv: 最近一次收到pong的時間,使用unix時間戳表示.
  • config-epoch: 節點的epoch值(or of the current master if the node is a slave)。每當節點發生失敗切換時,都會建立一個新的,獨特的,遞增的epoch。若是多個節點競爭同一個哈希槽時,epoch值更高的節點會搶奪到。

   命令詳解:cluster slots

  其餘幾個命令:

節點的添加與刪除

  • 增長節點(每次添加2個)

① 增長新的配置文件:redis6385.conf redis6386.conf

② 按照以前的配置修改對應參數

③ 啓動新的節點

bin/redis-server conf/redis6385.conf

bin/redis-server conf/redis6386.conf

④ 添加主節點

bin/redis-trib.rb add-node 192.168.56.72:6385 192.168.56.72:6379

  其中:

192.168.56.72:6385是新添加的節點

192.168.56.72:6379是集羣中,任一個舊節點

⑤ 檢查集羣的節點信息

bin/redis-trib.rb check 192.168.56.72:6379

⑥ 添加從節點

bin/redis-trib.rb add-node --slave --master-id f27013eaebcf998078edf1621e4433534f8d8b11 192.168.56.72:6386 192.168.56.72:6379  

其中:

--slave:表示添加的是一個從節點

--master-id:表示該從節點的主節點

192.168.56.72:6386:新添加的從節點

192.168.56.72:6379:是集羣中,任一個舊節點
 

⑦ 從新檢查集羣的狀態信息

bin/redis-trib.rb check 192.168.56.72:6379

 

⑧ 從新分配slot

bin/redis-trib.rb reshard 192.168.56.72:6379

 

⑨ 從新查看集羣的節點槽的信息,能夠看到新添加的節點信息。

cluster slots

或者使用:

bin/redis-trib.rb check 192.168.56.72:6379

 

刪除節點

① 先刪除從節點:

bin/redis-trib.rb del-node 192.168.56.72:6385 21e3e82610ce206708aa8f4189e2c9b2f3d1c540

 

 

② 再刪除主節點

bin/redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01

 

③ 若是出現如下錯誤,須要先清空(移動)該節點上的slot,再刪除

  第一步:bin/redis-trib.rb reshard  192.168.56.72:6386

第二步:bin/redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01

 

④ 從新檢查集羣的信息,發生節點已經被刪除

bin/redis-trib.rb check 192.168.56.72:6379

8.Redis Cluster節點的失敗遷移

① 首先,爲了看到演示的效果,清除一下以前的設置,仍是以六個節點爲例

② 啓動每一個節點,並建立集羣

bin/redis-server conf/redis6379.conf

bin/redis-server conf/redis6380.conf

bin/redis-server conf/redis6381.conf

bin/redis-server conf/redis6382.conf

bin/redis-server conf/redis6383.conf

bin/redis-server conf/redis6384.conf

  bin/redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384

 

③ 檢查集羣狀態

bin/redis-trib.rb check 192.168.56.72:6379
 

④ 殺掉6379上的主節點,並從新檢查集羣的狀態
 

⑤ 稍等一段時間,從新檢查集羣的狀態
 

⑥ 若是從新啓動6379上的實例,它將變成6382的從節點

相關文章
相關標籤/搜索