商品分類引入緩存-Redis主從複製-Redis Cluster集羣

實現步驟:
1.引入Redis和Spring的整合文件和Redis的屬性配置文件
2.修改redis.properties的參數配置(主要修改ip和端口號)
示例:
redis.maxTotal=50
redis.node1.ip=192.168.163.235
redis.node1.port=6379
redis.node2.ip=192.168.163.235
redis.node2.port=6380
3.修改applicationContext.xml,加入redis.properties文件
4.檢查和修改applicationContext-redis.xml
5.引入RedisService到Common工程下
這個類利用Jedis提供了set( ),get( )等操做redis方法
6.改寫Service層代碼
Redis和Spring整合+後臺商品類目緩存


代碼示例:
@Service
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private RedisService rs;
private static final ObjectMapper MAPPER = new ObjectMapper();
public class ItemCatService {
//存在緩存中的商品分類key,加上ITEM_CAT主要用於標識,從而區別其餘的業務key
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
//1.根據key,先從緩存裏查找數據
String rsResult=rs.get(ITEM_CAT_KEY);
//2.若是沒有數據,說明是首次查詢,則去數據庫查詢
List<ItemCat> resultList=itemCatMapper.findItemCatByParentId(parentId);
//3.在返回結果以前,要把查詢的結果放在緩存裏,京淘中是把List<ItemCat>轉換爲json傳放在Redis中
rs.set(ITEM_CAT_KEY, MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(rsResult)){
}
//4.從緩衝中,將json串拿到,並轉化爲List<ItemCat>結構傳回
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
List<ItemCat> resultList=MAPPER.readValue(MAPPER.readTree(rsResult).traverse(),
return resultList;
else{
}
try {
e.printStackTrace();
} catch (Exception e) {
}
return null;
public List<ItemCat> findItemCatByParentId(Long parentId) {
}
}
7.修改ItemCat 類
由於在這個類裏,有一個方法:
return isParent==1?"closed":"true";
public String getState(){
}
這個方法主要是爲了知足前臺的js要求,但並無對應的State字段,而ObjectMapper在作格式轉化時,遇到這種狀況會報錯:
Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)
解決辦法是在ItemCat類上加上一個註解:
@JsonIgnoreProperties(ignoreUnknown=true)
@Table(name="tb_item_cat")
@SuppressWarnings(value = { "all" })
public class ItemCat extends BasePojo{
…………
分區 新分區 2 的第 2 頁
…………
8.從新對項目發佈,而後啓動測試
分區 新分區 2 的第 3 頁
環境準備:
1.準備兩臺虛擬機
2.關閉虛擬機的防火牆
實現步驟:
1.安裝第一臺redis服務器,做爲Master節點(本例中主節點ip是192.168.234.131)
2.進入redis安裝目錄,編輯redis.conf文件
只須要配置daemonize yes便可
3.安裝第二臺redis服務器,做爲slave節點(本例中此從節點ip是192.168.234.132)
4.進入redis安裝目錄,編輯redis.conf文件
配置daemonize yes
配置slaveof 主節點ip 端口號
5.啓動Master節點和Salve節點的Redis服務
進入到redis安裝目錄
執行:./src/redis-server redis.conf
6.都啓動完畢後
在Master節點執行:redis-cli
而後執行:info replication
Redis 主從配置
2016年1月1日
12:07
分區 新分區 2 的第 4 頁
能夠看到當前的節點爲Master節點
有一個從節點
從節點的ip
7.在從節點執行:redis-cli
而後執行:info replication
能夠看到當前節點爲從節點
主節點的ip及端口號
若是以上信息一致,證實Redis的主從配置成功。
8.測試Redis主從數據的複製,經過Master節點設置一個key value 值,好比:
set name tony
而後經過Slave節點來get 對應的key,看是否有數據
在從節點執行:
get name
有結果,證實主從複製沒有問題
分區 新分區 2 的第 5 頁
注意:slave節點不能執行寫操做,好比在slave節點執行set 操做,會提示:
主從複製的步驟:
一、從服務器開始連接主服務器時,會向主服務器發送一個 SYNC 命令
二、主服務接收到命令以後,執行 BGSAVE,異步的將寫命令保存到一個緩衝區裏面
三、主服務器執行完BGSAVE以後,就.rdb 文件(BOF的持久化文件)發送給從服務器,從服務器從該
文件恢復數據到內存中
四、主服務器還會以 Redis 命令協議的格式, 將寫命令緩衝區中積累的全部內容都發送給從服務
器,從服務器經過執行命令將數據恢復到內存中
分區 新分區 2 的第 6 頁
哨兵機制
Redis提供了sentinel(哨兵)機制,Redis官方推薦的高可用性(HA)解決方案,當用Redis作
Master-slave的高可用方案時,假如master宕機了,Redis自己(包括它的不少客戶端)都沒有實
現自動進行主備切換,而Redis-sentinel自己也是一個獨立運行的進程,它能監控多個master-
slave集羣,發現master宕機後能進行自動切換。
每一個sentinel會向其它sentinal、master、slave定時發送消息,以確認對方是否「活」着,若是
發現對方在指定時間(可配置)內未迴應,則暫時認爲對方已掛(所謂的「主觀認爲宕機」
Subjective Down,簡稱SDOWN)。
若「哨兵羣」中的多數sentinel,都報告某一master沒響應,系統才認爲該master"完全死
亡"(即:客觀上的真正down機,Objective Down,簡稱ODOWN),經過必定的vote算法,從
剩下的slave節點中,選一臺提高爲master,而後自動修改相關配置。
實現步驟
1.先完成Redis的主從配置,並確保主從環境是正確可用的
2.配置Master的哨兵環境,進入Master節點的redis安裝目錄,編輯sentinel.conf 文件
修改配置項:sentinel monitor mymaster 192.168.234.131 6379 1
Redis哨兵
2016年1月1日
12:07
分區 新分區 2 的第 7 頁
說明:監控master節點192.168.234.131,master節點使用端口6379,最後一個數字表示投票須要
的"最少法定人數",好比有10個sentinal哨兵都在監控某一個master節點,若是須要至少6個哨兵
發現master掛掉後,才認爲master真正down掉,那麼這裏就配置爲6,最小配置1臺master,1臺
slave,在二個機器上都啓動sentinal的狀況下,哨兵數只有2個,若是一臺機器物理掛掉,只剩
一個sentinal能發現該問題,因此這裏配置成1。
3.配置Slave的哨兵,進入Slave節點的redis安裝目錄,編輯sentinel.conf 文件
修改配置項:sentinel monitor mymaster 192.168.234.131 6379 1
說明:不管是主節點仍是從節點,哨兵都是檢測主節點的ip
5.啓動主節點的Redis服務
6.啓動從節點的Redis服務
7.啓動主節點的哨兵
在redis的安裝目錄下,執行:
./src/redis-sentinel sentinel.conf
能夠看到:
哨兵已經找到並開始檢測主節點
分區 新分區 2 的第 8 頁
哨兵已經找到並開始檢測主節點
哨兵已找到並開始檢測從節點
8.啓動從節點的哨兵
在redis的安裝目錄下,執行:
./src/redis-sentinel sentinel.conf
9.測試,down掉Slave節點後哨兵的打印(在redis 安裝目錄執行:./src/redis-cli -p 6379 shutdown,
或者先進入redis-cli,再執行shutdown 也能夠)
10.測試,down掉Master節點後哨兵的打印
[17569] 21 Nov 11:06:57.389 # +switch-master mymaster 192.168.234.131 6379
192.168.234.132 6379
從紅線部分能夠看出,master發生了遷移,等剛纔停掉的master再重啓後,能夠觀察到它將被看成
slave加入,相似如下輸出:
[36444] 21 Nov 11:11:14.540 * +convert-to-slave slave 192.168.234.131 6379
192.168.234.131 6379 @ mymaster 192.168.234.132 6379
11.最後,若是想中止sentinel,可輸入命令./redis-cli -p shutdown 26379
12.當引入哨兵機制後,當主從關係發生變化時,sentienl.conf裏的配置文件監聽的Master ip 地址
也會發生變化,這個能夠本身驗證一下
哨兵配置項說明:
1 port <sentinel-port> :哨兵實例運行所在的端口(默認26379)
2 sentinel down-after-milliseconds mymaster <milliseconds> : master或slave多長時間
(默認30秒)不能使用後標記爲s_down狀態。
3 sentinel failover-timeout <master-name> <milliseconds(默認值3分鐘)>
表示若是在指定時間內,mymaster仍沒活過來,則啓動failover,從剩下的slave中選一個升級爲
master
分區 新分區 2 的第 9 頁
原理說明
1.Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另一種叫作哈希槽 (hash
slot)的方式來分配的。redis cluster 默認分配了 16384(2^14) 個slot,當咱們set一個key
時,會用CRC16算法來取模獲得所屬的slot,而後將這個key 分到哈希槽區間的節點上,具體
算法就是:CRC16(key) % 16384。
2.集羣的最大節點數量也是 16384 個(推薦的最大節點數量爲 1000 個),同理每一個主節點
能夠負責處理1到16384個槽位。當16384個槽位都有主節點負責處理時,集羣進入」穩定
「上線狀態,能夠開始處理數據命令。
3.Redis 集羣會把數據存在 master 節點上,而後在這個 master 和其對應的salve 之間進行
數據同步。一個主節點能夠有任意多個從節點, 這些從節點用於在主節點發生網絡斷線或者
節點失效時, 對主節點進行替換。
備註1:
這裏之因此用CRC16算法,沒有用一致性hash,是由於Redis的做者認爲它的crc16(key)
mod 16384的效果已經不錯了,雖然沒有一致性hash靈活,但實現很簡單,節點增刪時處理
起來也很方便。這個算法簡單歸納就是把任意長度的輸入經過散列算法變換成固定長度(16
位)的輸出,該輸出就是散列值。
CRC即循環冗餘校驗碼(Cyclic Redundancy Check):是數據通訊領域中最經常使用的一種差
錯校驗碼。目前最經常使用的是CRC16和CRC32。
備註2:
須要注意的是:必需要3個或以上的主節點,不然在建立集羣時會失敗,而且當存活的主節點
數小於總節點數的一半時,整個集羣就沒法提供服務了。
以下圖,集羣一共有6臺機器,若是有一個master掛掉,則集羣沒法提供服務。
Redis集羣
分區 新分區 2 的第 10 頁
分區 新分區 2 的第 11 頁
實現步驟
1.準備一臺虛擬機,關閉防火牆以及安裝好Redis
2.安裝Ruby,(啓動Redis集羣時,會用到Ruby指令)
執行:yum install ruby
(京淘提供的虛擬機已默認裝好)
3.驗證是否已安裝好ruby
執行:ruby -v
4.肯定Redis的集羣架構
本例中搭建的是6臺Redis節點,實現方式是在一臺虛擬機上啓動6個Redis服務進程,每一個進程至關因而一個Redis
節點(固然,也能夠在6臺虛擬機或物理機上搭建),最後造成的集羣架構是:3主3從,每一個Redis都有一個對應的
訪問端口,以下圖:
5.在Redis安裝目錄下建立cluster目錄,並在cluster目錄下建立6個目錄,目錄名爲:
7000,7001,7002,7003,7004,7005
注:這樣作的目的是爲了更清晰的管理,路徑以及目錄名是本身定的
[root@localhost redis-3.0.7]# mkdir cluster
[root@localhost cluster]# mkdir 7000 7001 7002 7003 7004 7005
6.將redis.conf配置文件拷貝到這個六個目錄下,以7000目錄爲例:
[root@localhost cluster]# cp ../redis.conf 7000
7.逐一編輯每一個目錄下的配置文件,以7000目錄的配置文件爲例:
Redis集羣搭建
分區 新分區 2 的第 12 頁
7.逐一編輯每一個目錄下的配置文件,以7000目錄的配置文件爲例:
示例:
port 7000 //端口7000
bind 本機ip //默認ip爲127.0.0.1 須要改成其餘節點機器可訪問的ip 不然建立集羣時沒法
訪問對應的端口,沒法建立集羣
daemonize yes //redis後臺運行
pidfile /home/software/redis-3.0.7/cluster/7000/redis_7000.pid //pidfile文件對應7000
cluster-enabled yes //開啓集羣 把註釋#去掉
cluster-config-file nodes-7000.conf //集羣的配置 配置文件首次啓動自動生成
appendonly yes //aof日誌開啓 有須要就開啓,它會每次寫操做都記錄一條日誌
注:須要將主從配置項註釋掉
#slave of ……
8.將7000目錄下配置好的文件拷貝到其餘5個目錄:
[root@localhost 7000]# cp redis.conf ../7001
[root@localhost 7000]# cp redis.conf ../7002
[root@localhost 7000]# cp redis.conf ../7003
[root@localhost 7000]# cp redis.conf ../7004
[root@localhost 7000]# cp redis.conf ../7005
9.更改每一個目錄下的配置文件,以更改7001目錄的配置文件爲例:
[root@localhost 7001]#vim redis.conf
而後在編輯模式下執行 :%s/7000/7001/g #替換全部7000爲7001
其餘的目錄同理。
10.啓動6個Redis進程
爲了後續啓動方便,能夠編輯shell腳本。
在cluster目錄下,執行:vim start.sh
內容示例:
#!/bin/sh
redis-server 7000/redis.conf &
redis-server 7001/redis.conf &
redis-server 7002/redis.conf &
redis-server 7003/redis.conf &
redis-server 7004/redis.conf &
redis-server 7005/redis.conf &
中止腳本:
redis-cli -p 7000 shutdown
redis-cli -p 7001 shutdown
redis-cli -p 7002 shutdown
redis-cli -p 7003 shutdown
redis-cli -p 7004 shutdown
redis-cli -p 7005 shutdown
11.驗證6個Redis進程是否已啓動:
執行:ps -ef | grep redis
12.使6個Redis進程變成一個集羣:
分區 新分區 2 的第 13 頁
12.使6個Redis進程變成一個集羣:
切換到Redis安裝目錄下的src目錄下,找到:redis-trib.rb 這個文件,並將這個文件複製到 /usr/local/bin 目錄下
[root@localhost src]# cp redis-trib.rb /usr/local/bin/
而後執行:
./redis-trib.rb create --replicas 1 192.168.234.231:7000 192.168.234.231:7001 192.168.234.231:7002 192.168.234.231:7003
192.168.234.231:7004 192.168.234.231:7005
上圖顯示:三個主三個從
13.執行:redis-cli -h 192.168.234.231 -c -p 7000
14.執行測試:
好比進入7002節點,設置一對k,v 會發現k,v會被自動分配到7001節點
分區 新分區 2 的第 14 頁
備註:如何查看某個redis是不是主仍是從
在redis命令行內,執行:info replication
分區 新分區 2 的第 15 頁
實現步驟:
1.引入Jedis的相關依賴
2.引入Redis的屬性配置文件
4.引入Redis集羣整合的加載工具類
>RedisCluster.java
拷貝到jt-common工程下的util包下
5.引入Redis集羣和Spring的整合文件
6.改寫ItemCatService代碼:
代碼示意:
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private JedisCluster rsCluster;
private static final ObjectMapper MAPPER=new ObjectMapper();
@Override
ItemCat itemCat = new ItemCat();
itemCat.setParentId(parentId);
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
String jsonResult=rsCluster.get(ITEM_CAT_KEY);
List<ItemCat> resultList=itemCatMapper.select(itemCat);
rsCluster.set(ITEM_CAT_KEY,MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(jsonResult)){
return MAPPER.readValue(MAPPER.readTree(jsonResult).traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
}else{
}
try {
return itemCatMapper.select(itemCat);
} catch (Exception e) {
}
public List<ItemCat> findItemCatList(Long parentId) {
}
Redis集羣和Spring整合
分區 新分區 2 的第 16 頁
}
分區 新分區 2 的第 17 頁
Redis緩存數據的持久化
redis自身支持兩種持久化方式RDB和AOF
一、RDB是定時對數據庫內存作快照的方式備份整個內存數據庫,這種方式,在redis或者服務
器故障的時候有可能會丟失大量數據,可是這種方式是主進程fork一個子進程來執行,不影響
到主進程的效率,也不會阻塞,同時保存數據集的完整性,若是對數據丟失能容忍一個小時左
右的數據,能夠採用這種方式,性能高。
二、AOF是將redis全部寫的操做做爲日誌存在AOF文件中,採用追加的方式,一般能夠設置no:
不作aof追加,always,每次寫操做都作一次追加aof文件,everysec:每秒鐘追加一次,其中
always不會丟失任何數據,可是會耗不少性能,其中everysec是推薦使用的,其速度也和rdb
相差無幾
若是每隔一段時間進行數據持久化,咱們叫「半持久化」。
若是每次操做都進行數據持久化,咱們叫「全持久化」。
但最多見的配置,就是關閉AOF,使用RDB方式作持久化。
RDB持久化默認生成的文件名爲dump.rdb,這個能夠經過配置文件配置。
Redis沒有專門的RDB文件載入命令,只要Redis服務器開啓,就會檢測RDB文件是否存在,
就會自動載入RDB文件,
注意:若是服務器開啓了AOF持久化功能,服務器會優先使用AOF文件來還原數據庫狀態,
只有在AOF持久化功能關閉的時候,纔會使用RDB文件來還原數據庫狀態。
RDB方式能夠自動保存,也能夠能夠經過手動執行,save命令和bgsave命令
注:利用save命令執行持久化操做時,服務器是被阻塞的,此時redis不能對外提供服務。
bgsave命令執行持久化操做時,服務器是不會被阻塞的,由於是單獨啓動一個線程來處理
的,建議使用這種方式作數據持久化
Redis.conf配置文件裏,有一項配置是和RDB持久相關的參數
save 900 1
save 300 10
save 60 10000
以上表示的意思是,
900秒以內對服務進行了至少一次修改
300秒以內服務器進行了至少10次修改
60秒以內對服務器進行了至少10000次修改。
這些條件知足其中的任意一個bgsave命令就會自動執行。
Redis 數據持久化
2016年1月5日
16:19
分區 新分區 2 的第 18 頁
1. Redis默認不是以守護進程的方式運行,能夠經過該配置項修改,使用yes啓用守護進程
daemonize no
2. 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,能夠經過
pidfile指定
pidfile /var/run/redis.pid
3. 指定Redis監聽端口,默認端口爲6379,redis做者說由於6379在手機按鍵上MERZ對應的號
碼,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4. 綁定的主機地址
bind 127.0.0.1
5.當客戶端閒置多長時間後關閉鏈接,若是指定爲0,表示關閉該功能
timeout 300
6. 指定日誌記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認爲
verbose
loglevel verbose
7. 日誌記錄方式,默認爲標準輸出,若是配置Redis爲守護進程方式運行,而這裏又配置爲日
志記錄方式爲標準輸出,則日誌將會發送給/dev/null
logfile stdout
8. 設置數據庫的數量,默認數據庫爲0,可使用SELECT <dbid>命令在鏈接上指定數據庫id
databases 16
Redis經常使用參數設置
分區 新分區 2 的第 19 頁
databases 16
9. 指定在多長時間內,有多少次更新操做,就將數據同步到數據文件,能夠多個條件配合
save <seconds> <changes>
Redis默認配置文件中提供了三個條件:
save 900 1
save 300 10
save 60 10000
分別表示900秒(15分鐘)內有1個更改,300秒(5分鐘)內有10個更改以及60秒內有10000個
更改。
10. 指定存儲至本地數據庫時是否壓縮數據,默認爲yes,Redis採用LZF壓縮,若是爲了節省
CPU時間,能夠關閉該選項,但會致使數據庫文件變的巨大
rdbcompression yes
11. 指定本地數據庫文件名,默認值爲dump.rdb
dbfilename dump.rdb
12. 指定本地數據庫存放目錄
dir ./
13. 設置當本機爲slave服務時,設置master服務的IP地址及端口,在Redis啓動時,它會自動從
master進行數據同步
slaveof <masterip> <masterport>
14. 設置同一時間最大客戶端鏈接數,默認無限制,Redis能夠同時打開的客戶端鏈接數爲Redis
進程能夠打開的最大文件描述符數,若是設置maxclients 0,表示不做限制。當客戶端鏈接數
分區 新分區 2 的第 20 頁
進程能夠打開的最大文件描述符數,若是設置maxclients 0,表示不做限制。當客戶端鏈接數
到達限制時,Redis會關閉新的鏈接並向客戶端返回max number of clients reached錯誤信息
maxclients 128
15. 指定Redis最大內存限制,Redis在啓動時會把數據加載到內存中,達到最大內存後,Redis
會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大內存設置,將沒法再
進行寫入操做,但仍然能夠進行讀取操做。Redis新的vm機制,會把Key存放內存,Value會存
放在swap區
maxmemory <bytes>
16. 指定是否在每次更新操做後進行日誌記錄,Redis在默認狀況下是異步的把數據寫入磁盤,
若是不開啓,可能會在斷電時致使一段時間內的數據丟失。由於redis自己同步數據文件是按
上面save條件來同步的,因此有的數據會在一段時間內只存在於內存中。默認爲no
appendonly no
17. 指定更新日誌文件名,默認爲appendonly.aof
appendfilename appendonly.aof
18. 指定更新日誌條件,共有3個可選值:
no:表示等操做系統進行數據緩存同步到磁盤(快)
always:表示每次更新操做後手動調用fsync()將數據寫到磁盤(慢,安全)
everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
19. 指定是否啓用虛擬內存機制,默認值爲no,不開啓。
若是開啓,則Redis將訪問量較少的頁即冷數據swap到磁盤上,訪問多的頁面由磁盤自動換出
到內存中
vm-enabled no
分區 新分區 2 的第 21 頁
vm-enabled no
20. 虛擬內存文件路徑,默認值爲/tmp/redis.swap,不可多個Redis實例共享
vm-swap-file /tmp/redis.swap
21. 設置在向客戶端應答時,是否把較小的包合併爲一個包發送,默認爲開啓
glueoutputbuf yes
22.rdbchecksum no
檢查RDB數據的正確性,會犧牲10%的性能,故建議關閉.
=============================================================
redis狀態與性能監控
一、redis-benchmark
redis基準信息,redis服務器性能檢測
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
100個併發鏈接,100000個請求,檢測host爲localhost 端口爲6379的redis服務器性能
分區 新分區 2 的第 22 頁
Redis 和 Memcache 都是基於內存的數據存儲系統,Redis的做者Salvatore Sanfilippo曾經對這兩
種基於內存的數據存儲系統進行過比較:
Redis支持服務器端的數據操做:Redis相比Memcached來講,擁有更多的數據結構和並支持更
豐富的數據操做,一般在Memcached裏,你須要將數據拿到客戶端來進行相似的修改再set回
去。這大大增長了網絡IO的次數和數據體積。在Redis中,這些複雜的操做一般和通常的
GET/SET同樣高效。因此,若是須要緩存可以支持更復雜的結構和操做,那麼Redis會是不錯的
選擇。
內存使用效率對比:使用簡單的key-value存儲的話,Memcached的內存利用率更高,而若是
Redis採用hash結構來作key-value存儲,因爲其組合式的壓縮,其內存利用率會高於
Memcached。
性能對比:因爲Redis只使用單核,而Memcached可使用多核,因此平均每個核上Redis在
存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於
Redis,雖然Redis最近也在存儲大數據的性能上進行優化,可是比起Memcached,仍是稍有遜
色。
一、數據類型支持不一樣
與Memcached僅支持簡單的key-value結構的數據記錄不一樣,Redis支持的數據類型要豐富
得多。最爲經常使用的數據類型主要由五種:String、Hash、List、Set和Sorted Set
二、內存管理機制不一樣
在Redis中,並非全部的數據都一直存儲在內存中的。這是和Memcached相比一個最大的
區別。當物理內存用完時,Redis能夠將一些好久沒用到的value交換到磁盤,可是Redis會緩
存全部的key的信息。
這種特性使得Redis能夠保持超過其機器自己內存大小的數據。固然,機器自己的內存必需要
可以保持全部的key,畢竟這些數據是不會進行swap操做的。
對於像Redis和Memcached這種基於內存的數據庫系統來講,內存管理的效率高低是影響系
統性能的關鍵因素。傳統C語言中的malloc/free函數是最經常使用的分配和釋放內存的方法,但
是這種方法存在着很大的缺陷:首先,對於開發人員來講不匹配的malloc和free容易形成內
存泄露;其次頻繁調用會形成大量內存碎片沒法回收從新利用,下降內存利用率;最後做爲系
Redis和Memcached的對比
分區 新分區 2 的第 23 頁
存泄露;其次頻繁調用會形成大量內存碎片沒法回收從新利用,下降內存利用率;最後做爲系
統調用,其系統開銷遠遠大於通常函數調用。因此,爲了提升內存的管理效率,高效的內存管
理方案都不會直接使用malloc/free調用。Redis和Memcached均使用了自身設計的內存管理
機制,可是實現方法存在很大的差別,下面將會對二者的內存管理機制分別進行介紹。
Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,
將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以徹底解決內存碎
片問題。
當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的
Slab Class,而後經過查詢Memcached保存着的該Slab Class內空閒Chunk的列表就能夠找
到一個可用於存儲數據的Chunk。當一條數據庫過時或者丟棄時,該記錄所佔用的Chunk就
能夠回收,從新添加到空閒列表中。
Redis的內存管理主要採用的是包裝的mallc/free,相較於Memcached的內存管理方法來
說,要簡單不少。
3.數據持久化支持
Redis雖然是基於內存的存儲系統,可是它自己是支持內存數據的持久化的,並且提供兩種主
要的持久化策略:RDB快照和AOF日誌。而memcached是不支持數據持久化操做的。
四、集羣管理的不一樣
Memcached是全內存的數據緩衝系統,Redis雖然支持數據的持久化,可是全內存畢竟纔是
其高性能的本質。做爲基於內存的存儲系統來講,機器物理內存的大小就是系統可以容納的最
大數據量。若是須要處理的數據量超過了單臺機器的物理內存大小,就須要構建分佈式集羣來
擴展存儲能力。
Memcached自己並不支持分佈式,所以只能在客戶端經過像一致性哈希這樣的分佈式算法來
實現Memcached的分佈式存儲。當客戶端向Memcached集羣發送數據以前,首先會經過內
置的分佈式算法計算出該條數據的目標節點,而後數據會直接發送到該節點上存儲。但客戶端
查詢數據時,一樣要計算出查詢數據所在的節點,而後直接向該節點發送查詢請求以獲取數
據。
分區 新分區 2 的第 24 頁
相較於Memcached只能採用客戶端實現分佈式存儲,Redis更偏向於在服務器端構建分佈式
存儲。最新版本的Redis已經支持了分佈式存儲功能。Redis Cluster是一個實現了分佈式且允
許單點故障的Redis高級版本,它沒有中心節點,具備線性可伸縮的功能。在數據的放置策略
上,Redis Cluster使用的分佈式算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。
爲了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。當
Master節點退出後,集羣會自動選擇一個Slave節點成爲新的Master節點。
分區 新分區 2 的第 25 頁
什麼是redis?
Redis 是一個基於內存的高性能key-value數據庫
Reids的特色
Redis本質上是一個Key-Value類型的內存數據庫,很像memcached,整個數據庫通通加載在內
存當中進行操做,按期經過異步操做把數據庫數據flush到硬盤上進行保存。由於是純內存操
做,Redis的性能很是出色,每秒能夠處理超過10萬次讀寫操做,是已知性能最快的Key-Value
DB。
Redis的出色之處不只僅是性能,Redis最大的魅力是支持保存多種數據結構,此外單個value的
最大限制是1GB,不像memcached只能保存1MB的數據,所以Redis能夠用來實現不少有用的功
能,比方說用他的List來作FIFO雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的Set
能夠作高性能的tag系統等等。另外Redis也能夠對存入的Key-Value設置expire時間,所以也可
以被看成一 個功能增強版的memcached來用。
Redis的主要缺點是數據庫容量受到物理內存的限制,不能用做海量數據的高性能讀寫,所以
Redis適合的場景主要侷限在較小數據量的高性能操做和運算上。
Redis支持的數據類型
Redis經過Key-Value的單值不一樣類型來區分, 如下是支持的類型:
String
Lists
Set 求交集、並集
Sorted Set
hashes
爲何redis須要把全部數據放到內存中?
Redis爲了達到最快的讀寫速度將數據都讀到內存中,並經過異步的方式將數據寫入磁盤。所
以redis具備快速和數據持久化的特徵。若是不將數據放在內存中,磁盤I/O速度爲嚴重影響
redis的性能。在內存愈來愈便宜的今天,redis將會愈來愈受歡迎。
若是設置了最大使用的內存,則數據已有記錄數達到內存限值後不能繼續插入新值。
Redis總結
分區 新分區 2 的第 26 頁
Redis是單進程單線程的
redis利用隊列技術將併發訪問變爲串行訪問,消除了傳統數據庫串行控制的開銷
虛擬內存
當你的key很小而value很大時,使用VM的效果會比較好.由於這樣節約的內存比較大.
當你的key不小時,能夠考慮使用一些很是方法將很大的key變成很大的value,好比你能夠考慮將
key,value組合成一個新的value.
vm-max-threads這個參數,能夠設置訪問swap文件的線程數,設置最好不要超過機器的核數,若是
設置爲0,那麼全部對swap文件的操做都是串行的.可能會形成比較長時間的延遲,可是對數據完
整性有很好的保證.
本身測試的時候發現用虛擬內存性能也不錯。若是數據量很大,能夠考慮分佈式或者其餘數據

分佈式
redis支持主從的模式。原則:Master會將數據同步到slave,而slave不會將數據同步到
master。Slave啓動時會鏈接master來同步數據。
這是一個典型的分佈式讀寫分離模型。咱們能夠利用master來插入數據,slave提供檢索服務。
這樣能夠有效減小單個機器的併發訪問數量
數據分片模型
爲了解決讀寫分離模型的缺陷,能夠將數據分片模型應用進來。
能夠將每一個節點當作都是獨立的master,而後經過業務實現數據分片。
結合上面兩種模型,能夠將每一個master設計成由一個master和多個slave組成的模型。
Redis的回收策略
volatile-lru:從已設置過時時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘

分區 新分區 2 的第 27 頁
volatile-ttl:從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰
volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
使用Redis有哪些好處?
(1) 速度快,由於數據存在內存中,相似於HashMap,HashMap的優點就是查找和操做的時間
複雜度都是O(1)
(2) 支持豐富數據類型,支持string,list,set,sorted set,hash
(3) 支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不
執行
(4) 豐富的特性:可用於緩存,消息,按key設置過時時間,過時後將會自動刪除
redis相比memcached有哪些優點?
(1) memcached全部的值均是簡單的字符串,redis做爲其替代者,支持更爲豐富的數據類型
(2) redis的速度比memcached快不少
(3) redis能夠持久化其數據
redis常見性能問題和解決方案:
(1) Master最好不要作任何持久化工做,如RDB內存快照和AOF日誌文件,可讓它的slave來
作持久化工做。
(2) 若是數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次
分區 新分區 2 的第 28 頁
(3) 爲了主從複製的速度和鏈接的穩定性,Master和Slave最好在同一個局域網內
(4) 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <-
Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。若是Master掛了,能夠馬上啓
用Slave1作Master,其餘不變。
MySQL裏有2000w數據,redis中只存20w的數據,如何保證redis中的數據
都是熱點數據
相關知識:redis 內存數據集大小上升到必定大小的時候,就會施行數據淘汰策略。redis 提供
6種數據淘汰策略
Memcache與Redis的區別都有哪些?
Redis 常見的性能問題都有哪些?如何解決?
1).Master寫內存快照,save命令調度rdbSave函數,會阻塞主線程的工做,當快照比較大時對
性能影響是很是大的,會間斷性暫停服務,因此Master最好不要寫內存快照。
2).Master AOF持久化,若是不重寫AOF文件,這個持久化方式對性能的影響是最小的,可是
AOF文件會不斷增大,AOF文件過大會影響Master重啓的恢復速度。Master最好不要作任何持
久化工做,包括內存快照和AOF日誌文件,特別是不要啓用內存快照作持久化,若是數據比較關
鍵,某個Slave開啓AOF備份數據,策略爲每秒同步一次。
3).Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會佔大量的CPU和內存資源,導
致服務load太高,出現短暫服務暫停現象。
4). Redis主從複製的性能問題,爲了主從複製的速度和鏈接的穩定性,Slave和Master最好在同
一個局域網內
redis 最適合的場景
分區 新分區 2 的第 29 頁
redis 最適合的場景
Redis最適合全部數據in-momory的場景
分區 新分區 2 的第 30 頁
實現步驟:
1.引入Redis和Spring的整合文件和Redis的屬性配置文件
2.修改redis.properties的參數配置(主要修改ip和端口號)
示例:
redis.maxTotal=50
redis.node1.ip=192.168.163.235
redis.node1.port=6379
redis.node2.ip=192.168.163.235
redis.node2.port=6380
3.修改applicationContext.xml,加入redis.properties文件
4.檢查和修改applicationContext-redis.xml
5.引入RedisService到Common工程下
這個類利用Jedis提供了set( ),get( )等操做redis方法
6.改寫Service層代碼
Redis和Spring整合+後臺商品類目緩存
2017年9月24日
19:05
分區 新分區 2 的第 1 頁
代碼示例:
@Service
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private RedisService rs;
private static final ObjectMapper MAPPER = new ObjectMapper();
public class ItemCatService {
//存在緩存中的商品分類key,加上ITEM_CAT主要用於標識,從而區別其餘的業務key
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
//1.根據key,先從緩存裏查找數據
String rsResult=rs.get(ITEM_CAT_KEY);
//2.若是沒有數據,說明是首次查詢,則去數據庫查詢
List<ItemCat> resultList=itemCatMapper.findItemCatByParentId(parentId);
//3.在返回結果以前,要把查詢的結果放在緩存裏,京淘中是把List<ItemCat>轉換爲json傳放在Redis中
rs.set(ITEM_CAT_KEY, MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(rsResult)){
}
//4.從緩衝中,將json串拿到,並轉化爲List<ItemCat>結構傳回
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
List<ItemCat> resultList=MAPPER.readValue(MAPPER.readTree(rsResult).traverse(),
return resultList;
else{
}
try {
e.printStackTrace();
} catch (Exception e) {
}
return null;
public List<ItemCat> findItemCatByParentId(Long parentId) {
}
}
7.修改ItemCat 類
由於在這個類裏,有一個方法:
return isParent==1?"closed":"true";
public String getState(){
}
這個方法主要是爲了知足前臺的js要求,但並無對應的State字段,而ObjectMapper在作格式轉化時,遇到這種狀況會報錯:
Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)
解決辦法是在ItemCat類上加上一個註解:
@JsonIgnoreProperties(ignoreUnknown=true)
@Table(name="tb_item_cat")
@SuppressWarnings(value = { "all" })
public class ItemCat extends BasePojo{
…………
分區 新分區 2 的第 2 頁
…………
8.從新對項目發佈,而後啓動測試
分區 新分區 2 的第 3 頁
環境準備:
1.準備兩臺虛擬機
2.關閉虛擬機的防火牆
實現步驟:
1.安裝第一臺redis服務器,做爲Master節點(本例中主節點ip是192.168.234.131)
2.進入redis安裝目錄,編輯redis.conf文件
只須要配置daemonize yes便可
3.安裝第二臺redis服務器,做爲slave節點(本例中此從節點ip是192.168.234.132)
4.進入redis安裝目錄,編輯redis.conf文件
配置daemonize yes
配置slaveof 主節點ip 端口號
5.啓動Master節點和Salve節點的Redis服務
進入到redis安裝目錄
執行:./src/redis-server redis.conf
6.都啓動完畢後
在Master節點執行:redis-cli
而後執行:info replication
Redis 主從配置
2016年1月1日
12:07
分區 新分區 2 的第 4 頁
能夠看到當前的節點爲Master節點
有一個從節點
從節點的ip
7.在從節點執行:redis-cli
而後執行:info replication
能夠看到當前節點爲從節點
主節點的ip及端口號
若是以上信息一致,證實Redis的主從配置成功。
8.測試Redis主從數據的複製,經過Master節點設置一個key value 值,好比:
set name tony
而後經過Slave節點來get 對應的key,看是否有數據
在從節點執行:
get name
有結果,證實主從複製沒有問題
分區 新分區 2 的第 5 頁
注意:slave節點不能執行寫操做,好比在slave節點執行set 操做,會提示:
主從複製的步驟:
一、從服務器開始連接主服務器時,會向主服務器發送一個 SYNC 命令
二、主服務接收到命令以後,執行 BGSAVE,異步的將寫命令保存到一個緩衝區裏面
三、主服務器執行完BGSAVE以後,就.rdb 文件(BOF的持久化文件)發送給從服務器,從服務器從該
文件恢復數據到內存中
四、主服務器還會以 Redis 命令協議的格式, 將寫命令緩衝區中積累的全部內容都發送給從服務
器,從服務器經過執行命令將數據恢復到內存中
分區 新分區 2 的第 6 頁
哨兵機制
Redis提供了sentinel(哨兵)機制,Redis官方推薦的高可用性(HA)解決方案,當用Redis作
Master-slave的高可用方案時,假如master宕機了,Redis自己(包括它的不少客戶端)都沒有實
現自動進行主備切換,而Redis-sentinel自己也是一個獨立運行的進程,它能監控多個master-
slave集羣,發現master宕機後能進行自動切換。
每一個sentinel會向其它sentinal、master、slave定時發送消息,以確認對方是否「活」着,若是
發現對方在指定時間(可配置)內未迴應,則暫時認爲對方已掛(所謂的「主觀認爲宕機」
Subjective Down,簡稱SDOWN)。
若「哨兵羣」中的多數sentinel,都報告某一master沒響應,系統才認爲該master"完全死
亡"(即:客觀上的真正down機,Objective Down,簡稱ODOWN),經過必定的vote算法,從
剩下的slave節點中,選一臺提高爲master,而後自動修改相關配置。
實現步驟
1.先完成Redis的主從配置,並確保主從環境是正確可用的
2.配置Master的哨兵環境,進入Master節點的redis安裝目錄,編輯sentinel.conf 文件
修改配置項:sentinel monitor mymaster 192.168.234.131 6379 1
Redis哨兵
2016年1月1日
12:07
分區 新分區 2 的第 7 頁
說明:監控master節點192.168.234.131,master節點使用端口6379,最後一個數字表示投票須要
的"最少法定人數",好比有10個sentinal哨兵都在監控某一個master節點,若是須要至少6個哨兵
發現master掛掉後,才認爲master真正down掉,那麼這裏就配置爲6,最小配置1臺master,1臺
slave,在二個機器上都啓動sentinal的狀況下,哨兵數只有2個,若是一臺機器物理掛掉,只剩
一個sentinal能發現該問題,因此這裏配置成1。
3.配置Slave的哨兵,進入Slave節點的redis安裝目錄,編輯sentinel.conf 文件
修改配置項:sentinel monitor mymaster 192.168.234.131 6379 1
說明:不管是主節點仍是從節點,哨兵都是檢測主節點的ip
5.啓動主節點的Redis服務
6.啓動從節點的Redis服務
7.啓動主節點的哨兵
在redis的安裝目錄下,執行:
./src/redis-sentinel sentinel.conf
能夠看到:
哨兵已經找到並開始檢測主節點
分區 新分區 2 的第 8 頁
哨兵已經找到並開始檢測主節點
哨兵已找到並開始檢測從節點
8.啓動從節點的哨兵
在redis的安裝目錄下,執行:
./src/redis-sentinel sentinel.conf
9.測試,down掉Slave節點後哨兵的打印(在redis 安裝目錄執行:./src/redis-cli -p 6379 shutdown,
或者先進入redis-cli,再執行shutdown 也能夠)
10.測試,down掉Master節點後哨兵的打印
[17569] 21 Nov 11:06:57.389 # +switch-master mymaster 192.168.234.131 6379
192.168.234.132 6379
從紅線部分能夠看出,master發生了遷移,等剛纔停掉的master再重啓後,能夠觀察到它將被看成
slave加入,相似如下輸出:
[36444] 21 Nov 11:11:14.540 * +convert-to-slave slave 192.168.234.131 6379
192.168.234.131 6379 @ mymaster 192.168.234.132 6379
11.最後,若是想中止sentinel,可輸入命令./redis-cli -p shutdown 26379
12.當引入哨兵機制後,當主從關係發生變化時,sentienl.conf裏的配置文件監聽的Master ip 地址
也會發生變化,這個能夠本身驗證一下
哨兵配置項說明:
1 port <sentinel-port> :哨兵實例運行所在的端口(默認26379)
2 sentinel down-after-milliseconds mymaster <milliseconds> : master或slave多長時間
(默認30秒)不能使用後標記爲s_down狀態。
3 sentinel failover-timeout <master-name> <milliseconds(默認值3分鐘)>
表示若是在指定時間內,mymaster仍沒活過來,則啓動failover,從剩下的slave中選一個升級爲
master
分區 新分區 2 的第 9 頁
原理說明
1.Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另一種叫作哈希槽 (hash
slot)的方式來分配的。redis cluster 默認分配了 16384(2^14) 個slot,當咱們set一個key
時,會用CRC16算法來取模獲得所屬的slot,而後將這個key 分到哈希槽區間的節點上,具體
算法就是:CRC16(key) % 16384。
2.集羣的最大節點數量也是 16384 個(推薦的最大節點數量爲 1000 個),同理每一個主節點
能夠負責處理1到16384個槽位。當16384個槽位都有主節點負責處理時,集羣進入」穩定
「上線狀態,能夠開始處理數據命令。
3.Redis 集羣會把數據存在 master 節點上,而後在這個 master 和其對應的salve 之間進行
數據同步。一個主節點能夠有任意多個從節點, 這些從節點用於在主節點發生網絡斷線或者
節點失效時, 對主節點進行替換。
備註1:
這裏之因此用CRC16算法,沒有用一致性hash,是由於Redis的做者認爲它的crc16(key)
mod 16384的效果已經不錯了,雖然沒有一致性hash靈活,但實現很簡單,節點增刪時處理
起來也很方便。這個算法簡單歸納就是把任意長度的輸入經過散列算法變換成固定長度(16
位)的輸出,該輸出就是散列值。
CRC即循環冗餘校驗碼(Cyclic Redundancy Check):是數據通訊領域中最經常使用的一種差
錯校驗碼。目前最經常使用的是CRC16和CRC32。
備註2:
須要注意的是:必需要3個或以上的主節點,不然在建立集羣時會失敗,而且當存活的主節點
數小於總節點數的一半時,整個集羣就沒法提供服務了。
以下圖,集羣一共有6臺機器,若是有一個master掛掉,則集羣沒法提供服務。
Redis集羣
分區 新分區 2 的第 10 頁
分區 新分區 2 的第 11 頁
實現步驟
1.準備一臺虛擬機,關閉防火牆以及安裝好Redis
2.安裝Ruby,(啓動Redis集羣時,會用到Ruby指令)
執行:yum install ruby
(京淘提供的虛擬機已默認裝好)
3.驗證是否已安裝好ruby
執行:ruby -v
4.肯定Redis的集羣架構
本例中搭建的是6臺Redis節點,實現方式是在一臺虛擬機上啓動6個Redis服務進程,每一個進程至關因而一個Redis
節點(固然,也能夠在6臺虛擬機或物理機上搭建),最後造成的集羣架構是:3主3從,每一個Redis都有一個對應的
訪問端口,以下圖:
5.在Redis安裝目錄下建立cluster目錄,並在cluster目錄下建立6個目錄,目錄名爲:
7000,7001,7002,7003,7004,7005
注:這樣作的目的是爲了更清晰的管理,路徑以及目錄名是本身定的
[root@localhost redis-3.0.7]# mkdir cluster
[root@localhost cluster]# mkdir 7000 7001 7002 7003 7004 7005
6.將redis.conf配置文件拷貝到這個六個目錄下,以7000目錄爲例:
[root@localhost cluster]# cp ../redis.conf 7000
7.逐一編輯每一個目錄下的配置文件,以7000目錄的配置文件爲例:
Redis集羣搭建
分區 新分區 2 的第 12 頁
7.逐一編輯每一個目錄下的配置文件,以7000目錄的配置文件爲例:
示例:
port 7000 //端口7000
bind 本機ip //默認ip爲127.0.0.1 須要改成其餘節點機器可訪問的ip 不然建立集羣時沒法
訪問對應的端口,沒法建立集羣
daemonize yes //redis後臺運行
pidfile /home/software/redis-3.0.7/cluster/7000/redis_7000.pid //pidfile文件對應7000
cluster-enabled yes //開啓集羣 把註釋#去掉
cluster-config-file nodes-7000.conf //集羣的配置 配置文件首次啓動自動生成
appendonly yes //aof日誌開啓 有須要就開啓,它會每次寫操做都記錄一條日誌
注:須要將主從配置項註釋掉
#slave of ……
8.將7000目錄下配置好的文件拷貝到其餘5個目錄:
[root@localhost 7000]# cp redis.conf ../7001
[root@localhost 7000]# cp redis.conf ../7002
[root@localhost 7000]# cp redis.conf ../7003
[root@localhost 7000]# cp redis.conf ../7004
[root@localhost 7000]# cp redis.conf ../7005
9.更改每一個目錄下的配置文件,以更改7001目錄的配置文件爲例:
[root@localhost 7001]#vim redis.conf
而後在編輯模式下執行 :%s/7000/7001/g #替換全部7000爲7001
其餘的目錄同理。
10.啓動6個Redis進程
爲了後續啓動方便,能夠編輯shell腳本。
在cluster目錄下,執行:vim start.sh
內容示例:
#!/bin/sh
redis-server 7000/redis.conf &
redis-server 7001/redis.conf &
redis-server 7002/redis.conf &
redis-server 7003/redis.conf &
redis-server 7004/redis.conf &
redis-server 7005/redis.conf &
中止腳本:
redis-cli -p 7000 shutdown
redis-cli -p 7001 shutdown
redis-cli -p 7002 shutdown
redis-cli -p 7003 shutdown
redis-cli -p 7004 shutdown
redis-cli -p 7005 shutdown
11.驗證6個Redis進程是否已啓動:
執行:ps -ef | grep redis
12.使6個Redis進程變成一個集羣:
分區 新分區 2 的第 13 頁
12.使6個Redis進程變成一個集羣:
切換到Redis安裝目錄下的src目錄下,找到:redis-trib.rb 這個文件,並將這個文件複製到 /usr/local/bin 目錄下
[root@localhost src]# cp redis-trib.rb /usr/local/bin/
而後執行:
./redis-trib.rb create --replicas 1 192.168.234.231:7000 192.168.234.231:7001 192.168.234.231:7002 192.168.234.231:7003
192.168.234.231:7004 192.168.234.231:7005
上圖顯示:三個主三個從
13.執行:redis-cli -h 192.168.234.231 -c -p 7000
14.執行測試:
好比進入7002節點,設置一對k,v 會發現k,v會被自動分配到7001節點
分區 新分區 2 的第 14 頁
備註:如何查看某個redis是不是主仍是從
在redis命令行內,執行:info replication
分區 新分區 2 的第 15 頁
實現步驟:
1.引入Jedis的相關依賴
2.引入Redis的屬性配置文件
4.引入Redis集羣整合的加載工具類
>RedisCluster.java
拷貝到jt-common工程下的util包下
5.引入Redis集羣和Spring的整合文件
6.改寫ItemCatService代碼:
代碼示意:
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private JedisCluster rsCluster;
private static final ObjectMapper MAPPER=new ObjectMapper();
@Override
ItemCat itemCat = new ItemCat();
itemCat.setParentId(parentId);
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
String jsonResult=rsCluster.get(ITEM_CAT_KEY);
List<ItemCat> resultList=itemCatMapper.select(itemCat);
rsCluster.set(ITEM_CAT_KEY,MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(jsonResult)){
return MAPPER.readValue(MAPPER.readTree(jsonResult).traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
}else{
}
try {
return itemCatMapper.select(itemCat);
} catch (Exception e) {
}
public List<ItemCat> findItemCatList(Long parentId) {
}
Redis集羣和Spring整合
分區 新分區 2 的第 16 頁
}
分區 新分區 2 的第 17 頁
Redis緩存數據的持久化
redis自身支持兩種持久化方式RDB和AOF
一、RDB是定時對數據庫內存作快照的方式備份整個內存數據庫,這種方式,在redis或者服務
器故障的時候有可能會丟失大量數據,可是這種方式是主進程fork一個子進程來執行,不影響
到主進程的效率,也不會阻塞,同時保存數據集的完整性,若是對數據丟失能容忍一個小時左
右的數據,能夠採用這種方式,性能高。
二、AOF是將redis全部寫的操做做爲日誌存在AOF文件中,採用追加的方式,一般能夠設置no:
不作aof追加,always,每次寫操做都作一次追加aof文件,everysec:每秒鐘追加一次,其中
always不會丟失任何數據,可是會耗不少性能,其中everysec是推薦使用的,其速度也和rdb
相差無幾
若是每隔一段時間進行數據持久化,咱們叫「半持久化」。
若是每次操做都進行數據持久化,咱們叫「全持久化」。
但最多見的配置,就是關閉AOF,使用RDB方式作持久化。
RDB持久化默認生成的文件名爲dump.rdb,這個能夠經過配置文件配置。
Redis沒有專門的RDB文件載入命令,只要Redis服務器開啓,就會檢測RDB文件是否存在,
就會自動載入RDB文件,
注意:若是服務器開啓了AOF持久化功能,服務器會優先使用AOF文件來還原數據庫狀態,
只有在AOF持久化功能關閉的時候,纔會使用RDB文件來還原數據庫狀態。
RDB方式能夠自動保存,也能夠能夠經過手動執行,save命令和bgsave命令
注:利用save命令執行持久化操做時,服務器是被阻塞的,此時redis不能對外提供服務。
bgsave命令執行持久化操做時,服務器是不會被阻塞的,由於是單獨啓動一個線程來處理
的,建議使用這種方式作數據持久化
Redis.conf配置文件裏,有一項配置是和RDB持久相關的參數
save 900 1
save 300 10
save 60 10000
以上表示的意思是,
900秒以內對服務進行了至少一次修改
300秒以內服務器進行了至少10次修改
60秒以內對服務器進行了至少10000次修改。
這些條件知足其中的任意一個bgsave命令就會自動執行。
Redis 數據持久化
2016年1月5日
16:19
分區 新分區 2 的第 18 頁
1. Redis默認不是以守護進程的方式運行,能夠經過該配置項修改,使用yes啓用守護進程
daemonize no
2. 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,能夠經過
pidfile指定
pidfile /var/run/redis.pid
3. 指定Redis監聽端口,默認端口爲6379,redis做者說由於6379在手機按鍵上MERZ對應的號
碼,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4. 綁定的主機地址
bind 127.0.0.1
5.當客戶端閒置多長時間後關閉鏈接,若是指定爲0,表示關閉該功能
timeout 300
6. 指定日誌記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認爲
verbose
loglevel verbose
7. 日誌記錄方式,默認爲標準輸出,若是配置Redis爲守護進程方式運行,而這裏又配置爲日
志記錄方式爲標準輸出,則日誌將會發送給/dev/null
logfile stdout
8. 設置數據庫的數量,默認數據庫爲0,可使用SELECT <dbid>命令在鏈接上指定數據庫id
databases 16
Redis經常使用參數設置
分區 新分區 2 的第 19 頁
databases 16
9. 指定在多長時間內,有多少次更新操做,就將數據同步到數據文件,能夠多個條件配合
save <seconds> <changes>
Redis默認配置文件中提供了三個條件:
save 900 1
save 300 10
save 60 10000
分別表示900秒(15分鐘)內有1個更改,300秒(5分鐘)內有10個更改以及60秒內有10000個
更改。
10. 指定存儲至本地數據庫時是否壓縮數據,默認爲yes,Redis採用LZF壓縮,若是爲了節省
CPU時間,能夠關閉該選項,但會致使數據庫文件變的巨大
rdbcompression yes
11. 指定本地數據庫文件名,默認值爲dump.rdb
dbfilename dump.rdb
12. 指定本地數據庫存放目錄
dir ./
13. 設置當本機爲slave服務時,設置master服務的IP地址及端口,在Redis啓動時,它會自動從
master進行數據同步
slaveof <masterip> <masterport>
14. 設置同一時間最大客戶端鏈接數,默認無限制,Redis能夠同時打開的客戶端鏈接數爲Redis
進程能夠打開的最大文件描述符數,若是設置maxclients 0,表示不做限制。當客戶端鏈接數
分區 新分區 2 的第 20 頁
進程能夠打開的最大文件描述符數,若是設置maxclients 0,表示不做限制。當客戶端鏈接數
到達限制時,Redis會關閉新的鏈接並向客戶端返回max number of clients reached錯誤信息
maxclients 128
15. 指定Redis最大內存限制,Redis在啓動時會把數據加載到內存中,達到最大內存後,Redis
會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大內存設置,將沒法再
進行寫入操做,但仍然能夠進行讀取操做。Redis新的vm機制,會把Key存放內存,Value會存
放在swap區
maxmemory <bytes>
16. 指定是否在每次更新操做後進行日誌記錄,Redis在默認狀況下是異步的把數據寫入磁盤,
若是不開啓,可能會在斷電時致使一段時間內的數據丟失。由於redis自己同步數據文件是按
上面save條件來同步的,因此有的數據會在一段時間內只存在於內存中。默認爲no
appendonly no
17. 指定更新日誌文件名,默認爲appendonly.aof
appendfilename appendonly.aof
18. 指定更新日誌條件,共有3個可選值:
no:表示等操做系統進行數據緩存同步到磁盤(快)
always:表示每次更新操做後手動調用fsync()將數據寫到磁盤(慢,安全)
everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
19. 指定是否啓用虛擬內存機制,默認值爲no,不開啓。
若是開啓,則Redis將訪問量較少的頁即冷數據swap到磁盤上,訪問多的頁面由磁盤自動換出
到內存中
vm-enabled no
分區 新分區 2 的第 21 頁
vm-enabled no
20. 虛擬內存文件路徑,默認值爲/tmp/redis.swap,不可多個Redis實例共享
vm-swap-file /tmp/redis.swap
21. 設置在向客戶端應答時,是否把較小的包合併爲一個包發送,默認爲開啓
glueoutputbuf yes
22.rdbchecksum no
檢查RDB數據的正確性,會犧牲10%的性能,故建議關閉.
=============================================================
redis狀態與性能監控
一、redis-benchmark
redis基準信息,redis服務器性能檢測
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
100個併發鏈接,100000個請求,檢測host爲localhost 端口爲6379的redis服務器性能
分區 新分區 2 的第 22 頁
Redis 和 Memcache 都是基於內存的數據存儲系統,Redis的做者Salvatore Sanfilippo曾經對這兩
種基於內存的數據存儲系統進行過比較:
Redis支持服務器端的數據操做:Redis相比Memcached來講,擁有更多的數據結構和並支持更
豐富的數據操做,一般在Memcached裏,你須要將數據拿到客戶端來進行相似的修改再set回
去。這大大增長了網絡IO的次數和數據體積。在Redis中,這些複雜的操做一般和通常的
GET/SET同樣高效。因此,若是須要緩存可以支持更復雜的結構和操做,那麼Redis會是不錯的
選擇。
內存使用效率對比:使用簡單的key-value存儲的話,Memcached的內存利用率更高,而若是
Redis採用hash結構來作key-value存儲,因爲其組合式的壓縮,其內存利用率會高於
Memcached。
性能對比:因爲Redis只使用單核,而Memcached可使用多核,因此平均每個核上Redis在
存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於
Redis,雖然Redis最近也在存儲大數據的性能上進行優化,可是比起Memcached,仍是稍有遜
色。
一、數據類型支持不一樣
與Memcached僅支持簡單的key-value結構的數據記錄不一樣,Redis支持的數據類型要豐富
得多。最爲經常使用的數據類型主要由五種:String、Hash、List、Set和Sorted Set
二、內存管理機制不一樣
在Redis中,並非全部的數據都一直存儲在內存中的。這是和Memcached相比一個最大的
區別。當物理內存用完時,Redis能夠將一些好久沒用到的value交換到磁盤,可是Redis會緩
存全部的key的信息。
這種特性使得Redis能夠保持超過其機器自己內存大小的數據。固然,機器自己的內存必需要
可以保持全部的key,畢竟這些數據是不會進行swap操做的。
對於像Redis和Memcached這種基於內存的數據庫系統來講,內存管理的效率高低是影響系
統性能的關鍵因素。傳統C語言中的malloc/free函數是最經常使用的分配和釋放內存的方法,但
是這種方法存在着很大的缺陷:首先,對於開發人員來講不匹配的malloc和free容易形成內
存泄露;其次頻繁調用會形成大量內存碎片沒法回收從新利用,下降內存利用率;最後做爲系
Redis和Memcached的對比
分區 新分區 2 的第 23 頁
存泄露;其次頻繁調用會形成大量內存碎片沒法回收從新利用,下降內存利用率;最後做爲系
統調用,其系統開銷遠遠大於通常函數調用。因此,爲了提升內存的管理效率,高效的內存管
理方案都不會直接使用malloc/free調用。Redis和Memcached均使用了自身設計的內存管理
機制,可是實現方法存在很大的差別,下面將會對二者的內存管理機制分別進行介紹。
Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,
將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以徹底解決內存碎
片問題。
當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的
Slab Class,而後經過查詢Memcached保存着的該Slab Class內空閒Chunk的列表就能夠找
到一個可用於存儲數據的Chunk。當一條數據庫過時或者丟棄時,該記錄所佔用的Chunk就
能夠回收,從新添加到空閒列表中。
Redis的內存管理主要採用的是包裝的mallc/free,相較於Memcached的內存管理方法來
說,要簡單不少。
3.數據持久化支持
Redis雖然是基於內存的存儲系統,可是它自己是支持內存數據的持久化的,並且提供兩種主
要的持久化策略:RDB快照和AOF日誌。而memcached是不支持數據持久化操做的。
四、集羣管理的不一樣
Memcached是全內存的數據緩衝系統,Redis雖然支持數據的持久化,可是全內存畢竟纔是
其高性能的本質。做爲基於內存的存儲系統來講,機器物理內存的大小就是系統可以容納的最
大數據量。若是須要處理的數據量超過了單臺機器的物理內存大小,就須要構建分佈式集羣來
擴展存儲能力。
Memcached自己並不支持分佈式,所以只能在客戶端經過像一致性哈希這樣的分佈式算法來
實現Memcached的分佈式存儲。當客戶端向Memcached集羣發送數據以前,首先會經過內
置的分佈式算法計算出該條數據的目標節點,而後數據會直接發送到該節點上存儲。但客戶端
查詢數據時,一樣要計算出查詢數據所在的節點,而後直接向該節點發送查詢請求以獲取數
據。
分區 新分區 2 的第 24 頁
相較於Memcached只能採用客戶端實現分佈式存儲,Redis更偏向於在服務器端構建分佈式
存儲。最新版本的Redis已經支持了分佈式存儲功能。Redis Cluster是一個實現了分佈式且允
許單點故障的Redis高級版本,它沒有中心節點,具備線性可伸縮的功能。在數據的放置策略
上,Redis Cluster使用的分佈式算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。
爲了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。當
Master節點退出後,集羣會自動選擇一個Slave節點成爲新的Master節點。
分區 新分區 2 的第 25 頁
什麼是redis?
Redis 是一個基於內存的高性能key-value數據庫
Reids的特色
Redis本質上是一個Key-Value類型的內存數據庫,很像memcached,整個數據庫通通加載在內
存當中進行操做,按期經過異步操做把數據庫數據flush到硬盤上進行保存。由於是純內存操
做,Redis的性能很是出色,每秒能夠處理超過10萬次讀寫操做,是已知性能最快的Key-Value
DB。
Redis的出色之處不只僅是性能,Redis最大的魅力是支持保存多種數據結構,此外單個value的
最大限制是1GB,不像memcached只能保存1MB的數據,所以Redis能夠用來實現不少有用的功
能,比方說用他的List來作FIFO雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的Set
能夠作高性能的tag系統等等。另外Redis也能夠對存入的Key-Value設置expire時間,所以也可
以被看成一 個功能增強版的memcached來用。
Redis的主要缺點是數據庫容量受到物理內存的限制,不能用做海量數據的高性能讀寫,所以
Redis適合的場景主要侷限在較小數據量的高性能操做和運算上。
Redis支持的數據類型
Redis經過Key-Value的單值不一樣類型來區分, 如下是支持的類型:
String
Lists
Set 求交集、並集
Sorted Set
hashes
爲何redis須要把全部數據放到內存中?
Redis爲了達到最快的讀寫速度將數據都讀到內存中,並經過異步的方式將數據寫入磁盤。所
以redis具備快速和數據持久化的特徵。若是不將數據放在內存中,磁盤I/O速度爲嚴重影響
redis的性能。在內存愈來愈便宜的今天,redis將會愈來愈受歡迎。
若是設置了最大使用的內存,則數據已有記錄數達到內存限值後不能繼續插入新值。
Redis總結
分區 新分區 2 的第 26 頁
Redis是單進程單線程的
redis利用隊列技術將併發訪問變爲串行訪問,消除了傳統數據庫串行控制的開銷
虛擬內存
當你的key很小而value很大時,使用VM的效果會比較好.由於這樣節約的內存比較大.
當你的key不小時,能夠考慮使用一些很是方法將很大的key變成很大的value,好比你能夠考慮將
key,value組合成一個新的value.
vm-max-threads這個參數,能夠設置訪問swap文件的線程數,設置最好不要超過機器的核數,若是
設置爲0,那麼全部對swap文件的操做都是串行的.可能會形成比較長時間的延遲,可是對數據完
整性有很好的保證.
本身測試的時候發現用虛擬內存性能也不錯。若是數據量很大,能夠考慮分佈式或者其餘數據

分佈式
redis支持主從的模式。原則:Master會將數據同步到slave,而slave不會將數據同步到
master。Slave啓動時會鏈接master來同步數據。
這是一個典型的分佈式讀寫分離模型。咱們能夠利用master來插入數據,slave提供檢索服務。
這樣能夠有效減小單個機器的併發訪問數量
數據分片模型
爲了解決讀寫分離模型的缺陷,能夠將數據分片模型應用進來。
能夠將每一個節點當作都是獨立的master,而後經過業務實現數據分片。
結合上面兩種模型,能夠將每一個master設計成由一個master和多個slave組成的模型。
Redis的回收策略
volatile-lru:從已設置過時時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘

分區 新分區 2 的第 27 頁
volatile-ttl:從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰
volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
使用Redis有哪些好處?
(1) 速度快,由於數據存在內存中,相似於HashMap,HashMap的優點就是查找和操做的時間
複雜度都是O(1)
(2) 支持豐富數據類型,支持string,list,set,sorted set,hash
(3) 支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不
執行
(4) 豐富的特性:可用於緩存,消息,按key設置過時時間,過時後將會自動刪除
redis相比memcached有哪些優點?
(1) memcached全部的值均是簡單的字符串,redis做爲其替代者,支持更爲豐富的數據類型
(2) redis的速度比memcached快不少
(3) redis能夠持久化其數據
redis常見性能問題和解決方案:
(1) Master最好不要作任何持久化工做,如RDB內存快照和AOF日誌文件,可讓它的slave來
作持久化工做。
(2) 若是數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次
分區 新分區 2 的第 28 頁
(3) 爲了主從複製的速度和鏈接的穩定性,Master和Slave最好在同一個局域網內
(4) 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <-
Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。若是Master掛了,能夠馬上啓
用Slave1作Master,其餘不變。
MySQL裏有2000w數據,redis中只存20w的數據,如何保證redis中的數據
都是熱點數據
相關知識:redis 內存數據集大小上升到必定大小的時候,就會施行數據淘汰策略。redis 提供
6種數據淘汰策略
Memcache與Redis的區別都有哪些?
Redis 常見的性能問題都有哪些?如何解決?
1).Master寫內存快照,save命令調度rdbSave函數,會阻塞主線程的工做,當快照比較大時對
性能影響是很是大的,會間斷性暫停服務,因此Master最好不要寫內存快照。
2).Master AOF持久化,若是不重寫AOF文件,這個持久化方式對性能的影響是最小的,可是
AOF文件會不斷增大,AOF文件過大會影響Master重啓的恢復速度。Master最好不要作任何持
久化工做,包括內存快照和AOF日誌文件,特別是不要啓用內存快照作持久化,若是數據比較關
鍵,某個Slave開啓AOF備份數據,策略爲每秒同步一次。
3).Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會佔大量的CPU和內存資源,導
致服務load太高,出現短暫服務暫停現象。
4). Redis主從複製的性能問題,爲了主從複製的速度和鏈接的穩定性,Slave和Master最好在同
一個局域網內
redis 最適合的場景
分區 新分區 2 的第 29 頁
redis 最適合的場景
Redis最適合全部數據in-momory的場景
分區 新分區 2 的第 30 頁
 java

相關文章
相關標籤/搜索