redis集群
一、 概述
redis将数据存储于内存中,内存的空间是有限的。为了满足更大的数据存储需求,可以搭建redis集群,redis-cluster。集群上每个节点保存的数据是不一样的,为了保证集群的高可用,每个节点添加备份机,做keepalived心跳测试。 所有的redis节点彼此互联;redis集群没有集群管理工具(比如nginx),节点的fail(宕机)通过投票容错机制(超过半数投票选举,就确认宕机,投票机制需要至少3个节点);客户端与redis节点直连,不需要中间proxy层,客户端连接集群中任意一个节点即可;为了均匀存储数据,redis集群把所有的物理节点映射到(0-16383)slop(槽)上,集群维护节点<>槽<>值。集群中最多可以有16384个节点。
二、 搭建redis集群
redis集群至少有3个节点,高可用的集群,要求每个节点至少需要一个备份机,redis集群至少需要6台服务器。如果为了练习,可以搭建伪分布式,使用一台虚拟机,修改redis的端口为7110-7116。
在urs/local下创建redis-cluster目录,将redis/bin下的文件复制到redis-cluster/redis01下,cp -r redis/bin redis-cluster/redis01,将redis01下的dump.rdb文件删除,如果有appendonly.aof文件也删除之。修改redis01下的redis.conf文件,
port 7111
cluster-enabled yes
在redis-cluster目录下,复制redis01为另外5份,并修改每一份的端口。
编写一个shell批处理文件。
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解压文件下的src目录下的redis-trib.rb文件复制到redis-cluster目录下。这个是一个ruby脚本。
使用ruby脚本搭建集群环境,需要ruby的运行环境。安装ruby,
yum install ruby
yum install rubygems
将redis-3.0.0.gem库文件上传到服务器。并安装之,gem install redis-3.0.0。
在redis-cluster目录下,也就是redis-trib.rb文件所在目录,执行
./redis-trib.rb create --replicas 1 192.168.0.121:7001 192.168.0.121:7002 192.168.0.121:7003 192.168.0.121:7004 192.168.0.121:7005 192.168.0.121:7006
yes,分配好集群的slop。
使用集群中任意一台正常运行的redis的客户端,测试。连接时,注意加上ip和port和-c(表示接入的是集群)。./redis-cli -h xxx.xxx.xxx.xxx -p 7005 -c
三、 JedisClient连接集群和项目中使用redis的例子
使用jedis的api连接集群,导入jedis的相关jar包。
@Test
publicvoid jedisClusterTest() throws Exception {
Set<HostAndPort> nodes = newHashSet<>();
nodes.add(new HostAndPort("192.168.0.121", 7001));
nodes.add(new HostAndPort("192.168.0.121", 7002));
nodes.add(new HostAndPort("192.168.0.121", 7003));
nodes.add(new HostAndPort("192.168.0.121", 7004));
nodes.add(new HostAndPort("192.168.0.121", 7005));
nodes.add(new HostAndPort("192.168.0.121", 7006));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("test1", "第一个jedis存储");
System.out.println(cluster.get("set2"));
System.out.println(cluster.get("test1"));
cluster.close();
}
redis缓存在实际开发中的应用。
public List<TbContent> getContentListByCid(long cid) {
// 查看缓存
// 如果缓存中有直接从缓存中取
try {
String string= jedisClient.hget(CONTENT_LIST, Long.toString(cid));
if(StringUtils.isNotBlank(string)) {
List<TbContent>list = JsonUtils.jsonToList(string, TbContent.class);
returnlist;
}
} catch(Exception e) {
e.printStackTrace();
}
// 如果没有查数据库
TbContentExampleexample = new TbContentExample();
Criteria criteria= example.createCriteria();
criteria.andCategoryIdEqualTo(cid);
List<TbContent>list = contentMapper.selectByExampleWithBLOBs(example);
// 将数据库结果保存到缓存
try {
jedisClient.hset(CONTENT_LIST,Long.toString(cid), JsonUtils.objectToJson(list));
} catch(Exception e) {
e.printStackTrace();
}
return list;
}
对于动态获取的内容,涉及到对该内容的增删改的操作,需要进行缓存同步。简单的做法是,在做增删改之后,删除对应的缓存。复杂的做法是,在增删改时,删除掉缓存后,做一次查询操作,将结果缓存。区别是对于增删改后重新载入缓存,不会导致客户访问时再次调用数据库,更快。可以将删除和重载缓存编写一个缓存updateCache的方法,每次做增删改后都updateCache。
/**
* 更新缓存
*/
void updateCate(String key,String field) {
jedisClient.hdel(key,field);
getContentListByCid(Long.parseLong(field));
}