1铛楣、安裝redis
安裝的前提條件:
需要安裝gcc:yum install gcc-c++
1弱左、下載redis的源碼包。
2棘钞、把源碼包上傳到linux服務(wù)器
3缠借、解壓源碼包:tar -zxvf redis-3.0.0.tar.gz
4、Make
5宜猜、Make install:[root@bogon redis-3.0.0]# make install PREFIX=/usr/local/redis
2烈炭、啟動(dòng)redis
1、前端啟動(dòng)模式
/usr/local/redis/bin/redis-server
默認(rèn)是前端啟動(dòng)模式宝恶,端口是6379
2符隙、后端啟動(dòng)
1)從redis的源碼目錄中復(fù)制redis.conf到redis的安裝目錄。
2)修改配置文件
3)[root@bogon bin]# ./redis-server redis.conf
3垫毙、Redis常用命令
127.0.0.1:6379> set a 10
OK
127.0.0.1:6379> get a
"10"
4霹疫、集群結(jié)構(gòu)
集群中有三個(gè)節(jié)點(diǎn)的集群,每個(gè)節(jié)點(diǎn)有一主一備综芥。需要6臺(tái)虛擬機(jī)丽蝎。
搭建一個(gè)偽分布式的集群,使用6個(gè)redis實(shí)例來模擬。
1屠阻、搭建集群需要的環(huán)境
搭建集群需要使用到官方提供的ruby腳本红省。需要安裝ruby的環(huán)境。
安裝ruby
yum install ruby
yum install rubygems
redis集群管理工具redis-trib.rb
[root@bogon ~]# cd redis-3.0.0
[root@bogon redis-3.0.0]# cd src
[root@bogon src]# ll *.rb
-rwxrwxr-x. 1 root root 48141 Apr 1 07:01 redis-trib.rb
腳本需要的ruby包:
需要上傳到linux服務(wù)国觉。
安裝ruby的包:
[root@bogon ~]# gem install redis-3.0.0.gem
2吧恃、集群的搭建
第一步:創(chuàng)建6個(gè)redis實(shí)例,端口號(hào)從7001~7006
第二步:修改redis的配置文件
1麻诀、修改端口號(hào)
2痕寓、打開cluster-enable前面的注釋。
第三步:把創(chuàng)建集群的ruby腳本redis-trib.rb復(fù)制到redis-cluster目錄下蝇闭。
第四步:?jiǎn)?dòng)6個(gè)redis實(shí)例
第五步:創(chuàng)建集群呻率。
[root@bogon 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
3、集群測(cè)試
[root@bogon redis-cluster]# redis01/redis-cli -h 192.168.25.153 -p 7002 -c
192.168.25.153:7002> set a 100
-> Redirected to slot [15495] located at 192.168.25.153:7003
OK
5呻引、Jedis客戶端
需要把jedis的jar包添加到工程中礼仗,如果是maven需要添加jar包的坐標(biāo)。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>
1逻悠、單機(jī)版
/**
* redis單機(jī)版測(cè)試
*/
@Test
public void testJedisSingle(){
Jedis jedis = new Jedis("10.10.1.146",6379);
jedis.set("name","abc");
String name = jedis.get("name");
System.out.println(name);
jedis.close();
}
/**
* redis連接池測(cè)試
*/
@Test
public void testJedisPool(){
JedisPool pool = new JedisPool("10.10.1.146",6379);
Jedis jedis = pool.getResource();
jedis.set("age","100");
String age = jedis.get("age");
System.out.println(age);
jedis.close();
pool.close();
}
2元践、集群版
/**
* redis集群測(cè)試(自帶連接池)
*/
@Test
public void testJedisCluster(){
//添加節(jié)點(diǎn)
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("10.10.1.146",7001));
nodes.add(new HostAndPort("10.10.1.146",7002));
nodes.add(new HostAndPort("10.10.1.146",7003));
nodes.add(new HostAndPort("10.10.1.146",7004));
nodes.add(new HostAndPort("10.10.1.146",7005));
nodes.add(new HostAndPort("10.10.1.146",7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("key1","redis cluster");
String str = jedisCluster.get("key1");
System.out.println(str);
jedisCluster.close();
}
3、jedis整合spring(單機(jī)版)
<!--redis連接池配置-->
<bean name="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大連接數(shù) -->
<property name="maxTotal" value="30" />
<!-- 最大空閑連接數(shù) -->
<property name="maxIdle" value="10" />
<!-- 每次釋放連接的最大數(shù)目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 釋放連接的掃描間隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 連接最小空閑時(shí)間 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 連接空閑多久后釋放, 當(dāng)空閑時(shí)間>該值 且 空閑連接>最大空閑連接數(shù) 時(shí)直接釋放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 獲取連接時(shí)的最大等待毫秒數(shù),小于零:阻塞不確定的時(shí)間,默認(rèn)-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在獲取連接的時(shí)候檢查有效性, 默認(rèn)false -->
<property name="testOnBorrow" value="true" />
<!-- 在空閑時(shí)檢查有效性, 默認(rèn)false -->
<property name="testWhileIdle" value="true" />
<!-- 連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!--redis單機(jī)版配置-->
<bean id="redisClient" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
<constructor-arg name="poolConfig" ref="redisPoolConfig"></constructor-arg>
</bean>
/**
* redis整合spring單機(jī)版測(cè)試
*/
@Test
public void testSpringJedisSingle(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
JedisPool pool = (JedisPool) applicationContext.getBean("redisClient");
Jedis jedis = pool.getResource();
String name = jedis.get("name");
System.out.println(name);
jedis.close();
pool.close();
}
4蹂风、jedis整合spring(集群版)
<!--redis連接池配置-->
<bean name="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大連接數(shù) -->
<property name="maxTotal" value="30" />
<!-- 最大空閑連接數(shù) -->
<property name="maxIdle" value="10" />
<!-- 每次釋放連接的最大數(shù)目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 釋放連接的掃描間隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 連接最小空閑時(shí)間 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 連接空閑多久后釋放, 當(dāng)空閑時(shí)間>該值 且 空閑連接>最大空閑連接數(shù) 時(shí)直接釋放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 獲取連接時(shí)的最大等待毫秒數(shù),小于零:阻塞不確定的時(shí)間,默認(rèn)-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在獲取連接的時(shí)候檢查有效性, 默認(rèn)false -->
<property name="testOnBorrow" value="true" />
<!-- 在空閑時(shí)檢查有效性, 默認(rèn)false -->
<property name="testWhileIdle" value="true" />
<!-- 連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!--redis集群版配置-->
<bean name="redisClient" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="10.10.1.146"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg name="poolConfig" ref="redisPoolConfig"></constructor-arg>
</bean>
/**
* redis整合spring集群版測(cè)試
*/
@Test
public void testSpringJedisCluster(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
JedisCluster jedisCluster = (JedisCluster) applicationContext.getBean("redisClient");
String str = jedisCluster.get("key1");
System.out.println(str);
jedisCluster.close();
}
6卢厂、把緩存添加到業(yè)務(wù)邏輯(把業(yè)務(wù)邏輯查詢到的數(shù)據(jù)放入redis數(shù)據(jù)庫)
注意:緩存的添加不能影響正常的業(yè)務(wù)邏輯乾蓬。
public List<TbContent> getContentList(long contentCid) {
//從緩存中取內(nèi)容
try {
String result = jedisClient.hget(INDEX_CONTENT_REDIS_KEY, contentCid + "");
if (!StringUtils.isBlank(result)) {
//把字符串轉(zhuǎn)換成list
List<TbContent> resultList = JsonUtils.jsonToList(result, TbContent.class);
return resultList;
}
} catch (Exception e) {
e.printStackTrace();
}
//業(yè)務(wù)邏輯:根據(jù)內(nèi)容分類id在mysql數(shù)據(jù)庫中查詢內(nèi)容列表
TbContentExample example = new TbContentExample();
Criteria criteria = example.createCriteria();
criteria.andCategoryIdEqualTo(contentCid);
List<TbContent> list = contentMapper.selectByExample(example);
//向緩存中添加內(nèi)容
try {
//把list轉(zhuǎn)換成字符串
String cacheString = JsonUtils.objectToJson(list);
jedisClient.hset(INDEX_CONTENT_REDIS_KEY, contentCid + "", cacheString);
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
7惠啄、緩存同步
解決方案:在taotao-rest工程中發(fā)布一個(gè)服務(wù)。當(dāng)后臺(tái)管理系統(tǒng)修改內(nèi)容后任内,調(diào)用此服務(wù)撵渡,同步緩存。
當(dāng)后臺(tái)管理系統(tǒng)死嗦,修改內(nèi)容之后需要通知redis把修改的內(nèi)容對(duì)應(yīng)的分類id的key刪除趋距。
Service層:
public class RedisServiceImpl implements RedisService {
@Autowired
private JedisClient jedisClient;
@Value("${INDEX_CONTENT_REDIS_KEY}")
private String INDEX_CONTENT_REDIS_KEY;
public TaotaoResult syncContent(long contentCid) {
try {
jedisClient.hdel(INDEX_CONTENT_REDIS_KEY, contentCid + "");
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok();
}
}
Controller層:
@Controller
@RequestMapping("/cache/sync")
public class RedisController {
@Autowired
private RedisService redisService;
@RequestMapping("/content/{contentCid}")
public TaotaoResult contentCacheSync(@PathVariable Long contentCid) {
TaotaoResult result = redisService.syncContent(contentCid);
return result;
}
}
同步緩存服務(wù)的調(diào)用(使用HttpClient調(diào)用http://localhost:8080//cache/sync/content/{contentCid}):