# 112. 基于 hystrix 完成对 redis 访问的资源隔离以避免缓存服务被拖垮
从本章开始,用几讲的时间,给咱们的 redis 访问这一块,加上保护措施,给商品服务的访问加上限流的保护措施(这里其实已经重复了,但是角度不一样,也就是场景不一样)
这里会使用之前的项目,就是有 storm 缓存预热的项目,那一套里面完成了之前的课程的知识点
redis 这一块,全都用 hystrix 的 command 进行封装,做资源隔离,确保 redis 的访问只能在固定的线程池内的资源来进行访问,哪怕是 redis 访问的很慢,有等待和超时也不要紧,只有少量额线程资源用来访问,缓存服务不会被拖垮
eshop-cache 项目中,对 redis 的操作有以下几个方法
// cn.mrcode.cachepdp.eshop.cache.service.impl.CacheServiceImpl#
saveProductInfo2RedisCache
getProductInfoOfRedisCache
saveShopInfo2RedisCache
getShopInfoOfRedisCache
1
2
3
4
5
2
3
4
5
把这几个方法修改成 hystrix 调用方式
添加依赖:compile 'com.netflix.hystrix:hystrix-core: 1.5.12'
上面四个方法,这里只贴出来其中一对,因为逻辑真的非常简单。
SaveProductInfo2RedisCommand.java
package cn.mrcode.cachepdp.eshop.cache.command;
import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import cn.mrcode.cachepdp.eshop.cache.model.ProductInfo;
import redis.clients.jedis.JedisCluster;
/**
* @author : zhuqiang
* @date : 2019/6/23 15:07
*/
public class SaveProductInfo2RedisCommand extends HystrixCommand<Boolean> {
private JedisCluster jedisCluster;
private final ProductInfo productInfo;
public SaveProductInfo2RedisCommand(ProductInfo productInfo) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SaveProductInfo2RedisCommand")));
this.productInfo = productInfo;
}
@Override
protected Boolean run() throws Exception {
String key = "product_info_" + productInfo.getId();
jedisCluster.set(key, JSONObject.toJSONString(productInfo));
return true;
}
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
调用处
/**
* 将商品信息保存到redis中
*/
public void saveProductInfo2RedisCache(ProductInfo productInfo) {
// String key = "product_info_" + productInfo.getId();
// jedisCluster.set(key, JSONObject.toJSONString(productInfo));
SaveProductInfo2RedisCommand command = new SaveProductInfo2RedisCommand(productInfo);
command.setJedisCluster(jedisCluster);
command.execute();
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
GetProductInfoOfRedisCommand.java
package cn.mrcode.cachepdp.eshop.cache.command;
import com.alibaba.fastjson.JSON;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import cn.mrcode.cachepdp.eshop.cache.model.ProductInfo;
import redis.clients.jedis.JedisCluster;
/**
* @author : zhuqiang
* @date : 2019/6/23 15:17
*/
public class GetProductInfoOfRedisCommand extends HystrixCommand<ProductInfo> {
private JedisCluster jedisCluster;
private Long productId;
public GetProductInfoOfRedisCommand(Long productId) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetProductInfoOfRedisCommand")));
this.productId = productId;
}
@Override
protected ProductInfo run() throws Exception {
String key = "product_info_" + productId;
String json = jedisCluster.get(key);
return JSON.parseObject(json, ProductInfo.class);
}
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
调用处
@Override
public ProductInfo getProductInfoOfRedisCache(Long productId) {
// String key = "product_info_" + productId;
// String json = jedisCluster.get(key);
// return JSON.parseObject(json, ProductInfo.class);
GetProductInfoOfRedisCommand command = new GetProductInfoOfRedisCommand(productId);
command.setJedisCluster(jedisCluster);
return command.execute();
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
启动项目后访问:http://localhost:6002/getProductInfo?productId=1
测试该方法的调用成功
可以看到只是把原有的逻辑放到 command 中去了,这里可以尝试使用 command 的注解,就不用这么麻烦的抽到类中了