redis笔记整理04

1、启动redis
src/redis-server &
2、关闭redis
src/redis-cli shutdown
3、连接
telnet localhost 6379
诊断命令
1、查看基本信息
INFO
2、查看缓存键
keys ‘*’
3、查看key的类型
type yourkey
操作命令

1、插入命令
set key yy
2、获取命令
get key
2、清空所有数据
FLUSHALL
配置命令
1、添加日志
vim redis.conf logfile /data/redis_cache/logs/redis.log #日志路径

Redis分布式锁的实现原理看这篇就够了~

https://blog.csdn.net/gupao123456/article/details/84327254

https://blog.csdn.net/gupao123456/article/details/84327254
单个Redis实例下的锁正确使用姿势

https://blog.csdn.net/She_lock/article/details/88894096

Java面试----2018最全Redis面试题整理

https://blog.csdn.net/wchengsheng/article/details/79925654

Redisson分布式锁
https://www.cnblogs.com/ASPNET2008/p/6385249.html

利用Redisson实现分布式锁及其底层原理解析(感觉还可以)
https://blog.csdn.net/turbo_zone/article/details/83422215

通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。

锁的原理
在Redisson中,使用key来作为是否上锁的标志,当通过getLock(String key)方法获得相应的锁之后,这个key即作为一个锁存储到Redis集群中,在接下来如果有其他的线程尝试获取名为key的锁时,便会向集群中进行查询,如果能够查到这个锁并发现相应的value的值不为0,则表示已经有其他线程申请了这个锁同时还没有释放,则当前线程进入阻塞,否则由当前线程获取这个锁并将value值加一,如果是可重入锁的话,则当前线程每获得一个自身线程的锁,就将value的值加一,而每释放一个锁则将value值减一,直到减至0,完全释放这个锁。因为底层是基于分布式的Redis集群,所以Redisson实现了分布式的锁机制。

加锁

在Redisson中,加锁需要以下三个参数:

KEYS[1] :需要加锁的key,这里需要是字符串类型。

ARGV[1] :锁的超时时间,防止死锁

ARGV[2] :锁的唯一标识,id(UUID.randomUUID()) + “:” + threadId

Future tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId) {
internalLockLeaseTime = unit.toMillis(leaseTime);
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_LONG,
// 检查是否key已经被占用,如果没有则设置超时时间和唯一标识,初始化value=1
"if (redis.call(‘exists’, KEYS[1]) == 0) then " +
"redis.call(‘hset’, KEYS[1], ARGV[2], 1); " +
"redis.call(‘pexpire’, KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
// 如果锁重入,需要判断锁的key field 都一直情况下 value 加一
"if (redis.call(‘hexists’, KEYS[1], ARGV[2]) == 1) then " +
"redis.call(‘hincrby’, KEYS[1], ARGV[2], 1); " +
//锁重入重新设置超时时间
"redis.call(‘pexpire’, KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
// 返回剩余的过期时间
“return redis.call(‘pttl’, KEYS[1]);”,
Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));
}

解锁

在Redisson中解锁需要以下五个参数:

KEYS[1] :需要加锁的key,这里需要是字符串类型。

KEYS[2] :redis消息的ChannelName,一个分布式锁对应唯一的一个channelName:“redisson_lock__channel__{” + getName() + “}”

ARGV[1] :reids消息体,这里只需要一个字节的标记就可以,主要标记redis的key已经解锁,再结合redis的Subscribe,能唤醒其他订阅解锁消息的客户端线程申请锁。

ARGV[2] :锁的超时时间,防止死锁

ARGV[3] :锁的唯一标识,也就是刚才介绍的 id(UUID.randomUUID()) + “:” + threadId

public void unlock() {
Boolean opStatus = commandExecutor.evalWrite(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
// 如果key已经不存在,说明已经被解锁,直接发布(publihs)redis消息
"if (redis.call(‘exists’, KEYS[1]) == 0) then " +
"redis.call(‘publish’, KEYS[2], ARGV[1]); " +
"return 1; " +
“end;” +
// key和field不匹配,说明当前客户端线程没有持有锁,不能主动解锁。
"if (redis.call(‘hexists’, KEYS[1], ARGV[3]) == 0) then " +
“return nil;” +
"end; " +
"local counter = redis.call(‘hincrby’, KEYS[1], ARGV[3], -1); " +
// 如果counter>0说明锁在重入,不能删除key
"if (counter > 0) then " +
"redis.call(‘pexpire’, KEYS[1], ARGV[2]); " +
"return 0; " +
"else " +
// 删除key并且publish 解锁消息
"redis.call(‘del’, KEYS[1]); " +
"redis.call(‘publish’, KEYS[2], ARGV[1]); " +
"return 1; "+
"end; " +
“return nil;”,
Arrays.asList(getName(), getChannelName()), LockPubSub.unlockMessage, internalLockLeaseTime, getLockName(Thread.currentThread().getId()));
if (opStatus == null) {
throw new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: "
+ id + " thread-id: " + Thread.currentThread().getId());
}
// 解锁成功之后取消更新锁expire的时间任务
if (opStatus) {
cancelExpirationRenewal();
}
}
注意点

Redisson 默认的 CommandExecutor 实现是通过 eval 命令来执行 Lua 脚本,所以要求 Redis 的版本必须为 2.6 或以上,否则可能要自己来实现

Redis分布式锁的正确实现方式
https://www.cnblogs.com/linjiqin/p/8003838.html

springCloud+Redis实现session共享技术
https://blog.csdn.net/lanshen110119/article/details/83104926

猜你喜欢

转载自blog.csdn.net/hbn1326317071/article/details/100631524