爲了解決高併發、高可用、高可擴展,大數據存儲等一系列問題而產生的數據庫解決方案,就是NoSql。php
NoSql,叫非關係型數據庫,它的全名Not only sql。它不能替代關係型數據庫,只能做爲關係型數據庫的一個良好補充。前端
鍵值(Key-Value)存儲數據庫 相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。 數據模型: 一系列鍵值對 優點: 快速查詢 劣勢: 存儲的數據缺乏結構化java
列存儲數據庫 相關產品:Cassandra, HBase, Riak 典型應用:分佈式的文件系統 數據模型:以列簇式存儲,將同一列數據存在一塊兒 優點:查找速度快,可擴展性強,更容易進行分佈式擴展 劣勢:功能相對侷限node
文檔型數據庫 相關產品:CouchDB、MongoDB 典型應用:Web應用(與Key-Value相似,Value是結構化的) 數據模型: 一系列鍵值對 優點:數據結構要求不嚴格 劣勢: 查詢性能不高,並且缺少統一的查詢語法linux
圖形(Graph)數據庫 相關數據庫:Neo4J、InfoGrid、Infinite Graph 典型應用:社交網絡 數據模型:圖結構 優點:利用圖結構相關算法。 劣勢:須要對整個圖作計算才能得出結果,不容易作分佈式的集羣方案。c++
Redis是使用c語言開發的一個高性能鍵值數據庫。Redis能夠經過一些鍵值類型來存儲數據。 鍵值類型: String字符類型 map散列類型 list列表類型 set集合類型 sortedset有序集合類型git
2008年,意大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人 Salvatore Sanfilippo便 對MySQL的性能感到失望,因而他決定親自爲LLOOGG量身定作一個數據庫,並於2009年開發完成,這個數據庫就是Redis。 不過Salvatore Sanfilippo並不知足只將Redis用於LLOOGG這一款產品,而是但願更多的人使用它,因而在同一年Salvatore Sanfilippo將Redis開源發佈,並開始和Redis的另外一名主要的代碼貢獻者Pieter Noordhuis一塊兒繼續着Redis的開發,直到今天。github
Salvatore Sanfilippo本身也沒有想到,短短的幾年時間,Redis就擁有了龐大的用戶羣體。Hacker News在2012年發佈了一份數據庫的使用狀況調查,結果顯示有近12%的公司在使用Redis。國內如新浪微博、街旁網、知乎網,國外如GitHub、Stack Overflow、Flickr等都是Redis的用戶。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
#sftp 上傳安裝包到linux
#解壓
tar -zxvf redis.3.0.0.tar.gz
#安裝c語言環境
sudo apt-get install gcc-c++
#編譯
cd redis-3.0.0
make
#安裝
make install PREFIX = /usr/local/redis
# 查看
cd /usr/local/redis
ls
複製代碼
./redis-server
ctrl+c
正常關閉 ./redis-cli shutdown
**tips:**一旦客戶端關閉,則redis服務也會停掉
cp /root/redis-3.0.0/redis.conf
vim redis.conf
./redis-server redis.conf
ps -aux | grep redis
kill -9 進程號
正常關閉:./redis-cli shutdown
./redis-cli -h 127.0.0.1 -p 6379
-h 指定訪問 redis 服務器的 ip 地址 -p 指定訪問的 redis 服務器的 port 端口 還能夠寫成 ./redis-cli 使用默認配置,默認ip 127.0.0.1,默認端口 6379redis-desktop-manager 打開以下:
選擇數據庫方式: 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
添加 spring 的 jar 包 配置 spring 配置文件 applicationContext.xml
<?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 test 321
"123"
127.0.0.1:6379> get test
"321"
複製代碼
設置獲取多個鍵值 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> mget k1 k2
1) "v1"
2) "v2"
複製代碼
刪除 del key
127.0.0.1:6379> del test
(integer) 1
複製代碼
數值增減
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
127.0.0.1:6379> incr num
(integer) 4
複製代碼
127.0.0.1:6379> incrby num 2
(integer) 8
127.0.0.1:6379> incrby num 2
(integer) 10
複製代碼
127.0.0.1:6379> decr num
(integer) 9
127.0.0.1:6379> decr num
(integer) 8
複製代碼
127.0.0.1:6379> decrby num 2
(integer) 6
127.0.0.1:6379> decrby num 2
(integer) 4
複製代碼
向尾部追加值 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) 10
127.0.0.1:6379> get str
"helloworld"
複製代碼
獲取字符串長度 STRLEN命令返回鍵值的長度,若是鍵不存在則返回0。 語法:strlen key
127.0.0.1:6379> strlen str
(integer) 10
複製代碼
應用
假設有User對象以JSON序列化的形式存儲到Redis中,User對象有id,username、password、age、name等屬性,存儲的過程以下: 保存、更新:User對象 json(string) redis
若是在業務上只是更新age屬性,其餘的屬性並不作更新我應該怎麼作呢? 若是仍然採用上邊的方法在傳輸、處理時會形成資源浪費,下邊講的hash能夠很好的解決這個問題。
hash叫散列類型,它提供了字段和字段值的映射。字段值只能是字符串類型,不支持散列類型、集合類型等其它類型。以下:
賦值 HSET命令不區分插入和更新操做,當執行插入操做時HSET命令返回1,當執行更新操做時返回0。
127.0.0.1:6379> hset user username zhangsan
(integer) 1
複製代碼
127.0.0.1:6379> hmset user age 20 username lisi
OK
複製代碼
127.0.0.1:6379> hsetnx user age 30
(integer) 0
複製代碼
取值
127.0.0.1:6379> hget user username
"lisi"
複製代碼
127.0.0.1:6379> hmget user age username
1) "20"
2) "lisi"
複製代碼
127.0.0.1:6379> hgetall user
1) "username"
2) "lisi"
3) "age"
4) "20"
複製代碼
刪除字段 能夠刪除一個或多個字段,返回值是被刪除的字段的個數。 語法:hdel key field [field...]
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hdel user age username
(integer) 1
複製代碼
增長數字 語法:hincrby key field increment
127.0.0.1:6379> hincrby user age 2
(integer) 2
複製代碼
判斷字段是否存在 語法:hexists key field
127.0.0.1:6379> hexists user age
(integer) 1
複製代碼
只獲取字段名或字段值 語法: hkeys key hvals key
127.0.0.1:6379> hkeys user
1) "age"
複製代碼
獲取字段數量 語法:hlen key
127.0.0.1:6379> hlen user
(integer) 1
複製代碼
應用 存儲商品信息
127.0.0.1:6379> hlen user
(integer) 1
複製代碼
獲取商品信息
127.0.0.1:6379> hgetall items:1001
1) "id"
2) "3"
3) "name"
4) "apple"
5) "price"
6) "5.00"
複製代碼
Arraylist是使用數組來存儲數據,特色:查詢快、增刪慢
Linkedlist是使用雙向鏈表存儲數據,特色:增刪快、查詢慢,可是查詢鏈表兩端的數據也很快。
Redis的list是採用來鏈表來存儲的,因此對於redis的list數據類型的操做,是操做list的兩端數據來操做的。
向列表兩端增長元素
127.0.0.1:6379> lpush list:1 1 2 3
(integer) 3
複製代碼
127.0.0.1:6379> rpush list:1 4 5 6
(integer) 6
複製代碼
查看列表 LRANGE命令是列表類型最經常使用的命令之一,獲取列表中的某一片斷,將返回start、stop之間的全部元素(包含兩端的元素),索引從0開始。索引能夠是負數,如:「-1」表明最後邊的一個元素。
語法:lrange key start stop
127.0.0.1:6379> lrange list:1 0 2
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lrange list:1 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
6) "6"
複製代碼
從列表兩端彈出元素 LPOP命令從列表左邊彈出一個元素,會分兩步完成:
127.0.0.1:6379> lpop list:1
"3"
127.0.0.1:6379> rpop list:1
"6"
複製代碼
獲取列表中元素的個數 語法:llen key
127.0.0.1:6379> llen list:1
(integer) 4
複製代碼
刪除列表中指定的值 LREM命令會刪除列表中前count個值爲value的元素,返回實際刪除的元素個數。根據count值的不一樣,該命令的執行方式會有所不一樣:
語法:lrem key count value
得到/設置指定索引的元素值
127.0.0.1:6379> lindex list:1 2
"4"
複製代碼
127.0.0.1:6379> lset list:1 2 2
OK
複製代碼
只保留列表指定片斷 指定範圍和 lrange 一致 語法:ltrim key start stop
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
4) "5"
127.0.0.1:6379> ltrim list:1 0 2
OK
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
複製代碼
向列表中插入元素 該命令首先會在列表中從左到右查找值爲pivot的元素,而後根據第二個參數是BEFORE仍是AFTER來決定將value插入到該元素的前面仍是後面。 語法:linsert key before | after pivot value
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
127.0.0.1:6379> linsert list:1 after 1 9
(integer) 4
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"
複製代碼
將元素從一個列表轉移到另外一個列表 語法:rpoplpush source destination
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"
127.0.0.1:6379> rpoplpush list:1 newlist
"2"
127.0.0.1:6379> lrange newlist 0 -1
1) "2"
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
複製代碼
應用 在Redis中建立商品評論列表 用戶發佈商品評論,將評論信息轉成json存儲到list中。 用戶在頁面查詢評論列表,從redis中取出json數據展現到頁面。
定義商品評論列表key: 商品編號爲1001的商品評論key【items: comment:1001】
集合類型:無序、不可重複 列表類型:有序、可重複
增長/刪除元素 語法: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
(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 屬於 A 而且 不屬於 B 的元素構成的集合
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的元素構成的集合
127.0.0.1:6379> sinter setA setB
1) "2"
2) "3"
複製代碼
集合的並集運算 屬於 A 或者 屬於 B 的元素構成的集合
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
"2"
複製代碼
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
複製代碼
得到排名在某個範圍的元素列表
127.0.0.1:6379> zrange scoreboard 0 2
1) "zhangsan"
2) "wangwu"
複製代碼
127.0.0.1:6379> zrevrange scoreboard 0 2
1) "wangwu"
2) "zhangsan"
複製代碼
若是須要得到元素的分數能夠在命令末尾加上 withscores 參數 ··· 127.0.0.1:6379> zrevrange scoreboard 0 2 withscores
127.0.0.1:6379> zrank scoreboard zhangsan
(integer) 0
複製代碼
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) "wangwu"
複製代碼
語法: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,分數爲商品銷售量。
寫入商品銷售量:
商品編號1001的銷量是9,商品編號1002的銷量是10 192.168.101.3:7007> ZADD items:sellsort 9 1001 10 1002
商品編號1001的銷量加1 192.168.101.3:7001> ZINCRBY items:sellsort 1 1001
商品銷量前10名: 192.168.101.3:7001> ZRANGE items:sellsort 0 9 withscores
keys 返回知足給定pattern 的全部key redis 127.0.0.1:6379> keys mylist*
exists 確認一個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>
del 刪除一個key redis 127.0.0.1:6379> del age (integer) 1 redis 127.0.0.1:6379> exists age (integer) 0
rename 重命名key 示例:age 成功的被咱們更名爲age_new 了 redis 127.0.0.1:6379[1]> keys *
type 返回值的類型 示例:這個方法能夠很是簡單的判斷出值的類型 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 中修改持久化快照的條件:
在 redis.conf 中能夠指定持久化文件的存儲目錄
一旦redis非法關閉,那麼會丟失最後一次持久化以後的數據。
若是數據不重要,則沒必要要關心。 若是數據不能容許丟失,那麼要使用 aof 方式。
Redis 默認是不使用該方式持久化的。Aof 方式的持久化,是操做一次 redis 數據庫,則將操做的記錄存儲到 aof 持久化文件中。
第一步:開啓 aof 方式持久化方案。 將redis.conf中的appendonly改成yes,即開啓aof方式的持久化方案。
Aof文件存儲的目錄和rdb方式的同樣。 Aof文件存儲的名稱
在使用aof和rdb方式時,若是redis重啓,則數據從aof文件加載。
持久化保證了即便redis服務重啓也不會丟失數據,由於redis服務重啓後會將硬盤上持久化的數據恢復到內存中,可是當redis服務器的硬盤損壞了可能會致使數據丟失,若是經過redis的主從複製機制就能夠避免這種單點故障,以下圖:
無需配置
cp bin/ bin2 -r
rm -rf appendonly.aof dump.rdb
./redis-server redis.conf
./redis-cli -p 6380
注意: 主機一旦發生增刪改操做,那麼從機會將數據同步到從機中 從機不能執行寫操做
架構細節: (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 腳本語言編寫的。
sudo apt-get install ruby
複製代碼
gem install redis-3.0.0.gem
cd /usr/local/redis/
mkdir redis-cluster
cd /root/redis-3.0.0/src/
cp redis-trib.rb /usr/local/redis/redis-cluster
複製代碼
搭建集羣最少須要 3 臺主機,若是每臺主機再配置一臺從機的話,則最少須要6臺機器。 端口設計:7001-7006
cp bin ./redis-cluster/7001 -r
rm -rf appendonly.aof dump.rdb
cp 7001/ 7002-r
cp 7001/ 7003-r
cp 7001/ 7004-r
cp 7001/ 7005-r
cp 7001/ 7006-r
複製代碼
cd 7001
./redis-server redis.conf
cd ..
cd 7002
./redis-server redis.conf
cd ..
cd 7003
./redis-server redis.conf
cd ..
cd 7004
./redis-server redis.conf
cd ..
cd 7005
./redis-server redis.conf
cd ..
cd 7006
./redis-server redis.conf
cd ..
複製代碼
chmod u+x start-all.sh
複製代碼
./start-all.sh
複製代碼
./redis-trib.rb create --replicas 1 192.168.126.128:7001 192.168.126.128:7002 192.168.126.128:7003 192.168.126.128:7004 192.168.126.128:7005 192.168.126.128:7006
root@ubuntu:/usr/local/redis/redis-cluster/7001# ./redis-cli -p 7001 -c
-c 指定集羣鏈接
查看集羣信息
192.168.126.128:7002> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:260
cluster_stats_messages_received:260
複製代碼
查看集羣節點
192.168.126.128:7002> cluster nodes
3a15e73dacb512745156535ae7f959acf65ae12e 192.168.126.128:7005 slave 23e173cdc0b7673dc28cae70efaabbc41308bfdc 0 1531452321139 5 connected
2a58a53a5b10f7bd91af04128a6ed439d534c0ee 192.168.126.128:7001 master - 0 1531452322145 1 connected 0-5460
d0808388485dd08f1a2ecdfe3d2b213742d0050d 192.168.126.128:7004 slave 2a58a53a5b10f7bd91af04128a6ed439d534c0ee 0 1531452318117 4 connected
23e173cdc0b7673dc28cae70efaabbc41308bfdc 192.168.126.128:7002 myself,master - 0 0 2 connected 5461-10922
2af2312acc56552f9f73470f90d9a51973fc74d3 192.168.126.128:7006 slave 78faf92cfdbd12e1b27b270fb0798e67017f4d0b 0 1531452320132 6 connected
78faf92cfdbd12e1b27b270fb0798e67017f4d0b 192.168.126.128:7007 master - 0 1531452319123 3 connected 10923-16383
複製代碼
@Test
public void jedisCluster() {
// 建立jedisCluster
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.242.137", 7001));
nodes.add(new HostAndPort("192.168.242.137", 7002));
nodes.add(new HostAndPort("192.168.242.137", 7003));
nodes.add(new HostAndPort("192.168.242.137", 7004));
nodes.add(new HostAndPort("192.168.242.137", 7005));
nodes.add(new HostAndPort("192.168.242.137", 7006));
nodes.add(new HostAndPort("192.168.242.137", 7007));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("s4", "444");
String result = cluster.get("s4");
System.out.println(result);
cluster.close();
}
複製代碼
配置 applicationContext.xml
<!-- 鏈接池配置 -->
<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);
}
複製代碼