課程計划:
- 第五天
- 1、首頁輪播圖的展示
- 2、首頁大廣告展示流程圖
- 3、Redis的安裝及使用
- 4、Redis集群的搭建
- 5、向業務邏輯中添加緩存
- 6、Jedis的使用(redis的客戶端)
- 7、緩存同步
- 8、Solr服務器安裝
1、首頁輪播圖的展示
taotao-portal-web工程中,動態展示內容信息。
前端團隊:負責JS,html等開發。
后端團隊:負責后台的開發並提供數據給前端。
1.1、功能分析
只需要動態生成一個json數據,輪播圖就可以動態展示。
taotao-portal-web工程下的index.jsp中:
Json數據格式:
[
{
"srcB": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg",
"height": 240,
"alt": "",
"width": 670,
"src": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg",
"widthB": 550,
"href": "http://sale.jd.com/act/e0FMkuDhJz35CNt.html?cpdad=1DLSUE",
"heightB": 240
},
{
"srcB": "http://image.taotao.com/images/2015/03/03/2015030304353109508500.jpg",
"height": 240,
"alt": "",
"width": 670,
"src": "http://image.taotao.com/images/2015/03/03/2015030304353109508500.jpg",
"widthB": 550,
"href": "http://sale.jd.com/act/UMJaAPD2VIXkZn.html?cpdad=1DLSUE",
"heightB": 240
},
......
]
分析:
taotao-portal-web 需要自己自定義的POJO的類型數據的列表。
taotao-content 是服務層公用的,可以被其他的系統(表現層的系統)來調用。
為了通用性:taotao-content 服務層中獲取tb_content的內容列表 即:list<TbContent>
taotao-portal-web 表現層需要拿到tb_content的列表,然后進行轉換成自定義的類型的數據列表即可。
從tb_content表中取數據,根據(葉子節點)內容分類id查詢列表(內容列表)。
內容分類id固定,需要配置在屬性文件中
。
圖片的width、height配置在屬性文件中
。
alt屬性從字段sub_title中獲取。
src --> pic
srcB --> pic2
href --> url
URL:/index
參數:無。
返回值:首頁頁面(數據是JSON,設置在Model中)
業務邏輯:
1、根據分類的id 查詢內容列表(List<TbContent>)
2、服務層發布服務。
3、表現層引入服務。
4、調用服務,轉換成自定義的數據類型(Ad1Node)
的列表。
5、將數據列表設置到Model
中,返回給頁面。
需要創建一個pojo轉換成頁面需要的json數據格式。放入taotao-portal-web工程的com.taotao.portal.pojo中。
AD1Node.java
/**
* 前台大廣告位需要的pojo數據類型
* @author chenmingjun
* @date 2018年11月18日下午4:03:34
* @version 1.0
*/
public class AD1Node implements Serializable {
private static final long serialVersionUID = 1L;
private String srcB;
private Integer height;
private String alt;
private Integer width;
private String src;
private Integer widthB;
private String href;
private Integer heightB;
public String getSrcB() {
return srcB;
}
public void setSrcB(String srcB) {
this.srcB = srcB;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public String getAlt() {
return alt;
}
public void setAlt(String alt) {
this.alt = alt;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public Integer getWidthB() {
return widthB;
}
public void setWidthB(Integer widthB) {
this.widthB = widthB;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public Integer getHeightB() {
return heightB;
}
public void setHeightB(Integer heightB) {
this.heightB = heightB;
}
@Override
public String toString() {
return "AD1Node [srcB=" + srcB + ", height=" + height + ", alt=" + alt + ", width=" + width + ", src=" + src
+ ", widthB=" + widthB + ", href=" + href + ", heightB=" + heightB + "]";
}
}
1.2、Dao層
從tb_content表中取出數據,根據內容分類id查詢內容列表。可以使用逆向工程生成的Mapper。
1.3、Service層
參數:Long categoryId
返回值:List<TbContent>
@Override
public List<TbContent> getContentListByCategoryId(Long categoryId) {
TbContentExample contentExample = new TbContentExample();
Criteria criteria = contentExample.createCriteria();
criteria.andCategoryIdEqualTo(categoryId);
List<TbContent> list = contentMapper.selectByExample(contentExample);
return list;
}
1.3.1、發布服務
在taotao-content-service工程applicationContext-service.xml中發布服務

1.4、表現層
在taotao-portal-web中實現,查詢首頁輪播圖的內容。
1.4.1、引用服務
先在taotao-protal-web項目中引入對taotao-content-interface的依賴,如圖:

在taotao-content-web工程springmvc.xml中引入服務

1.4.2、Controller
在首頁展示之前,對數據進行處理,然后展示首頁,需要在IndexController中實現。
/**
* 前台首頁展示Controller
* @author chenmingjun
* @date 2018年12月31日
* @version V1.0
*/
@Controller
public class IndexController {
@Autowired
private ContentService contentService;
@Value("${AD1_CATEGORY_ID}")
private Long AD1_CATEGORY_ID;
@Value("${AD1_HEIGHT}")
private Integer AD1_HEIGHT;
@Value("${AD1_HEIGHT_B}")
private Integer AD1_HEIGHT_B;
@Value("${AD1_WIDTH}")
private Integer AD1_WIDTH;
@Value("${AD1_WIDTH_B}")
private Integer AD1_WIDTH_B;
/**
* 展示前台首頁,並展示首頁輪播圖(大廣告)+展示小廣告......
* @return
*/
@RequestMapping("/index")
public String showIndex(Model model) {
// 展示首頁輪播圖
// 1、引入服務
// 2、注入服務
// 3、調用方法查詢TbContent的列表
List<TbContent> contentList = contentService.getContentListByCategoryId(AD1_CATEGORY_ID);
// 4、把TbContent的列表轉換為AD1Node列表
List<AD1Node> aD1NodeList = new ArrayList<>();
for (TbContent tbContent : contentList) {
AD1Node aD1Node = new AD1Node();
aD1Node.setAlt(tbContent.getSubTitle());
aD1Node.setHref(tbContent.getUrl());
aD1Node.setSrc(tbContent.getPic());
aD1Node.setSrcB(tbContent.getPic2());
aD1Node.setHeight(AD1_HEIGHT);
aD1Node.setHeightB(AD1_HEIGHT_B);
aD1Node.setWidth(AD1_WIDTH);
aD1Node.setWidthB(AD1_WIDTH_B);
aD1NodeList.add(aD1Node);
}
// 5、把AD1Node列表轉換為JSON數據
String json = JsonUtils.objectToJson(aD1NodeList);
// 6、把JSON數據設置到request域中去(Model)
model.addAttribute("ad1", json);
// 展示小廣告......等等省略了,以后實現
return "index";
}
}
屬性文件所在位置:

在taotao-portal-web中的springmvc.xml中還需要配置:
<!-- 配置加載屬性文件 -->
<context:property-placeholder location="classpath:resource/resource.properties"/>
1.5、測試
后台數據如下圖所示:

前台瀏覽器顯示界面:

其他廣告位同理。
2、首頁大廣告展示流程圖

首頁是系統的門戶
,也就是系統的入口
。所以首頁的訪問量是這個系統最大的。如果每次展示首頁都從數據庫中查詢首頁的內容信息,那么勢必會對數據庫造成很大的壓力,所以需要使用緩存來減輕數據庫壓力。
實現緩存的工具有很多,現在比較流行的是redis。
首頁大廣告展示流程:
展示流程:先從緩存取,如果不存在,從數據庫取出來,寫入緩存,再返回頁面;如果存在key,直接從緩存中取出來,展示到頁面。
同步緩存:當事務提交(更新,刪除,插入)后,需要同步緩存,直接根據Key刪除redis的key(清空緩存),再展示時,由上邊的流程展示。
3、Redis的安裝及使用
3.1、redis的下載
官網地址:http://redis.io/
下載地址:http://download.redis.io/releases/redis-3.0.0.tar.gz
3.2、redis的安裝
安裝redis需要c語言的編譯環境,如果沒有gcc需要在線安裝。如下命令:
[root@itheima ~]# yum -y install gcc-c++
檢測是否有gcc環境,只需輸入命令:
[root@itheima ~]# gcc
[root@itheima ~]# gcc
gcc: 致命錯誤:沒有輸入文件
編譯中斷。
[root@itheima ~]#
出現如上所述內容,表示gcc安裝成功。
安裝步驟:
第一步:將redis的源碼包上傳到linux系統。
第二步:解壓縮redis的源碼包。
第三步:進行編譯。cd到解壓后的目錄,輸入命令:make
第四步:進行安裝。輸入命令:make install PREFIX=/usr/local/redis
第五步:檢查目錄是否存在。在/usr/local/redis下有bin目錄,則說明安裝成功。
3.3、連接redis
3.3.1、redis的啟動
前端啟動:在redis的安裝目錄下直接啟動redis-server
[root@itheima bin]# pwd
/usr/local/redis/bin
[root@itheima bin]# ./redis-server
后台啟動:
把/root/redis-3.0.0/redis.conf復制到/usr/local/redis/bin目錄下
[root@itheima redis-3.0.0]# cp redis.conf /usr/local/redis/bin/
修改配置文件:將daemonize由no改為yes
再次啟動redis:
[root@itheima bin]# ./redis-server redis.conf
查看redis進程:
[root@itheima bin]# ps aux | grep redis
root 5845 0.4 0.2 140888 2104 ? Ssl 22:51 0:00 ./redis-server *:6379
root 5858 0.0 0.0 112720 980 pts/1 R+ 22:51 0:00 grep --color=auto redis
[root@itheima bin]#
前端啟動,不能更換終端,影響下一步操作。而后台啟動,只在進程中悄悄啟動。推薦使用后台啟動。
3.3.2、使用redis自帶的客戶端redis-cli連接redis
使用redis-cli建立連接:
[root@itheima bin]# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
默認連接localhost運行在6379端口的redis服務。
連接其他ip和端口:
[root@itheima bin]# ./redis-cli -h 192.168.25.153 -p 6379
192.168.25.153:6379> ping
PONG
192.168.25.153:6379>
-h:連接的服務器的地址
-p:服務的端口號
退出redis連接的三種方式:
第一種方式:
[root@itheima bin]# ./redis-cli
127.0.0.1:6379> quit
[root@itheima bin]#
第二種方式:
[root@itheima bin]# ./redis-cli
127.0.0.1:6379> exit
[root@itheima bin]#
第三種方式:
Ctrl+C
3.3.3、使用redis的桌面客戶端軟件連接redis
先安裝:redis-desktop-manager-0.7.9.809.exe,注意:該軟件只能連接redis單機版。

安裝好后,雙擊打開軟件

redis默認有16個庫,如果不指定庫,默認存儲在索引為0的庫中。

3.3.4、關閉redis服務
第一種:通過使用redis自帶的客戶端redis-cli進行關閉,使用 shutdown 命令。
[root@itheima bin]# ./redis-cli
127.0.0.1:6379> shutdown
not connected>
第二種:使用 kill 命令。
找到對應的redis的進程id 然后使用命令:(pid為進程id)
[root@itheima bin]# kill -9 pid
3.4、redis五種數據類型
3.4.1、String:key-value
redis命令不區分大小寫,但是key區分大小寫
的。
redis中所有的數據都是字符串
。
redis是單線程
的,所以不適合存儲比較大的數據,最好要存小且能快速處理完的東西。
使用incr
命令,如果key不存在,會自動創建key並自動+1。
set key value 設置值
get key 獲取值
incr key 加一
decr key 減一
127.0.0.1:6379> set key1 2
OK
127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> get key1
"2"
127.0.0.1:6379> get key2
"value2"
127.0.0.1:6379> Get key2
"value2"
127.0.0.1:6379> incr key1
(integer) 3
127.0.0.1:6379> decr key1
(integer) 2
127.0.0.1:6379>
3.4.2、Hash: key-field-value
相當於一個key對應一個map (map中又是key-value),
一般應用於歸類。
hset key field value
hget key field
hincrby key field num
127.0.0.1:6379> hset hkey1 filed1 value1
(integer) 1
127.0.0.1:6379> hset hkey1 filed2 2
(integer) 1
127.0.0.1:6379> hget hkey1 filed1
"value1"
127.0.0.1:6379> hget hkey1 filed2
"2"
127.0.0.1:6379> hincrby hkey1 filed2 1
(integer) 3
127.0.0.1:6379> hincrby hkey1 filed2 -1
(integer) 2
127.0.0.1:6379>
3.4.3、List
List是有順序可重復(數據結構中的:雙鏈表,隊列)
。
可作為鏈表,可以從左添加元素,也可以從右添加元素。
lpush list a b c d (從左添加元素)
rpush list 1 2 3 4 (從右邊添加元素)
lrange list 0 -1 (從 0 到 -1 元素查看:也就表示查看所有)
lpop list (從左邊取,刪除)
rpop list (從右邊取,刪除)
127.0.0.1:6379> lpush list1 a b c d
(integer) 4
127.0.0.1:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> rpush list1 1 2 3 4
(integer) 8
127.0.0.1:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379> lpop list1
"d"
127.0.0.1:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
7) "4"
127.0.0.1:6379> rpop list1
"4"
127.0.0.1:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379>
3.4.4、Set
Set無順序,不能重復。
sadd set1 a b c d d (向set1中添加元素)元素不重復
smembers set1 (查詢元素)
srem set1 a (刪除元素)
127.0.0.1:6379> sadd set1 a a a b b c
(integer) 3
127.0.0.1:6379> smembers set1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> srem set1 a
(integer) 1
127.0.0.1:6379> smembers set1
1) "c"
2) "b"
127.0.0.1:6379>
3.4.5、SortedSet(zset)
SortedSet有順序,不能重復。
適合做排行榜 排序需要一個分數屬性。
zadd zset1 8 a 4 b 5 c 1 d (添加元素:zadd key score member)
zrange key start stop [WITHSCORES] (查看所有元素:zrange key 0 -1 withscores)
如果要查看分數,需要加上withscores
zrange zset1 0 -1 (從小到大)
zrevrange zset1 0 -1 (從大到小)
zincrby zset1 score member (對元素 member 增加 score)
127.0.0.1:6379> zadd zset1 8 a 4 b 5 c 1 d
(integer) 4
127.0.0.1:6379> zrange zset1 0 -1
1) "d"
2) "b"
3) "c"
4) "a"
127.0.0.1:6379> zadd zset1 9 a
(integer) 0
127.0.0.1:6379> zrange zset1 0 -1
1) "d"
2) "b"
3) "c"
4) "a"
127.0.0.1:6379> zrange zset1 0 -1 withscores
1) "d"
2) "1"
3) "b"
4) "4"
5) "c"
6) "5"
7) "a"
8) "9"
127.0.0.1:6379> zrevrange zset1 0 -1
1) "a"
2) "c"
3) "b"
4) "d"
127.0.0.1:6379> zrevrange zset1 0 -1 withscores
1) "a"
2) "9"
3) "c"
4) "5"
5) "b"
6) "4"
7) "d"
8) "1"
127.0.0.1:6379>
3.5、key 命令
expire key second 設置key的過期時間
ttl key 查看剩余時間(-2 表示不存在,-1 表示已被持久化(永不過期),正數表示剩余的時間)
persist key 清除過期時間,也即持久化,持久化成功體提示 1,不成功提示 0
del key 刪除key
exists key 若key存在,返回1,否則返回0。
select 0 表示選擇0號數據庫。默認是0號數據庫。
redis 默認有16個庫 select num 從0開始換庫
keys * 獲取redis里面所有的key
dbsize 查看當前數據庫的key的數量
flushdb 清空當前庫的所有key
flushall 清空所有庫的key
exists key 是否存在該key
move key db 把當前庫的key移到db號庫中
type key 查看key的類型
3.6、redis持久化方案
redis 數據都放在內存中
。如果機器掛掉,內存的數據就不存在。
需要做持久化處理
,將內存中的數據保存在磁盤,下一次啟動的時候就可以恢復數據到內存中。
方案1:RDB 快照形式(定期將當前時刻的數據保存磁盤中)會產生一個dump.rdb文件。
特點:會存在數據丟失,性能較好,數據備份。
方案2:AOF:append only file (所有對redis的操作命令記錄在aof文件中),恢復數據,重新執行一遍即可。
特點:每秒保存(也可能會存在數據丟失),數據比較完整,耗費性能。其實也可以設置成每次保存,但是此就失去了緩存的意義了。redis默認開啟RDB。
如下圖:

redis.conf 中默認設置了保存規則及時間間隔。
save 開頭的一行就是持久化配置,可以配置多個條件(每行配置一個條件),每個條件之間是“或”的關系。
save 900 1 表示15分鍾(900秒)內至少1個鍵被更改則進行快照。
save 300 10 表示5分鍾(300秒)內至少10個鍵被更改則進行快照。
save 60 10000 表示1分鍾(60秒)內至少10000個鍵被更改則進行快照。
AOF開啟設置,修改 redis.conf 文件,如下圖:
將appendonly設置為yes即可。

同時開啟兩個持久化方案,則按照
AOF的持久化放案恢復數據
。
默認是按照RDB的方式恢復數據,如果開啟了AOF,就是用AOF恢復數據,數據是存在於/usr/local/redis/bin/appendonly.aof文件中。
4、Redis集群的搭建
4.1、redis-cluster架構圖

架構細節詳解如下:
架構細節:
(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 會根據節點數量`大致均等`的將哈希槽映射到不同的節點。如下圖所示:
哈希槽的圖解:

redis-cluster投票,容錯機制圖解:

4.2、redis集群的搭建
因為有投票容錯機制
,所以需要至少3個節點(奇數),為了集群的高可用
,為每一個節點增加一個備份機
(共6台服務器)。
搭建偽分布式集群
方案:在一台機器里面運行6個redis實例。端口需要不同即可(7001-7006)。
4.2.1、集群搭建環境
4.2.2、搭建步驟
參考文章鏈接:https://www.cnblogs.com/chenmingjun/p/9903889.html
創建集群命令:
[root@itheima redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005 192.168.25.153:7006
4.3、集群的使用方法
redis-cli連接集群。連接主節點或者從節點都可以。
[root@itheima redis-cluster]# 7001/redis-cli -h 192.168.25.153 -p 7006 -c
192.168.25.153:7006> set key1 123
-> Redirected to slot [9189] located at 192.168.25.153:7002
OK
192.168.25.153:7002> keys *
1) "key1"
192.168.25.153:7002> set key2 abc
-> Redirected to slot [4998] located at 192.168.25.153:7001
OK
192.168.25.153:7001> keys *
1) "key2"
192.168.25.153:7001> set key3 bbbb
OK
192.168.25.153:7001> set key4 cccc
-> Redirected to slot [13120] located at 192.168.25.153:7003
OK
192.168.25.153:7003>
-c:代表連接的是redis集群
使用命令操作redis集群是和單機版的redids是一樣的。
192.168.25.153:7003> 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:3
cluster_stats_messages_sent:1623
cluster_stats_messages_received:1623
192.168.25.153:7003> cluster nodes #查詢集群的節點
ecb5aafd409740004ac3bf298318e2243f562e4e 192.168.25.153:7004 slave b207611daffa174990c64499495fc42ce3978767 0 1542619629901 4 connected
30775ef3b509604b604b76a4407334fe1fb6304f 192.168.25.153:7006 slave c6514cdac6977ef8a8fbee8c7d5c3e4edd7df585 0 1542619634936 6 connected
fd369b55daa7cdd8640e1e1bfa8fa2ab9cfe39cd 192.168.25.153:7002 master - 0 1542619633928 2 connected 5461-10922
c6514cdac6977ef8a8fbee8c7d5c3e4edd7df585 192.168.25.153:7003 myself,master - 0 0 3 connected 10923-16383
75a701f4cd545ee704ded294c17bbfa3f02eaee1 192.168.25.153:7005 slave fd369b55daa7cdd8640e1e1bfa8fa2ab9cfe39cd 0 1542619631916 5 connected
b207611daffa174990c64499495fc42ce3978767 192.168.25.153:7001 master - 0 1542619632921 1 connected 0-5460
192.168.25.153:7003>
5、Java客戶端Jedis的使用方法
需要把jedis依賴的jar包添加到工程中。Maven工程中需要把jedis的坐標添加到依賴。推薦添加到服務層
。本例中是:taotao-content-service工程中。
第一步:添加jar包的依賴

在taotao-content-service中添加測試方法,測試如下:
5.1、通過單實例連接redis服務器單機版
@Test
public void jedisClientTest() throws Exception {
// 1、創建一個Jedis的連接對象(單實例),需要指定服務端的ip及端口
Jedis jedis = new Jedis("192.168.25.153", 6379);
// 2、選擇要操作的數據庫
jedis.select(2);
// 3、執行redis命令,即使用Jedis對象操作數據庫,每個redis命令對應一個方法
jedis.set("s4", "曉藝,你還好嗎?");
// 從redis中取值
String result = jedis.get("s4");
// 打印結果
System.out.println(result);
// 4、關閉連接
jedis.close();
}
通過單實例連接redis服務器,我們發現每一次連接都需要創建連接,創建連接是比較浪費資源的,所以我們需要使用連接池來連接redis數據庫。
5.2、通過連接池連接redis服務器單機版
測試代碼如下:
/**
* 通過連接池連接redis服務器單機版
*/
@Test
public void jedisPoolTest() throws Exception {
// 1、創建一個連接池JedisPool對象(單實例),需要指定服務端的ip及端口
JedisPool jedisPool = new JedisPool("192.168.25.153", 6379);
// 2、從連接池JedisPool中獲取jedis會話對象
Jedis jedis = jedisPool.getResource();
// 3、使用redis命令操作redis數據庫(方法級別使用:用完之后就要關閉)
String result = jedis.get("s11");
System.out.println(result);
// 4、關閉連接,操作完畢后關閉jedis對象,連接池要回收資源。
jedis.close();
// 5、關閉連接池對象JedisPool
jedisPool.close();
}
5.3、使用spring整合JedisPool連接redis服務器單機版
添加spring的jar包
配置spring配置文件applicationContext.xml
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單機 通過連接池連接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.5.128" />
<constructor-arg name="port" value="6379" />
</bean>
</beans>
測試代碼如下:
/**
* 通過連接池連接redis服務器單機版(整合spring)
*/
@Test
public void jedisPoolTest() {
JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool");
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set("s5", "lisi");
String name = jedis.get("s5");
System.out.println(name);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (jedis != null) {
// 關閉連接
jedis.close();
}
}
}
5.4、使用JedisCluster類連接redis服務器集群版
第一步:使用JedisCluster對象。需要使用Set<HostAndPort>
參數。表示redis節點的列表。
第二步:直接使用JedisCluster對象操作redis。該對象在系統中是單例存在的。
第三步:打印結果。
第四步:在系統關閉前,關閉JedisCluster對象。
/**
* 使用JedisCluster類連接redis集群版
*/
@Test
public void jedisClusterTest() throws Exception {
// 需要使用 Set<HostAndPort> 參數。表示redis節點的列表。
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.25.153", 7001));
nodes.add(new HostAndPort("192.168.25.153", 7002));
nodes.add(new HostAndPort("192.168.25.153", 7003));
nodes.add(new HostAndPort("192.168.25.153", 7004));
nodes.add(new HostAndPort("192.168.25.153", 7005));
nodes.add(new HostAndPort("192.168.25.153", 7006));
// 創建JedisCluster對象,該對象在系統中是單例存在的
JedisCluster jedisCluster = new JedisCluster(nodes);
// 執行JedisCluster對象中的方法,方法和redis中的一一對應
jedisCluster.set("cluster-test", "Jedis connects redis cluster test");
String result = jedisCluster.get("cluster-test");
System.out.println(result);
// 程序結束時需要關閉JedisCluster對象
jedisCluster.close();
}
5.5、使用spring整合JedisCluster連接redis服務器集群版
配置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="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.5.128"></constructor-arg>
<constructor-arg index="1" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.5.128"></constructor-arg>
<constructor-arg index="1" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.5.128"></constructor-arg>
<constructor-arg index="1" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.5.128"></constructor-arg>
<constructor-arg index="1" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.5.128"></constructor-arg>
<constructor-arg index="1" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.5.128"></constructor-arg>
<constructor-arg index="1" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg>
</bean>
</beans>
測試代碼:
private ApplicationContext applicationContext;
@Before
public void init() {
applicationContext = new ClassPathXmlApplicationContext(
"classpath:applicationContext.xml");
}
/**
* 使用spring實現Jedis連接Redis集群
*/
@Test
public void testJedisCluster2() {
JedisCluster jedisCluster = (JedisCluster) applicationContext.getBean("jedisCluster");
jedisCluster.set("name", "xiaoyi");
String value = jedisCluster.get("name");
System.out.println(value);
}
6、向業務邏輯中添加緩存
因為集群是比較消耗成本的
,所以在公司中,一般生產環境使用集群
,開發環境使用單機版
。
我們在項目整合中
都需要有。使用設計模式之策略模式:接口+實現類。
可以開發一個接口,有單機版的實現類
和集群版的實現類
。使用時可以面向接口開發
,不影響業務邏輯,使用spring管理實現類
,部署時切換實現類
即可。
6.1、接口封裝
常用的操作redis的方法提取出一個接口,分別對應單機版和集群版創建兩個實現類。
6.1.1、接口定義
package com.taotao.jedis;
import java.util.Map;
public interface JedisClient {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field); // 刪除hkey
Map<String, String> hgetAll(String key); // 查詢所有的hash類型的列表
}
6.1.2、redis單機版實現類
package com.taotao.jedis;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisClientPool implements JedisClient {
@Autowired
private JedisPool jedisPool;
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}
@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}
@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}
@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}
@Override
public Map<String, String> hgetAll(String key) {
Jedis jedis = jedisPool.getResource();
Map<String, String> map = jedis.hgetAll(key);
jedis.close();
return map;
}
}
applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 注意:我們已經在 applicationContext-service.xml 配置了包掃描器,該配置做了兩件事:既開啟注解,又掃描包 -->
<!-- <context:annotation-config></context:annotation-config> 表示開啟注解,但是不能掃描包。所以這句配置可以不用了。-->
<!-- 如果使用方式二,我們在加載配置文件的時候,要加載所有的配置文件才可以。(本案例中使用的是方式一) -->
<!-- 如果使用方式一,我們在加載配置文件的時候,要加載單個的配置文件即可。 -->
<!-- 配置對redis單機版的連接 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<!-- 手動配置的jedis單機版客戶端實現類bean:會在spring容器中加載 ,原因是:我們已經在 applicationContext-service.xml 配置了包掃描器,該配置做了兩件事:既開啟注解,又掃描包-->
<bean id="jedisClientPool" class="com.taotao.jedis.手動配置的bean"/>
</beans>
注意:
在spring中要使用注解,我們先要開啟注解,開啟注解有兩種方式
:
方式一:配置<context:annotation-config></context:annotation-config>
注解,表示開啟注解,但是不能掃描包。
方式二:配置包掃描器<context:component-scan base-package="com.taotao.content.service"></context:component-scan>
注解,表示掃描所有需要帶@Service注解的類,該配置做了兩件事:既開啟注解,又掃描包。
所以我們只要配置了包掃描器,那么我們手動配置的bean就會在spring容器中加載。特別注意:
如果使用方式二,我們在加載配置文件的時候,要加載所有的配置文件才可以。(本案例中使用的是方式一)
如果使用方式一,我們在加載配置文件的時候,要加載單個的配置文件即可。
6.1.3、redis集群版實現類
package com.taotao.jedis;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisCluster;
public class JedisClientCluster implements JedisClient {
@Autowired
private JedisCluster jedisCluster;
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}
@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}
@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
@Override
public Map<String, String> hgetAll(String key) {
return jedisCluster.hgetAll(key);
}
}
添加此配置到applicationContext-redis.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 注意:我們已經在 applicationContext-service.xml 配置了包掃描器,該配置做了兩件事:既開啟注解,又掃描包 -->
<!-- <context:annotation-config></context:annotation-config> 表示開啟注解,但是不能掃描包。所以這句配置可以不用了。-->
<!-- 如果使用方式二,我們在加載配置文件的時候,要加載所有的配置文件才可以。(本案例中使用的是方式一) -->
<!-- 如果使用方式一,我們在加載配置文件的時候,要加載單個的配置文件即可。 -->
<!-- 配置對redis單機版的連接 -->
<!-- 單機版和集群版不能共存,使用單機版時注釋集群版的配置。使用集群版,把單機版注釋。
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
手動配置的jedis單機版客戶端實現類bean:會在spring容器中加載
<bean id="jedisClientPool" class="com.taotao.jedis.JedisClientPool"/>
-->
<!-- 配置對redis集群版的連接 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg>
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean>
<!-- 手動配置的jedis集群版客戶端實現類bean:會在spring容器中加載 -->
<bean id="jedisClientCluster" class="com.taotao.jedis.JedisClientCluster"/>
</beans>
注意:單機版和集群版不能共存,使用單機版時注釋集群版的配置。使用集群版,把單機版注釋。
6.2、封裝代碼測試
策略設計模式的優勢,只要切換實現類(即簡單注釋下spring配置文件),不需修改測試類。
測試代碼:
public class JedisSpringTest {
@Test
public void testJedisClient() throws Exception {
// 初始化Spring容器,我們已經在 applicationContext-service.xml 配置了包掃描器,需要我們在加載配置文件的時候,要加載所有的配置文件才可以。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml"); // 加載所有配置文件
// 從容器中獲得JedisClient對象
JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
jedisClient.set("first", "100");
String result = jedisClient.get("first");
System.out.println(result);
}
}
命令行中進行測試如下:沒有問題
[root@itheima bin]# ./redis-cli -p 7001 -c
127.0.0.1:7001> get first
-> Redirected to slot [11149] located at 192.168.25.153:7003
"100"
192.168.25.153:7003>
6.3、向業務邏輯中添加緩存
由於我們處於開發階段,所以我們先將我們的連接方式切換為單機版。
6.3.1、功能分析
查詢內容列表時添加緩存。
1、查詢數據庫之前先查詢緩存。
2、查詢到結果,直接響應結果。
3、查詢不到,緩存中沒有需要查詢數據庫。
4、把查詢結果添加到緩存中。
5、返回結果。
向redis中添加緩存,添加緩存我們使用什么樣的數據類型呢?
key:categoryId 字段(field),即我們的查詢條件
value:內容列表。由於redis中不能存java對象,所以需要把java對象轉換成json格式的數據(即json字符串),可以使用工具類。
推薦使用hash類型,因為hash類型可以對key進行歸類。
HASH_KEY:HASH
|--KEY:VALUE
|--KEY:VALUE
|--KEY:VALUE
|--KEY:VALUE注意:添加緩存不能影響正常業務邏輯。
6.3.2、代碼實現
在ContentServiceImpl實現類中添加緩存。
部分代碼如下:
// 通過spring容器注入JedisClient對象
@Autowired
private JedisClient jedisClient;
@Value("${INDEX_CONTENT_KEY}")
private String INDEX_CONTENT_KEY;
@Override
public List<TbContent> getContentListByCategoryId(Long categoryId) {
// 查詢數據庫之前先查詢緩存
// 注意:添加了緩存不能影響正常業務邏輯,所以我們使用try...catch,將異常捕獲,其余的向下繼續執行
try {
// 從緩存中查詢到結果,需要把json格式的數據轉成List返回
String json = jedisClient.hget(INDEX_CONTENT_KEY, categoryId + "");
if (StringUtils.isNotBlank(json)) { // 如果json不是空才去轉換
List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}
// 第一次查詢沒有,緩存中沒有命中,則去查詢數據庫
TbContentExample contentExample = new TbContentExample();
Criteria criteria = contentExample.createCriteria();
criteria.andCategoryIdEqualTo(categoryId);
List<TbContent> list = contentMapper.selectByExample(contentExample);
// 把從數據庫中查詢到的結果添加到緩存
// 注意:添加了緩存不能影響正常業務邏輯,所以我們使用try...catch,將異常捕獲,其余的向下繼續執行
try {
// 添加緩存我們使用什么樣的數據類型呢?答:使用String或者Hash均可,推薦使用Hash類型,因為Hash類型可以對key進行歸類。
jedisClient.hset(INDEX_CONTENT_KEY, categoryId + "", JsonUtils.objectToJson(list));
} catch (Exception e) {
e.printStackTrace();
}
// 返回結果
return list;
}
屬性文件所在的位置:

要想能加載還需要在taotao-content-service工程applicationContext-dao.xml中配置:
<!-- 加載配置文件 -->
<context:property-placeholder location="classpath:properties/*.properties" />
6.4、緩存同步
在對內容信息做增刪改
操作后只需要把對應緩存key
刪除即可。
我們以【添加內容】為例,可以根據categoryId刪除。
@Override
public TaotaoResult saveContent(TbContent content) {
// 注入Mapper
// 補全屬性
content.setCreated(new Date());
content.setUpdated(content.getCreated());
// 將內容數據保存至內容表
contentMapper.insert(content);
try {
// 同步緩存:在對內容信息做【增刪改】操作后只需要把對應緩存key刪除即可。
jedisClient.hdel(INDEX_CONTENT_KEY, content.getCategoryId().toString());
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok();
}
【更新內容】和【刪除內容】加入緩存同步代碼如下:
@Override
public TaotaoResult updateContent(TbContent content) {
// 設置創建時間
content.setCreated(new Date());
// 設置更新時間
content.setUpdated(new Date());
// 將內容數據更新至內容表(全字段更新)
contentMapper.updateByPrimaryKeyWithBLOBs(content);
try {
// 同步緩存:在對內容信息做【增刪改】操作后只需要把對應緩存key刪除即可。
jedisClient.hdel(INDEX_CONTENT_KEY, content.getCategoryId().toString());
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok();
}
@Override
public TaotaoResult getContentText(Long id) {
TbContent content = contentMapper.selectByPrimaryKey(id);
return TaotaoResult.ok(content);
}
@Override
public TaotaoResult deleteContent(List<Long> ids) {
for (Long id : ids) {
TbContent content = contentMapper.selectByPrimaryKey(id);
contentMapper.deleteByPrimaryKey(id);
try {
// 同步緩存:在對內容信息做【增刪改】操作后只需要把對應緩存key刪除即可。
jedisClient.hdel(INDEX_CONTENT_KEY, content.getCategoryId().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
return TaotaoResult.ok();
}
7、附錄
我們在搭建redis集群的時候,會寫一些自定義的批處理文件
,如下圖所示:

具體內容如下:
redis_start_all.sh
cd redis01/
./redis-server redis.conf
cd ..
cd redis02/
./redis-server redis.conf
cd ..
cd redis03/
./redis-server redis.conf
cd ..
cd redis04/
./redis-server redis.conf
cd ..
cd redis05/
./redis-server redis.conf
cd ..
cd redis06/
./redis-server redis.conf
cd ..
redis_shutdown_all.sh
cd redis01/
./redis-cli -h 192.168.25.153 -p 7001 shutdown
cd ..
cd redis02/
./redis-cli -h 192.168.25.153 -p 7002 shutdown
cd ..
cd redis03/
./redis-cli -h 192.168.25.153 -p 7003 shutdown
cd ..
cd redis04/
./redis-cli -h 192.168.25.153 -p 7004 shutdown
cd ..
cd redis05/
./redis-cli -h 192.168.25.153 -p 7005 shutdown
cd ..
cd redis06/
./redis-cli -h 192.168.25.153 -p 7006 shutdown
cd ..
redis_delete_aof_rdb_nodes.sh
cd redis01/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..
cd redis02/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..
cd redis03/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..
cd redis04/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..
cd redis05/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..
cd redis06/
rm -rf appendonly.aof dump.rdb nodes.conf
cd ..