redis 实现高并发高可用、
redis单机qps在在几万左右,搭建分布式集群主从架构,实现redis 的读写分离,解决高并发问题,高可用;
1、redis主master ,负责写redis
2、redis从slave ,负责读redis ,读的qps高达几十W
主从架构支持水平扩展,什么是水平扩展?
就是,当写的数据过多的时候,可以加master 机器、随时加机器
redis高可用的实现
使用redis + 哨兵 的架构部署、完成redis 高可用的实现;
主从复制原理
1、master node 写,异步的同步数据到 slave node、
2、master node 必须持久化机制,否则master 节点宕机,同步到 slave node 以后 ,所有数据空了;
尽管选举机制 slave node 可以代替master node , 当rdb 恢复时候, 若没有检测到 master fail 时master node 就重启了,数据仍旧是空;
1、slave第一次连接master ,master使用full resynchronization 命令来处理全部复制,
2、slave 第二次连接master ,采取部分复制方式,master 生成的RDB 到slave ,slave 会先到磁盘,再从磁盘中加载到内存;
在复制过程中中断续连
master 复制中断,采用backlog中replica offset 来继续断点复制,若没有找到,就会采取全部复制的方式。
无RDB 的主从复制
在内存中生成RDB文件,继续
删除过期key
slave 不会过期key ,master node 通过LRU 删除过期key 并且模拟发送一条 del 命令给slave,slave 删除过期key ;
哨兵+redis
sentinal 的作用
1、集群的监控
2、消息通知
3、故障转移
4、配置中心
为什么哨兵机制必须要有3个节点才能够维持高可用、
设置配置参数:configuration quorum=1 主节点master node 宕机切换master
哨兵集群 3个节点时候, majority =2 ,哨兵集群2 个node 时候, majority =2 ,宕掉一个redis 的master ,majority=1 无法保证大多数哨兵在运行,所以无法进行故障转移;
redis 集群数据丢失
1、异步主从复制
master node 在没有同步到 slave node 时候宕掉、
导致数据丢失
2、redis 脑裂
由于网络等原因、redis 的 master node 和其他node 出现异常,导致slave node 上升为 master node 、这样就出现了2 个master node;
client 此时继续向原来的 master node 写数据,导致其他node 拿不到数据。
异步主从复制数据丢失损失降低
配置参数 ,至少一个slave 和master 连接延迟不高于 10s,降低异步复制导致的数据丢失的损失降低,丢数据就丢了10s钟的:
min-slaves-to-write 1
min-slaves-max-lag 10
采取client 的降级方案,把数据在本地存储,或者放在队列中。
解决脑裂问题的损失降低
min-slaves-to-write 1
min-slaves-max-lag 10
slave->master 选举机制
当master 宕掉以后,majority 哨兵进行选举机制、进行redis 的贮备切换、
1、slave 的优先级,slave-priority 越小,slave的优先级越高
2、若slave-priority 相同,比较replica offset ,slave 复制的数据越多,优先级越高、
3、若上面两个条件都相同,比较 run id ,run id 越小的slave 优先级越高、
quorum 和majority
哨兵进行主备切换时候,需要得到 quorum 数目的哨兵认为 master 已经宕掉了,选举出一个哨兵并需要 majority 的授权、然后 该哨兵才能够进行主备切换;
哨兵集群的发现机制、
就是利用 pub/sub 模型,每一个 sentinal 每个2s都会向 channel 中添加 run id 、host 、ip 等数据,所以每一个哨兵都能够感知到其他哨兵的存在。
redis的并发竞争问题、解决方案
多个client 同时写了相同的key ,导致并发问题。
使用 zookeeper 获取分布式锁 ,确保同一时间只有一个key 进行读写、写的时候进行 value的时间戳 判断。
redis 本身有分布式锁,一般不用;
mysql 数据写入时候 设置时间戳, 判断 时间戳 的新旧,新的时间戳可以写入,旧的时间戳不写、
19/01/03更新
redis 的key 的7种数据类型,value 的 5种数据类型、
1、string ,list ,hash ,set ,sorted set ,pub/sub ,transactions事务
2、string ,数字,json ,二进制、
redis 事务
redis 事务执行,事务失败仍有一部分数据执行,但是redis 提供了WACTCH 这个命令用来监控key 变化来拒绝命令执行。
MULTI:标记一个事务块的开始;
EXEC:执行所有事务块内的命令;
DISCARD:取消事务,放弃执行事务块内的所有命令;
UNWATCH:取消 WATCH 命令对所有 key 的监视;
WATCH key:监视 key,如果在事务执行之前 key 被其他命令所改动,那么事务将被打断。
redis 的客户端jedis 多线程并发问题
使用jedis 连接池,避免多线程并发问题;
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); //JedisPool是单例的,需要new一个GenericObjectPoolConfig对象
JedisPool jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379); // 建立连接池的连接
Jedis jedis = null; // 类似于new一个jedis对象
try{
jedis = jedisPool.getResource(); // 从连接池获取Jedis对象
jedis.set("hello","world"); // 设置
}catch(Exception e){
e.printStackTrace();
}finally{
if(jedis!=null){
jedis.close();// 注意不是关闭,而是归还到连接池
}
}
2019.01.19 更新
1、redis的持久化,RDB,AOF,区别,各自的特点是什么,适合什么场景
2、redis的企业级的持久化方案是什么,是用来跟哪些企业级的场景结合起来使用的???
3、redis持久化的意义,在于故障恢复
若部署了一个redis 没有持久化的话,redis遇到灾难性故障的时候,就会丢失所有的数据、
若通过持久化将数据搞一份儿在磁盘上去,同步到阿里云 ODPS