缓存
Redis 最常使用的场景是作为缓存,缓存用户信息,会话信息,还有一些热点信息。
淘汰策略
缓存内存是有限制的,当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换(swap)。交换会让 Redis 性能急剧下降。
Redis 提供了maxmemory 来限制内存期望的大小。
当实际内存超过 maxmemory 时,Redis 提供了几种可选策略。
- noeviciction 不会继续服务写请求。读请求可以继续执行。这样会保证数据不会丢失,但是会让线上业务不能继续进行。这个是默认的淘汰策略。
- volatile-lru 尝试淘汰设置了过期时间的 key, 最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰。这样可以保证持久化的数据不会被淘汰
- volatile-ttl 和volatil-lru 一样,也是淘汰设置过期的 key , 但是淘汰策略不是 LRU ,而是 key 的剩余寿命 ttl 的值,ttl 值越小,越优先淘汰。
- volatile-random 和 ttl lru 类似,前提条件是设置了过期时间, 是淘汰过期 key 集合中随机的 key。
- allkeys-lru 区别 volatile-lru 是对全体的key 对象进行淘汰,包含没有设置过期时间的 key.
- allkeys-random 和allkeys-lru 类似,不过淘汰策略是随机的 key
分布式锁
分布式锁的 本质上是在 Redis 中占一个位置,当别的进程来占用时,发现已经被占用,只能放弃或者稍后重试。
redis 占用操作一般使用 setnx (set if not exists)指令占用锁,然后使用 del 指令释放锁,但是可能会有问题。
172.31.1.135:7001> setnx lock:test true
(integer) 1
172.31.1.135:7001> get lock:test
"true"
172.31.1.135:7001>
但是这样存在温柔 setnx 之后,用户线程突然宕机了怎么办,永远无法解锁,这样就存在问题了。
下面给个正确使用实例:
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
欢迎关注: