java监听redis过期_⼩⽩都能看懂的Redis(三)
5、分布式锁
⽇常开发中我们可以⽤ synchronized 、Lock 实现并发编程。但是Java中的锁只能保证在同⼀个JVM进程内中执⾏。如果在分布式集环境下⽤锁呢?⽇常⼀般有两种选择⽅案。
5.1、 Zookeeper实现分布式锁
你需要知道⼀点基本zookeeper知识:
1、持久节点:客户端断开连接zk不删除persistent类型节点
2、临时节点:客户端断开连接zk删除ephemeral类型节点
3、顺序节
点:节点后⾯会⾃动⽣成类似0000001的数字表⽰顺序 4、节点变化的通知:客户端注册了监听节点变化的时候,会调⽤回调⽅法
⼤致流程如下,其中注意每个节点只监控它前⾯那个节点状态,从⽽避免⽺效应。关于模板代码百度即
可。
缺点:
频繁的创建删除节点,加上注册watch事件,对于zookeeper集的压⼒⽐较⼤,性能也⽐不上Redis实现的分布式锁。
5.2、 Redis实现分布式锁
本⾝原理也⽐较简单,Redis ⾃⾝就是⼀个单线程处理器,具备互斥的特性,通过setNX,exist等命令就可以完成简单的分布式锁,处理好超时释放锁的逻辑即可。
SETNX
SETNX 是SET if Not eXists的简写,⽇常指令是SETNX key value,如果 key 不存在则set成功返回 1,如果这个key已经存在了返回0。
SETEX
SETEX key seconds value 表达的意思是 将值 value 关联到 key ,并将 key 的⽣存时间设为多少秒。如果 key 已经存在,setex 命令将覆写旧值。并且 setex是⼀个原⼦性(atomic)操作。
加锁:
⼀般就是⽤⼀个标识唯⼀性的字符串⽐如UUID 配合 SETNX 实现加锁。
解锁:
这⾥⽤到了LUA脚本,LUA可以保证是原⼦性的,思路就是判断⼀下Key和⼊参是否相等,是的话就删除,返回成功1,0就是失败。
缺点:
这个锁是⽆法重⼊的,且⾃⼰实⼼的话各种边边⾓⾓都要考虑到,所以了解个⼤致思路流程即可,⼯程化还是⽤开源⼯具包就⾏。
5.3、 Redisson实现分布式锁
Redisson 是在Redis基础上的⼀个服务,采⽤了基于NIO的Netty框架,不仅能作为Redis底层驱动客户端,还能将原⽣的
RedisHash,List,Set,String,Geo,HyperLogLog等数据结构封装为Java⾥⼤家最熟悉的映射(Map),列表(List),集(Set),通⽤对象桶(Object Bucket),地理空间对象桶(Geospatial Bucket),基数估计算法(HyperLogLog)等结构。
这⾥我们只是⽤到了关于分布式锁的⼏个指令,他的⼤致底层原理:
Redisson加锁解锁 ⼤致流程图如下:
6、Redis 过期策略和内存淘汰策略
6.1、Redis的过期策略
Redis中 过期策略 通常有以下三种:
1、定时过期:
每个设置过期时间的key都需要创建⼀个定时器,到过期时间就会⽴即对key进⾏清除。该策略可以⽴即清除过期的数据,对内存很友好;但是会占⽤⼤量的CPU资源去处理过期的数据,从⽽影响缓存的响应时间和吞吐量。
2、惰性过期:
小白学java有前途吗只有当访问⼀个key时,才会判断该key是否已过期,过期则清除。该策略可以最⼤化地节省CPU资源,却对内存⾮常不友好。极端情况可能出现⼤量的过期key没有再次被访问,从⽽不会被清除,占⽤⼤量内存。
3、定期过期:
每隔⼀定的时间,会扫描⼀定数量的数据库的expires字典中⼀定数量的key,并清除其中已过期的key。该策略是前两者的⼀个折中
⽅案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
expires字典会保存所有设置了过期时间的key的过期时间数据,其中 key 是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表⽰的过期时间。键空间是指该Redis集中保存的所有键。
Redis采⽤的过期策略:惰性删除 + 定期删除。memcached采⽤的过期策略:惰性删除。
6.2、6种内存淘汰策略
Redis的内存淘汰策略是指在Redis的⽤于缓存的内存不⾜时,怎么处理需要新写⼊且需要申请额外空间的数据。
1、volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使⽤的数据淘汰
2、volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
3、volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
4、allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使⽤的数据淘汰
5、allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
6、no-enviction(驱逐):禁⽌驱逐数据,不删除的意思。
⾯试常问常考的也就是LRU了,⼤家熟悉的LinkedHashMap中也实现了LRU算法的,实现如下:
class SelfLRUCache extends LinkedHashMap {    private final int CACHE_SIZE;    /**    * 传递进来最多能缓存多少数据    * @param cacheSize 缓存⼤⼩    */    pu
6.2、总结
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略⽤于处理内存不⾜时的需要申请额外空间的数据,过期策略⽤于
处理过期的缓存数据。
7、Redis 集⾼可⽤
单机问题有机器故障、容量瓶颈、QPS瓶颈。在实际应⽤中,Redis的多机部署时候会涉及到redis主从复制、Sentinel哨兵模式、Redis Cluster。
模式优点缺点单机版架构简单,部署⽅便机器故障、容量瓶颈、QPS瓶颈主从复制⾼可靠性,读写分离故障恢复复杂,主库的写跟存受单机限制Sentinel 哨兵集部署简单,HA原理繁琐,slave存在资源浪费,不能解决读写分离问题Redis Cluster数据动态存储solt,可扩展,⾼可⽤客户端动态感知后端变更,批量操作⽀持查
7.1、redis主从复制
该模式下 具有⾼可⽤性且读写分离, 会采⽤ 增量同步 跟 全量同步 两种机制。
7.1.1、全量同步
Redis全量复制⼀般发⽣在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制⼀份:
1、slave连接master,发送psync命令。
2、master接收到psync命名后,开始执⾏bgsave命令⽣成RDB⽂件并使⽤缓冲区记录此后执⾏的所有写命令。
3、master发送快照⽂件到slave,并在发送期间继续记录被执⾏的写命令。
4、slave收到快照⽂件后丢弃所有旧数据,载⼊收到的
快照。
5、master快照发送完毕后开始向slave发送缓冲区中的写命令。
6、slave完成对快照的载⼊,开始接收命令请求,并执⾏来⾃master缓冲区的写命令。
7.1.2、增量同步
也叫指令同步,就是从库重放在主库中进⾏的指令。Redis会把指令存放在⼀个环形队列当中,因为内存容量有限,如果备机⼀直起不来,不可能把所有的内存都去存指令,也就是说,如果备机⼀直未同步,指令可能会被覆盖掉。
Redis增量复制是指Slave初始化后开始正常⼯作时master发⽣的写操作同步到slave的过程。增量复制的过程主要是master每执⾏⼀个写命令就会向slave发送相同的写命令。
7.1.3、Redis主从同步策略:
1、主从刚刚连接的时候,进⾏全量同步;全同步结束后,进⾏增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同
步。redis 策略是,⽆论如何,⾸先会尝试进⾏增量同步,如不成功,要求从机进⾏全量同步。2、slave在同步master数据时候如果slave丢失连接不⽤怕,slave在重新连接之后丢失重补。
3、⼀般通过主从来实现读写分离,但是如果master挂掉后如何保证Redis的 HA呢?引⼊Sentinel进⾏master的选择。
7.2、⾼可⽤之哨兵模式
Redis-sentinel 本⾝是⼀个独⽴运⾏的进程,⼀般sentinel集 节点数⾄少三个且奇数个,它能监控多个master-slave集,sentinel节点发现master宕机后能进⾏⾃动切换。Sentinel可以监视任意多个主服务
器以及主服务器属下的从服务器,并在被监视的主服务器下线时,⾃动执⾏故障转移操作。这⾥需注意sentinel也有single-point-of-failure问题。⼤致罗列下哨兵⽤途:
集监控:循环监控master跟slave节点。
消息通知:当它发现有redis实例有故障的话,就会发送消息给管理员
故障转移:这⾥分为主观下线(单独⼀个哨兵发现master故障了)。客观下线(多个哨兵进⾏抉择发现达到quorum数时候开始进⾏切换)。
配置中⼼:如果发⽣了故障转移,它会通知将master的新地址写在配置中⼼告诉客户端。
7.3、Redis Cluster
RedisCluster是Redis的分布式解决⽅案,在3.0版本后推出的⽅案,有效地解决了Redis分布式的需求。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。