redis缓存机制
一、先安装redis
安装的前提条件:需要安装gcc:
yum install gcc-c++
1、下载redis的源码包。
2、把源码包上传到linux服务器
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
二、启动redis
1、前端启动模式/usr/local/redis/bin/redis-server 默认是前端启动模式,端口是6379
2、后端启动
1)从redis的源码目录中复制redis.conf到redis的安装目录。
2)修改配置文件 vim redis.conf -> 修改 daemonize=yes
3)启动redis
[root@bogon bin]# ./redis-server redis.conf
三、搭建集群redis
1、搭建集群需要使用到官方提供的ruby脚本。
需要安装ruby的环境。
安装ruby
yum install ruby
yum install rubygems
redis集群管理工具redis-trib.rb (在redis目录下的src目录下)
脚本需要的ruby包 redis-xxx.gem
需要上传到linux服务
安装ruby的包
gem install redis-xxx.gem
2、集群搭建
第一步:创建6个redis实例,端口号从7001~7006
第二步:修改redis的配置文件
1、修改端口号
2、打开cluster-enable前面的注释。
第三步:把创建集群的ruby脚本复制到redis-cluster目录下。
第四步:启动6个redis实例
第五步:创建集群。
命令:
./redis-trib.rb create --replicas 1 linuxIP:7001 linuxIP:7002 linuxIP:7003 linuxIP:7004 192.168.25.153:7005 linuxIP:7006
连接集群cli
命令:
./redis-cli -h linuxIP -p redis端口 -c
关闭redis
命令:
./redis-cli -p redis端口 hutdown
四、java连接redis
单机版
普通版,类似jdbc
//创建一个jedis的对象。
Jedis jedis = new Jedis("192.168.0.181", 6379);
//调用jedis对象的方法,方法名称和redis的命令一致。
jedis.set("key1", "jedis test");
String string = jedis.get("key1");
System.out.println(string);
//关闭jedis。
jedis.close();
连接池版,类似C3P0
//创建jedis连接池
JedisPool pool = new JedisPool("192.168.0.181", 6379);
//从连接池中获得Jedis对象
Jedis jedis = pool.getResource();
String string = jedis.get("key1");
System.out.println(string);
//关闭jedis对象
jedis.close();
pool.close();
集群版
HashSet<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.0.181", 7001));
nodes.add(new HostAndPort("192.168.0.181", 7002));
nodes.add(new HostAndPort("192.168.0.181", 7003));
nodes.add(new HostAndPort("192.168.0.181", 7004));
nodes.add(new HostAndPort("192.168.0.181", 7005));
nodes.add(new HostAndPort("192.168.0.181", 7006));
//添加了redis集群节点的JedisCluster 可以直接往里存 key value,在spring容器中的JedisCluster的bean是配置好集群redis的,可以从容器中取出直接执行set、get、hset、hget、incr、expire、ttl、del等方法
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("key1", "1000");
String string = cluster.get("key1");
System.out.println(string);
cluster.close();
开发中多以单机版开发,上线时才换成集群版
五、服务层添加缓存
在查数据库前 先查询redis,若查询到则不运行下面的查数据库;若redis没有缓存,则查询数据库并把内容存到redis
// 从缓存中取内容
try {
String result = jedisClient.hget(INDEX_CONTENT_REDIS_KEY,
contentCid + "");
if (!StringUtils.isBlank(result)) {
// 把字符串转换成list
List<TbContent> resultList = JsonUtils.jsonToList(result,
TbContent.class);
return resultList;
}
} catch (Exception e) {
e.printStackTrace();
}
查询数据库
xxxxxx
// 查完数据库后向缓存中添加内容
try {
// 把list转换成字符串,redis只能存字符串
String cacheString = JsonUtils.objectToJson(list);
jedisClient.hset(INDEX_CONTENT_REDIS_KEY, contentCid + "",
cacheString);
} catch (Exception e) {
e.printStackTrace();
}
return list;
六、后台同步缓存
服务层创建更新服务
/**
* 删除redis中的缓存
*
* @author Administrator
*
*/
@Service
public class RedisServiceImpl implements RedisService {
@Autowired
private JedisClient jedisClient; //spring已经配置了这个bean
@Value("${INDEX_CONTENT_REDIS_KEY}")
private String INDEX_CONTENT_REDIS_KEY; //常量标记
@Override
public TaotaoResult syncContent(long contentCid) {
try {
jedisClient.hdel(INDEX_CONTENT_REDIS_KEY, contentCid + "");//第一个参数是常量标记,第二个参数是key
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok();
}
}
后台更新内容时调用服务层更新服务
使用HttpClient来调用服务层服务(封装httpClient为一个工具类)
public class HttpClientUtil {
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(),
"UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(
paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json,
ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return resultString;
}
}
在每次更新内容时,执行缓存同步
// 添加缓存同步机制
public void updateCache(long id) {
try {
HttpClientUtil.doGet(REST_BASE_URL + REST_CONTENT_SYNC_URL + id); //服务层缓存同步url
} catch (Exception e) {
e.printStackTrace();
}
}