本文已参与「新人创作礼」活动,一起开启掘金创作之路。
为什么使用setnx
为什么使用setnx
1,原子操作(若没有setnx则需要使用事务,通信延时) set
2,使用分布式锁,要用set(key,value,EX,timeout,NX) (过期时间、value为"UUID+TreadID"、lua脚本原子删除)
使用分布式锁的要点:
- 使用 set 命令设置锁标记,必须有超时时间,(使得持有锁的应用崩溃也可以释放锁,不会造成死锁);
- 每个获取锁的客户端设置的 value 必须是独一无二的(防止锁被其他线程误删);
- 使用LUA脚本保证原子性来删除锁
- 对于不需要超时时间的情况,可以设置不断刷新锁超时时间的线程;
- 为了保证集群的锁不会出现超时的情况,必须合理设置网络等待时间和锁超时时间。
- 分布式集群中,直接每台机器设置一样的超时时间和锁标记(防止数据同步延迟丢失锁,);
这个分布式锁满足如下四个条件:
- 任意时刻只能有一个客户端持有锁;
- 不能发生死锁,有一个客户端持有锁期间出现了问题没有解锁,也能保证后面别的客户端继续去持有锁;
- 加锁和解锁必须是同一个客户端,客户端自己加的锁只能自己去解;
- 只要大多数 Redis 节点正常,客户端就能正常使用锁。
总结:分布式锁的使用,使用set命令将redis未命中的数据作为key存入缓存作为锁,只有锁设置成功时才能访问数据库。(注意设置key的过期时间,value设置为唯一标志防止锁被误删,“UUID+ThreadID”,使用LUA脚本原子性删除锁)【set key value ex 100 nx】 value: 通常存储加锁方的唯一标记,如 “UUID+ThreadID”
【set key value ex 100 nx】 (注意设置key的过期时间,value设置为唯一标志防止锁被误删,使用LUA脚本原子性删除锁)
Redis怎么扩容?
Redis持久化数据和缓存怎么做扩容?
如果Redis被当做缓存使用,使用一致性哈希实现动态扩缩容。
如果Redis被当做持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量不能变化。否则的话,必须使用Redis集群在运行时进行数据再平衡。
一致性哈希:分布式系统中对象与节点的映射关系,传统方案是使用对象的哈希值对节点个数取模,再映射到相应编号的节点,这种方案在节点个数变动时,绝大多数对象的映射关系会失效而需要迁移;而一致性哈希算法中,当节点个数变动时,映射关系失效的对象非常少,迁移成本也非常小。