目录
一、主从模式
优点:解决单台机器的内存问题,主机写,从机读,如果master挂了,还需要手动切到slave上面去。
缺点:主从模式没有故障检测
1.当主机挂掉以后还有从机继续提供服务。
2.比较好的方式是配置DNS(domain name system,域名系统),访问是访问的域名,某主机挂掉了,我们也能将其连接到从机。需要Nginx介入!
redis主从同步:
1. 全量同步
master开启一个线程生成rdb文件,并缓存这段时间的写操作,将rdb发往slave,slave先读取rdb,再读缓存,一致性
2. 增量同步
- redis2.8版本新增此功能,原来统统是全量更新
- master 服务器内存中给每个 slave 服务器维护了一份同步日志保存同步标识(偏移量标识)
- 每个slave在与master进行同步时携带自己的同步标识
- 主从断了,slave每1秒尝试与master连接,并检查同步标识,如果标识还在master同步备份日志中,就从标识开始继续增量更新,如果不在了,全量更新一次。
3. 主从同步策略:
增量优先,不行再全量
二、哨兵模式
优点:基于主从模式的,提供了对master的监控和故障转移,当master节点出现故障后,可以自动通过选举选出一台slave做master,待master故障恢复后,再切回来,这就大大提高了可用性了,且哨兵之间也可以做集群部署,相互监测。
缺点:①在主机down后,再选取一个新的,存在访问瞬断②虽然是主从模式,单机访问量有限10w③RDB和AOF的数据量大,恢复慢
前面的需要人工介入,这个自动切换,注意用户一定连的是哨兵集群。
这种模式的问题:
- 无法满足高可用:所有的写操作都指向主机,虽然哨兵集群能够自动切换,但是要一定的时间判断是否主机下线,再选举,在这一段时间内“写”是不可以的——访问瞬断!
- 无法满足大并发:RDB,aof,数据恢复比较慢。
- 无法满足大内存:单机最大访问10W
三、高可用redis集群模式
一个主down了,从还能转到其他的master上,并且存放时是通过hash分散到不同的主从模式上,共同组成redis主从集群
redis有16384个虚拟节点,均匀分布在三个主机。
比如来一段语句set name guojia;
计算哈希值,再对16384取模,能够找到对应的主机,这样数据均匀分散到各个节点,数据分流。
四、搭建redis集群
总步骤:
1.进行如下设定
为了方便,设定连接任意IP地址
vim移动光标:
2.开启服务
开启所有redis
查看一下
接下来搭建redis集群,请redis版本在5.0以上,
-a 111111是密码,后面一次是IP:端口,最后的号码1是1个从机,即1主1从,下面的M代表master,S代表slave。
slots是hash值,均匀分布的。
至此,整体的集群搭建完毕。
3. 接入集群:
①普通模式:
下面连接
注意,这是在本机做的,如果远程需要写 redis-cli -a111111 -h"添加IP地址" -p8001
可以看到,当set a a时出现了error,也就是经过了hash计算后,这个应该在8003的位置,换到8003端口,设定aa,出现OK。
②智能客户端
通过keyslot命令能够得到具体的slot号码即hash之后的值。
3)主节点4)从节点
五、利用Jedis测试集群
为什么建立连接池?为了避免频繁的TCP三次握手。
前提是上述的搭建集群完成后,下面代码能够运行!
public class jedisCluster1 {
public static void main(String[] args) {
Set<HostAndPort> clusters = new HashSet<>();
clusters.add(new HostAndPort("localhost",8001));
clusters.add(new HostAndPort("localhost",8002));
clusters.add(new HostAndPort("localhost",8003));
clusters.add(new HostAndPort("localhost",8004));
clusters.add(new HostAndPort("localhost",8005));
clusters.add(new HostAndPort("localhost",8006));
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(100);
jedisPoolConfig.setMaxIdle(10);
jedisPoolConfig.setTestOnBorrow(true);
JedisCluster jedisCluster = new JedisCluster(clusters,jedisPoolConfig);
jedisCluster.set("name","guojai");
System.out.println(jedisCluster.get("name"));
jedisCluster.close();
}
}