一、 redis介紹php
a) 什麼是NoSql前端
b) NoSql的分類java
c) 什麼是redisnode
d) Redis應用場景linux
二、 redis安裝(重點)c++
三、 redis客戶端git
a) redis自帶客戶端github
b) 圖形界面的客戶端(瞭解)redis
c) Java客戶端jedis(重點)算法
四、 Redis數據類型(重點)
a) String類型
b) Map類型
c) List類型
d) Set類型
e) SortedSet
五、 Keys命令(瞭解)
六、 Redis的持久化方案
a) Rbd方式
b) Aof方式
七、 Redis的主從複製
八、 Redis的集羣(重點)
九、 Jedis鏈接redis集羣
爲了解決高併發、高可用、高可擴展,大數據存儲等一系列問題而產生的數據庫解決方案,就是NoSql。
NoSql,叫非關係型數據庫,它的全名Not only sql。它不能替代關係型數據庫,只能做爲關係型數據庫的一個良好補充。
n 鍵值(Key-Value)存儲數據庫
相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。
數據模型: 一系列鍵值對
優點: 快速查詢
劣勢: 存儲的數據缺乏結構化
n 列存儲數據庫
相關產品:Cassandra, HBase, Riak
典型應用:分佈式的文件系統
數據模型:以列簇式存儲,將同一列數據存在一塊兒
優點:查找速度快,可擴展性強,更容易進行分佈式擴展
劣勢:功能相對侷限
n 文檔型數據庫
相關產品:CouchDB、MongoDB
典型應用:Web應用(與Key-Value相似,Value是結構化的)
數據模型: 一系列鍵值對
優點:數據結構要求不嚴格
劣勢: 查詢性能不高,並且缺少統一的查詢語法
n 圖形(Graph)數據庫
相關數據庫:Neo4J、InfoGrid、Infinite Graph
典型應用:社交網絡
數據模型:圖結構
優點:利用圖結構相關算法。
劣勢:須要對整個圖作計算才能得出結果,不容易作分佈式的集羣方案。
Redis是使用c語言開發的一個高性能鍵值數據庫。Redis能夠經過一些鍵值類型來存儲數據。
鍵值類型:
String字符類型
map散列類型
list列表類型
set集合類型
sortedset有序集合類型
2008年,意大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人 Salvatore Sanfilippo便 對MySQL的性能感到失望,因而他決定親自爲LLOOGG量身定作一個數據庫,並於2009年開發完成,這個數據庫就是Redis。 不過Salvatore Sanfilippo並不知足只將Redis用於LLOOGG這一款產品,而是但願更多的人使用它,因而在同一年Salvatore Sanfilippo將Redis開源發佈,並開始和Redis的另外一名主要的代碼貢獻者Pieter Noordhuis一塊兒繼續着Redis的開發,直到今天。
Salvatore Sanfilippo本身也沒有想到,短短的幾年時間,Redis就擁有了龐大的用戶羣體。Hacker News在2012年發佈了一份數據庫的使用狀況調查,結果顯示有近12%的公司在使用Redis。國內如新浪微博、街旁網、知乎網,國外如GitHub、Stack Overflow、Flickr等都是Redis的用戶。
VMware公司從2010年開始贊助Redis的開發, Salvatore Sanfilippo和Pieter Noordhuis也分別在3月和5月加入VMware,全職開發Redis。
緩存(數據查詢、短鏈接、新聞內容、商品內容等等)。(最多使用)
分佈式集羣架構中的session分離。
聊天室的在線好友列表。
任務隊列。(秒殺、搶購、12306等等)
應用排行榜。
網站訪問統計。
數據過時處理(能夠精確到毫秒)
官網地址:http://redis.io/
下載地址:http://download.redis.io/releases/redis-3.0.0.tar.gz
Redis 沒有官方的Windows版本,可是微軟開源技術團隊(Microsoft Open Tech group)開發和維護着這個 Win64 的版本,
下載地址:https://github.com/MicrosoftArchive/redis/releases
redis的安裝環境能夠安裝到Windows或 linux系統中。
Windows安裝
安裝下載的Redis-x64-3.2.100.msi,或直接解壓免安裝版
打開 cmd ,跳轉到安裝目錄或解壓目錄。
啓動 redis
打開Redis自帶的客戶端
執行相關操做:
後端安裝服務,能夠避免手動啓動Redis
redis-server --service-install redis.windows.conf --service-name Redis
卸載Redis 服務
管理員身份運行命令行,輸入命令
查看版本:
linux安裝
第一步:安裝VMware,而且在VMware中安裝centos系統(參考linux教程)。
第二步:將redis的壓縮包,上傳到linux系統
第三步:對redis的壓縮包進行解壓縮
Redis解壓縮以後的文件是用c語言寫的源碼文件
[root@itheima ~]# tar -zxf redis-3.0.0.tar.gz
第四步:安裝c語言環境(安裝centos以後,自帶c語言環境)
[root@itheima ~]# yum install gcc-c++
第五步:編譯redis源碼
[root@itheima ~]# cd redis-3.0.0
[root@itheima redis-3.0.0]# make
第六步:安裝redis
[root@itheima redis-3.0.0]# make install PREFIX=/usr/local/redis19
第七步:查看是否安裝成功
前端啓動的命令:
[root@itheima bin]# ./redis-server
前端啓動的關閉:
強制關閉:Ctrl+c
正常關閉:[root@itheima bin]# ./redis-cli shutdown
啓動界面:
前端啓動的問題:
一旦客戶端關閉,則redis服務也停掉。
第一步:須要將redis解壓以後的源碼包中的redis.conf文件拷貝到bin目錄下
[root@itheima bin]# cp /root/redis-3.0.0/redis.conf ./
第二步:修改redis.conf文件,將daemonize改成yes
先要使用vim redis.conf
第三步:使用命令後端啓動redis
[root@itheima bin]# ./redis-server redis.conf
第四步:查看是否啓動成功
關閉後端啓動的方式:
強制關閉:[root@itheima bin]# kill -9 5071
正常關閉:[root@itheima bin]# ./redis-cli shutdown
在項目中,建議使用正常關閉。
由於redis做爲緩存來使用的話,將數據存儲到內存中,若是使用正常關閉,則會將內存數據持久化到本地以後,再關閉。
若是是強制關閉,則不會進行持久化操做,可能會形成部分數據的丟失。
l 啓動
啓動客戶端命令:[root@itheima bin]# ./redis-cli -h 127.0.0.1 -p 6379
-h:指定訪問的redis服務器的ip地址
-p:指定訪問的redis服務器的port端口
還能夠寫成:[root@itheima bin]# ./redis-cli
使用默認配置:默認的ip【127.0.0.1】,默認的port【6379】
l 關閉
Ctrl+c
127.0.0.1:6379> quit
容許遠程鏈接Redis,修改redis.windows.conf文件
安裝文件位置:
安裝以後,打開以下:
防火牆設置:
[root@itheima redis-3.0.0]# vim /etc/sysconfig/iptables # Firewall configuration written by system-config-firewall # Manual customization of this file is not recommended. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "/etc/sysconfig/iptables" 16L, 677C 已寫入 [root@itheima redis-3.0.0]# service iptables restart iptables:清除防火牆規則: [肯定] iptables:將鏈設置爲政策 ACCEPT:filter [肯定] iptables:正在卸載模塊: [肯定] iptables:應用防火牆規則: [肯定] [root@itheima redis-3.0.0]# |
Redis.conf中的數據庫數量的設置:
選擇數據庫的方式:
使用select 加上數據庫的下標 就能夠選擇指定的數據庫來使用,下標從0開始
127.0.0.1:6379> select 15
OK
127.0.0.1:6379[15]>
Redis不只是使用命令來操做,如今基本上主流的語言都有客戶端支持,好比java、C、C#、C++、php、Node.js、Go等。
在官方網站裏列一些Java的客戶端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推薦使用Jedis和Redisson。 在企業中用的最多的就是Jedis,下面咱們就重點學習下Jedis。
Jedis一樣也是託管在github上,地址:https://github.com/xetorthio/jedis
添加jar包
//Redis服務器IP
private static String ADDR = "127.0.0.1";
//Redis的端口號
private static int PORT = 6379;
//可用鏈接實例的最大數目,默認值爲8;若是賦值爲-1,則表示不限制;若是pool已經分配了maxActive個jedis實例,則此時pool的狀態爲exhausted(耗盡)。
private static int MAX_ACTIVE = 1024;
//控制一個pool最多有多少個狀態爲idle(空閒的)的jedis實例,默認值也是8。
private static int MAX_IDLE = 200;
//等待可用鏈接的最大時間,單位毫秒,默認值爲-1,表示永不超時。若是超過等待時間,則直接拋出JedisConnectionException;
private static int MAX_WAIT = 10000;
//在borrow一個jedis實例時,是否提早進行validate操做;若是爲true,則獲得的jedis實例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT);
} catch (Exception e) {
e.printStackTrace();
}
}
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 鏈接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大鏈接數 --> <property name="maxTotal" value="30" /> <!-- 最大空閒鏈接數 --> <property name="maxIdle" value="10" /> <!-- 每次釋放鏈接的最大數目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 釋放鏈接的掃描間隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 鏈接最小空閒時間 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 鏈接空閒多久後釋放, 當空閒時間>該值 且 空閒鏈接>最大空閒鏈接數 時直接釋放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 獲取鏈接時的最大等待毫秒數,小於零:阻塞不肯定的時間,默認-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在獲取鏈接的時候檢查有效性, 默認false --> <property name="testOnBorrow" value="false" /> <!-- 在空閒時檢查有效性, 默認false --> <property name="testWhileIdle" value="true" /> <!-- 鏈接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true --> <property name="blockWhenExhausted" value="false" /> </bean>
<!-- redis單機 經過鏈接池 --> <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="close"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="192.168.242.130" /> <constructor-arg name="port" value="6379" /> </bean> </beans> |
@Test public void testJedisPool() { JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool"); Jedis jedis = null; try { jedis = pool.getResource();
jedis.set("name", "lisi"); String name = jedis.get("name"); System.out.println(name); } catch (Exception ex) { ex.printStackTrace(); } finally { if (jedis != null) { // 關閉鏈接 jedis.close(); } } } |
語法:SET key value
127.0.0.1:6379> set test 123 OK |
語法:GET key
127.0.0.1:6379> get test "123「 |
語法:GETSET key value
127.0.0.1:6379> getset s2 222 "111" 127.0.0.1:6379> get s2 "222" |
語法:
MSET key value [key value …]
MGET key [key …]
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> mget k1 k3 1) "v1" 2) "v3" |
語法:DEL key
127.0.0.1:6379> del test (integer) 1 |
n 遞增數字
當存儲的字符串是整數時,Redis提供了一個實用的命令INCR,其做用是讓當前鍵值遞增,並返回遞增後的值。
語法:INCR key
127.0.0.1:6379> incr num (integer) 1 127.0.0.1:6379> incr num (integer) 2 127.0.0.1:6379> incr num (integer) 3 |
n 增長指定的整數
語法:INCRBY key increment
127.0.0.1:6379> incrby num 2 (integer) 5 127.0.0.1:6379> incrby num 2 (integer) 7 127.0.0.1:6379> incrby num 2 (integer) 9 |
n 遞減數值
語法:DECR key
127.0.0.1:6379> decr num (integer) 9 127.0.0.1:6379> decr num (integer) 8 |
n 減小指定的整數
語法:DECRBY key decrement
127.0.0.1:6379> decr num (integer) 6 127.0.0.1:6379> decr num (integer) 5 127.0.0.1:6379> decrby num 3 (integer) 2 127.0.0.1:6379> decrby num 3 (integer) -1 |
APPEND的做用是向鍵值的末尾追加value。若是鍵不存在則將該鍵的值設置爲value,即至關於 SET key value。返回值是追加後字符串的總長度。
語法:APPEND key value
127.0.0.1:6379> set str hello OK 127.0.0.1:6379> append str " world!" (integer) 12 127.0.0.1:6379> get str "hello world!" |
STRLEN命令返回鍵值的長度,若是鍵不存在則返回0。
語法:STRLEN key
127.0.0.1:6379> strlen str (integer) 0 127.0.0.1:6379> set str hello OK 127.0.0.1:6379> strlen str (integer) 5
|
商品編號、訂單號採用string的遞增數字特性生成。
定義商品編號key:items:id
192.168.101.3:7003> INCR items:id
(integer) 2
192.168.101.3:7003> INCR items:id
(integer) 3
散列類型
假設有User對象以JSON序列化的形式存儲到Redis中,User對象有id,username、password、age、name等屬性,存儲的過程以下:
保存、更新:
User對象 à json(string) à redis
若是在業務上只是更新age屬性,其餘的屬性並不作更新我應該怎麼作呢? 若是仍然採用上邊的方法在傳輸、處理時會形成資源浪費,下邊講的hash能夠很好的解決這個問題。
hash叫散列類型,它提供了字段和字段值的映射。字段值只能是字符串類型,不支持散列類型、集合類型等其它類型。以下:
HSET命令不區分插入和更新操做,當執行插入操做時HSET命令返回1,當執行更新操做時返回0。
語法:HSET key field value
127.0.0.1:6379> hset user username zhangsan (integer) 1 |
語法:HMSET key field value [field value ...]
127.0.0.1:6379> hmset user age 20 username lisi OK |
語法:HSETNX key field value
127.0.0.1:6379> hsetnx user age 30若是user中沒有age字段則設置age值爲30,不然不作任何操做 (integer) 0 |
語法:HGET key field
127.0.0.1:6379> hget user username "zhangsan「 |
語法:HMGET key field [field ...]
127.0.0.1:6379> hmget user age username 1) "20" 2) "lisi" |
語法:HGETALL key
127.0.0.1:6379> hgetall user 1) "age" 2) "20" 3) "username" 4) "lisi" |
能夠刪除一個或多個字段,返回值是被刪除的字段個數
語法:HDEL key field [field ...]
127.0.0.1:6379> hdel user age (integer) 1 127.0.0.1:6379> hdel user age name (integer) 0 127.0.0.1:6379> hdel user age username (integer) 1 |
語法:HINCRBY key field increment
127.0.0.1:6379> hincrby user age 2將用戶的年齡加2 (integer) 22 127.0.0.1:6379> hget user age獲取用戶的年齡 "22「 |
語法:HEXISTS key field
127.0.0.1:6379> hexists user age查看user中是否有age字段 (integer) 1 127.0.0.1:6379> hexists user name查看user中是否有name字段 (integer) 0 |
語法:
HKEYS key
HVALS key
127.0.0.1:6379> hmset user age 20 name lisi OK 127.0.0.1:6379> hkeys user 1) "age" 2) "name" 127.0.0.1:6379> hvals user 1) "20" 2) "lisi" |
語法:HLEN key
127.0.0.1:6379> hlen user (integer) 2 |
【商品id、商品名稱、商品描述、商品庫存、商品好評】
商品1001的信息在 Redis中的key爲:[items:1001]
192.168.101.3:7003> HMSET items:1001 id 3 name apple price 999.9 OK |
192.168.101.3:7003> HGET items:1001 id "3" 192.168.101.3:7003> HGETALL items:1001 1) "id" 2) "3" 3) "name" 4) "apple" 5) "price" 6) "999.9" |
Arraylist是使用數組來存儲數據,特色:遍歷快、增刪慢
Linkedlist是使用雙向鏈表存儲數據,特色:增刪快、查詢慢,可是查詢鏈表兩端的數據也很快。
Redis的list是採用的是鏈表結構來存儲的,因此對於redis的list數據類型的操做,是操做list的兩端數據來操做的。
語法:LPUSH key value [value ...] left push
127.0.0.1:6379> lpush list 1 2 3 (integer) 3 |
語法:RPUSH key value [value ...]
127.0.0.1:6379> rpush list 4 5 6 (integer) 3 |
LRANGE命令是列表類型最經常使用的命令之一,獲取列表中的某一片斷,將返回start、stop之間的全部元素(包含兩端的元素),索引從0開始。索引能夠是負數,如:「-1」表明最後邊的一個元素。
語法:LRANGE key start stop
127.0.0.1:6379> lrange list 0 2 1) "2" 2) "1" 3) "4"
127.0.0.1:6379> lrange list 0 -1 |
LPOP命令從列表左邊彈出一個元素,會分兩步完成:
第一步是將列表左邊的元素從列表中移除
第二步是返回被移除的元素值。
語法:
LPOP key
RPOP key
127.0.0.1:6379> lpop list "3「 127.0.0.1:6379> rpop list "6「 |
語法:LLEN key
127.0.0.1:6379> llen list (integer) 2 |
LREM命令會刪除列表中前count個值爲value的元素,返回實際刪除的元素個數。根據count值的不一樣,該命令的執行方式會有所不一樣:
l 當count>0時, LREM會從列表左邊開始刪除。
l 當count<0時, LREM會從列表後邊開始刪除。
l 當count=0時, LREM刪除全部值爲value的元素。
語法:LREM key count value
語法:LINDEX key index
127.0.0.1:6379> lindex l:list 2 "1" |
語法:LSET key index value
127.0.0.1:6379> lset l:list 2 2 OK 127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "2" 4) "2" |
指定範圍和LRANGE一致
語法:LTRIM key start stop
127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "0" 4) "2" 127.0.0.1:6379> ltrim l:list 0 2 OK 127.0.0.1:6379> lrange l:list 0 -1 1) "6" 2) "5" 3) "0" |
該命令首先會在列表中從左到右查找值爲pivot的元素,而後根據第二個參數是BEFORE仍是AFTER來決定將value插入到該元素的前面仍是後面。
語法:LINSERT key BEFORE|AFTER pivot value
127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "2" 3) "1" 127.0.0.1:6379> linsert list after 3 4 (integer) 4 127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "4" 3) "2" 4) "1" |
語法:RPOPLPUSH source destination
127.0.0.1:6379> rpoplpush list newlist "1" 127.0.0.1:6379> lrange newlist 0 -1 1) "1" 127.0.0.1:6379> lrange list 0 -1 1) "3" 2) "4" 3) "2" |
思路:
在Redis中建立商品評論列表
用戶發佈商品評論,將評論信息轉成json存儲到list中。
用戶在頁面查詢評論列表,從redis中取出json數據展現到頁面。
定義商品評論列表key:
商品編號爲1001的商品評論key【items: comment:1001】
192.168.101.3:7001> LPUSH items:comment:1001 '{"id":1,"name":"商品不錯,很好!!","date":1430295077289}' |
集合類型
集合類型:無序、不可重複
列表類型:有序、可重複
語法:SADD key member [member ...]
127.0.0.1:6379> sadd set a b c (integer) 3 127.0.0.1:6379> sadd set a (integer) 0 |
語法:SREM key member [member ...]
127.0.0.1:6379> srem set c d (integer) 1 |
語法:SMEMBERS key
127.0.0.1:6379> smembers set 1) "b" 2) "a」 |
語法:SISMEMBER key member
127.0.0.1:6379> sismember set a (integer) 1 127.0.0.1:6379> sismember set h (integer) 0 |
屬於A而且不屬於B的元素構成的集合。
語法:SDIFF key [key ...]
127.0.0.1:6379> sadd setA 1 2 3 (integer) 3 127.0.0.1:6379> sadd setB 2 3 4 (integer) 3 127.0.0.1:6379> sdiff setA setB 1) "1" 127.0.0.1:6379> sdiff setB setA 1) "4" |
屬於A且屬於B的元素構成的集合。
語法:SINTER key [key ...]
127.0.0.1:6379> sinter setA setB 1) "2" 2) "3" |
屬於A或者屬於B的元素構成的集合
語法:SUNION key [key ...]
127.0.0.1:6379> sunion setA setB 1) "1" 2) "2" 3) "3" 4) "4" |
語法:SCARD key
127.0.0.1:6379> smembers setA 1) "1" 2) "2" 3) "3" 127.0.0.1:6379> scard setA (integer) 3 |
注意:因爲集合是無序的,全部SPOP命令會從集合中隨機選擇一個元素彈出
語法:SPOP key
127.0.0.1:6379> spop setA "1「 |
Sortedset又叫zset
Sortedset是有序集合,可排序的,可是惟一。
Sortedset和set的不一樣之處,是會給set中的元素添加一個分數,而後經過這個分數進行排序。
向有序集合中加入一個元素和該元素的分數,若是該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含以前已經存在的元素。
語法:ZADD key score member [score member ...]
127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu (integer) 3 127.0.0.1:6379> zadd scoreboard 97 lisi (integer) 0 |
語法:ZSCORE key member
127.0.0.1:6379> zscore scoreboard lisi "97" |
移除有序集key中的一個或多個成員,不存在的成員將被忽略。
當key存在但不是有序集類型時,返回一個錯誤。
語法:ZREM key member [member ...]
127.0.0.1:6379> zrem scoreboard lisi (integer) 1 |
得到排名在某個範圍的元素列表
語法:ZRANGE key start stop [WITHSCORES]
127.0.0.1:6379> zrange scoreboard 0 2 1) "zhangsan" 2) "wangwu" 3) "lisi「 |
語法:ZREVRANGE key start stop [WITHSCORES]
127.0.0.1:6379> zrevrange scoreboard 0 2 1) " lisi " 2) "wangwu" 3) " zhangsan 「 |
若是須要得到元素的分數的能夠在命令尾部加上WITHSCORES參數
127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES 1) "zhangsan" 2) "80" 3) "wangwu" 4) "94" |
語法:ZRANK key member
127.0.0.1:6379> ZRANK scoreboard lisi (integer) 0 |
語法:ZREVRANK key member
127.0.0.1:6379> ZREVRANK scoreboard zhangsan (integer) 1 |
語法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES 1) "wangwu" 2) "94" 3) "lisi" 4) "97" 127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2 1) "wangwu" 2) "lisi" |
返回值是更改後的分數
語法:ZINCRBY key increment member
127.0.0.1:6379> ZINCRBY scoreboard 4 lisi "101「 |
語法:ZCARD key
127.0.0.1:6379> ZCARD scoreboard (integer) 3 |
語法:ZCOUNT key min max
127.0.0.1:6379> ZCOUNT scoreboard 80 90 (integer) 1 |
語法:ZREMRANGEBYRANK key start stop
127.0.0.1:6379> ZREMRANGEBYRANK scoreboard 0 1 (integer) 2 127.0.0.1:6379> ZRANGE scoreboard 0 -1 1) "lisi" |
語法:ZREMRANGEBYSCORE key min max
127.0.0.1:6379> zadd scoreboard 84 zhangsan (integer) 1 127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100 (integer) 1 |
需求:根據商品銷售量對商品進行排行顯示
思路:定義商品銷售排行榜(sorted set集合),Key爲items:sellsort,分數爲商品銷售量。
寫入商品銷售量:
192.168.101.3:7007> ZADD items:sellsort 9 1001 10 1002 |
192.168.101.3:7001> ZINCRBY items:sellsort 1 1001 |
192.168.101.3:7001> ZRANGE items:sellsort 0 9 withscores |
返回知足給定pattern 的全部key
redis 127.0.0.1:6379> keys mylist* 1) "mylist" 2) "mylist5" 3) "mylist6" 4) "mylist7" 5) "mylist8" |
確認一個key 是否存在
示例:從結果來看,數據庫中不存在HongWan 這個key,可是age 這個key 是存在的
redis 127.0.0.1:6379> exists HongWan (integer) 0 redis 127.0.0.1:6379> exists age (integer) 1 redis 127.0.0.1:6379> |
刪除一個key
redis 127.0.0.1:6379> del age (integer) 1 redis 127.0.0.1:6379> exists age (integer) 0 |
重命名key
示例:age 成功的被咱們更名爲age_new 了
redis 127.0.0.1:6379[1]> keys * 1) "age" redis 127.0.0.1:6379[1]> rename age age_new OK redis 127.0.0.1:6379[1]> keys * 1) "age_new" redis 127.0.0.1:6379[1]> |
返回值的類型
示例:這個方法能夠很是簡單的判斷出值的類型
redis 127.0.0.1:6379> type addr string redis 127.0.0.1:6379> type myzset2 zset redis 127.0.0.1:6379> type mylist list redis 127.0.0.1:6379> |
Redis在實際使用過程當中更多的用做緩存,然而緩存的數據通常都是須要設置生存時間的,即:到期後數據銷燬。
EXPIRE key seconds 設置key的生存時間(單位:秒)key在多少秒後會自動刪除 TTL key 查看key生於的生存時間 PERSIST key清除生存時間 PEXPIRE key milliseconds生存時間設置單位爲:毫秒 |
例子:
192.168.101.3:7002> set test 1設置test的值爲1 OK 192.168.101.3:7002> get test獲取test的值 "1" 192.168.101.3:7002> EXPIRE test 5設置test的生存時間爲5秒 (integer) 1 192.168.101.3:7002> TTL test查看test的生於生成時間還有1秒刪除 (integer) 1 192.168.101.3:7002> TTL test (integer) -2 192.168.101.3:7002> get test獲取test的值,已經刪除 (nil)
|
Redis默認的方式,redis經過快照來將數據持久化到磁盤中。
在redis.conf中修改持久化快照的條件,以下:
在900秒(15分鐘)內有一次操做,則把內存中的數據寫入到Redis存儲數據的磁盤文件中。
在300秒(5分鐘)內有10次操做,則把內存中的數據寫入到Redis存儲數據的磁盤文件中。
在60秒內有10000次操做,則把內存中的數據寫入到Redis存儲數據的磁盤文件中。
數據只有寫入到磁盤中,才能在下一次服務器啓動後,繼續操做之前的數據。
在redis.conf中能夠指定持久化文件存儲的目錄
一旦redis非法關閉,那麼會丟失最後一次持久化以後的數據。
若是數據不重要,則沒必要要關心。
若是數據不能容許丟失,那麼要使用aof方式。
Redis默認是不使用該方式持久化的。Aof方式的持久化,是操做一次redis數據庫,則將操做的記錄存儲到aof持久化文件中。
第一步:開啓aof方式的持久化方案
將redis.conf中的appendonly改成yes,即開啓aof方式的持久化方案。
第二步:Aof文件存儲的目錄和rdb方式的同樣。 Aof文件存儲的名稱
第三步:根據配置文件啓動Redis服務及客戶端。
redis-server redis.windows.conf
服務啓動後,自動在相關的目錄下建立appendonly.aof數據存儲文件。
在使用aof和rdb方式時,若是redis重啓,則數據從aof文件加載。
持久化保證了即便redis服務重啓也不會丟失數據,由於redis服務重啓後會將硬盤上持久化的數據恢復到內存中,可是當redis服務器的硬盤損壞了可能會致使數據丟失,若是經過redis的主從複製機制就能夠避免這種單點故障,以下圖:
說明:
n 主redis中的數據有兩個副本(replication)即從redis1和從redis2,即便一臺redis服務器宕機其它兩臺redis服務也能夠繼續提供服務。
n 主redis中的數據和從redis上的數據保持實時同步,當主redis寫入數據時經過主從複製機制會複製到兩個從redis服務上。
n 只有一個主redis,能夠有多個從redis。
n 主從複製不會阻塞master,在同步數據時,master 能夠繼續處理client 請求
n 一個redis能夠便是主又是從,以下圖:
無需配置
Windows系統配置
第一步:複製從機
第二步:修改從機的redis.windows.conf文件,主機不須要任何修改。
第三步:修改 從機的port 端口:6380,6381..
第四步:修改從機的配置中的 slaveof配置
第五步:啓動主機 redis-server redis.windows.conf
第六步:啓動兩臺從機 ,分別進入到從機的bin目錄下,執行啓動命令。
第七步:啓動主機客戶端,操做數據
第八步:啓動從機客戶端查看數據,是否同步。
另:在RedisDesktopManager圖形界面客戶端中也能夠看到數據。
linux系統配置
第一步:複製出兩個從機
[root@itheima redis19]# cp bin/ bin2 –r
第二步:修改從機的redis.conf
語法:Slaveof masterip masterport
slaveof 192.168.242.137 6379
第三步:修改從機的port地址爲6380
在redis.conf中修改
第四步:清除從機中的持久化文件
[root@itheima bin2]# rm -rf appendonly.aof dump.rdb
第五步:啓動從機
[root@itheima bin2]# ./redis-server redis.conf
第六步:啓動6380的客戶端
[root@itheima bin2]# ./redis-cli -p 6380
注意:
主機一旦發生增刪改操做,那麼從機會將數據同步到從機中
從機不能執行寫操做
127.0.0.1:6380> set s2 222 (error) READONLY You can't write against a read only slave. |
架構細節:
(1)全部的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
(2)節點的fail是經過集羣中超過半數的節點檢測失效時才生效.
(3)客戶端與redis節點直連,不須要中間proxy層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可
(4)redis-cluster把全部的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->value
Redis 集羣中內置了 16384 個哈希槽,當須要在 Redis 集羣中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大體均等的將哈希槽映射到不一樣的節點
示例以下:
(1)集羣中全部master參與投票,若是半數以上master節點與其中一個master節點通訊超過(cluster-node-timeout),認爲該master節點掛掉.
(2):何時整個集羣不可用(cluster_state:fail)?
集羣管理工具(redis-trib.rb)是使用ruby腳本語言編寫的。
第一步:安裝ruby
[root@itheima bin2]# yum install ruby
[root@itheima bin2]# yum install rubygems
第二步:將如下文件上傳到linux系統
第三步:安裝ruby和redis接口
[root@itheima ~]# gem install redis-3.0.0.gem
第四步:將redis-3.0.0包下src目錄中的如下文件拷貝到redis19/redis-cluster/
[root@itheima src]# cd /usr/local/redis19/
[root@itheima redis19]# mkdir redis-cluster
[root@itheima redis19]# cd /root/redis-3.0.0/src/
[root@itheima src]# cp redis-trib.rb /usr/local/redis19/redis-cluster
第五步:查看是否拷貝成功
搭建集羣最少也得須要3臺主機,若是每臺主機再配置一臺從機的話,則最少須要6臺機器。
建立6個目錄配置Redis服務:
Windows系統
安裝ruby, 安裝過程當中有一個界面出現三個複選框架,要勾選第二個複選框。
安裝ruby與Redis的接口驅動 gem文件
安裝方法:在redis目錄下運行:
D:\Redis>gem install --local F:\GZE-JY-JV-20180315-01班\redis\資料\ruby\redis-3.2.2.gem
成功:
拷貝文件到Redis目錄下:
以下:
配置 6個Redis:
修改每一個目錄中的配置文件:redis.windows.conf ,須要修改的內容以下:
port 6380 #端口號
appendonly yes #數據的保存爲aof格式
cluster-enabled yes #是否開啓集羣
cluster-config-file nodes.6380.conf #集羣配置信息保存文件
cluster-node-timeout 15000 #集羣節點時長
配置6個Redis服務。
任務管理器中查看建立的服務
啓動6個Redis服務
查看
啓動集羣
D:\Redis>redis-trib.rb create --replicas 1 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385
注意:D:\Redis>redis-trib.rb create --replicas 命令後的:1。 若是是 0 則表示6臺機器都是主機,若是是 1 ,則表示前3臺是主機,後 3臺是從機,主機與從機按順序匹配, 6380:6383 ,6381:6384 , 6382:6385
Redis目錄中的結果
信息文件:
查看集羣信息:redis-trib.rb check 127.0.0.1:6380 能夠鏈接任何一臺機器。
測試集羣:
Linux系統
端口設計以下:7001-7006
第一步:複製出一個7001機器
[root@itheima redis19]# cp bin ./redis-cluster/7001 –r
第二步:若是存在持久化文件,則刪除
[root@itheima 7001]# rm -rf appendonly.aof dump.rdb
第三步:設置集羣參數
第四步:修改端口
第五步:複製出7002-7006機器
[root@itheima redis-cluster]# cp 7001/ 7002 -r
[root@itheima redis-cluster]# cp 7001/ 7003 -r
[root@itheima redis-cluster]# cp 7001/ 7004 -r
[root@itheima redis-cluster]# cp 7001/ 7005 -r
[root@itheima redis-cluster]# cp 7001/ 7006 –r
第六步:修改7002-7006機器的端口
第七步:啓動7001-7006這六臺機器
第八步:修改start-all.sh文件的權限
[root@itheima redis-cluster]# chmod u+x start-all.sh
[root@itheima redis-cluster]# ./start-all.sh
第九步:建立集羣
[root@itheima redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.242.137:7001 192.168.242.137:7002 192.168.242.137:7003 192.168.242.137:7004 192.168.242.137:7005 192.168.242.137:7006 >>> Creating cluster Connecting to node 192.168.242.137:7001: OK Connecting to node 192.168.242.137:7002: OK Connecting to node 192.168.242.137:7003: OK Connecting to node 192.168.242.137:7004: OK Connecting to node 192.168.242.137:7005: OK Connecting to node 192.168.242.137:7006: OK >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 192.168.242.137:7001 192.168.242.137:7002 192.168.242.137:7003 Adding replica 192.168.242.137:7004 to 192.168.242.137:7001 Adding replica 192.168.242.137:7005 to 192.168.242.137:7002 Adding replica 192.168.242.137:7006 to 192.168.242.137:7003 M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001 slots:0-5460 (5461 slots) master M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002 slots:5461-10922 (5462 slots) master M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003 slots:10923-16383 (5461 slots) master S: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004 replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 S: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005 replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7 S: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006 replicates cb7c5def8f61df2016b38972396a8d1f349208c2 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join.. >>> Performing Cluster Check (using node 192.168.242.137:7001) M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001 slots:0-5460 (5461 slots) master M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002 slots:5461-10922 (5462 slots) master M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003 slots:10923-16383 (5461 slots) master M: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004 slots: (0 slots) master replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 M: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005 slots: (0 slots) master replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7 M: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006 slots: (0 slots) master replicates cb7c5def8f61df2016b38972396a8d1f349208c2 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@itheima redis-cluster]# |
[root@itheima 7001]# ./redis-cli -h 192.168.242.137 -p 7001 –c
-c:指定是集羣鏈接
l 查看集羣信息
l 192.168.242.137:7002> cluster info l cluster_state:ok l cluster_slots_assigned:16384 l cluster_slots_ok:16384 l cluster_slots_pfail:0 l cluster_slots_fail:0 l cluster_known_nodes:6 l cluster_size:3 l cluster_current_epoch:6 l cluster_my_epoch:2 l cluster_stats_messages_sent:2372 l cluster_stats_messages_received:2372 l 192.168.242.137:7002> |
l 查看集羣節點
l 192.168.242.137:7002> cluster nodes l 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001 master - 0 1451581348093 1 connected 0-5460 l cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003 master - 0 1451581344062 3 connected 10923-16383 l 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004 slave 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 0 1451581351115 1 connected l a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006 slave cb7c5def8f61df2016b38972396a8d1f349208c2 0 1451581349101 3 connected l 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002 myself,master - 0 0 2 connected 5461-10922 l cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005 slave 4f52a974f64343fd9f1ee0388490b3c0647a4db7 0 1451581350108 5 connected |
[root@itheima redis-cluster]# vim /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT # Firewall configuration written by system-config-firewall # Manual customization of this file is not recommended. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7001 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7002 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7003 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7004 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7005 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7006 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 7007 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT ~ ~ ~ ~ "/etc/sysconfig/iptables" 23L, 1146C 已寫入 [root@itheima redis-cluster]# service iptables restart iptables:清除防火牆規則: [肯定] iptables:將鏈設置爲政策 ACCEPT:filter [肯定] iptables:正在卸載模塊: [肯定] iptables:應用防火牆規則: [肯定] [root@itheima redis-cluster]# |
<!-- 鏈接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大鏈接數 --> <property name="maxTotal" value="30" /> <!-- 最大空閒鏈接數 --> <property name="maxIdle" value="10" /> <!-- 每次釋放鏈接的最大數目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 釋放鏈接的掃描間隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 鏈接最小空閒時間 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 鏈接空閒多久後釋放, 當空閒時間>該值 且 空閒鏈接>最大空閒鏈接數 時直接釋放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 獲取鏈接時的最大等待毫秒數,小於零:阻塞不肯定的時間,默認-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在獲取鏈接的時候檢查有效性, 默認false --> <property name="testOnBorrow" value="true" /> <!-- 在空閒時檢查有效性, 默認false --> <property name="testWhileIdle" value="true" /> <!-- 鏈接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true --> <property name="blockWhenExhausted" value="false" /> </bean> <!-- redis集羣 --> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg index="0"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7001"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7002"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7003"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7004"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7005"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.101.3"></constructor-arg> <constructor-arg index="1" value="7006"></constructor-arg> </bean> </set> </constructor-arg> <constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg> </bean> |
private ApplicationContext applicationContext; @Before public void init() { applicationContext = new ClassPathXmlApplicationContext( "classpath:applicationContext.xml"); } // redis集羣 @Test public void testJedisCluster() { JedisCluster jedisCluster = (JedisCluster) applicationContext .getBean("jedisCluster");
jedisCluster.set("name", "zhangsan"); String value = jedisCluster.get("name"); System.out.println(value); } |