redis中Set集合SortSet有序集合的复制

redis中Set集合SortSet有序集合的复制

redis集合类型中是没有复制命令的,我所说的复制,是通过redis
的其他指令来实现

需求:将key1的内容全部拷贝到key2中
下面我们来看看在redis中怎么处理

Set集合的复制

首先,我们创建一个集合key1,这时key2还没有创建

127.0.0.1:6380[1]> SADD key1 "a"
(integer) 1
127.0.0.1:6380[1]> SADD key1 "b"
(integer) 1
127.0.0.1:6380[1]> SADD key1 "c"
(integer) 1
127.0.0.1:6380[1]> smembers key1
1) "b"
2) "a"
3) "c"

然后将key1拷贝到key2中

127.0.0.1:6380[1]> SUNIONSTORE key2 key1 temp
(integer) 3
127.0.0.1:6380[1]> smembers key1
1) "b"
2) "a"
3) "c"
127.0.0.1:6380[1]> smembers key2
1) "a"
2) "b"
3) "c"
127.0.0.1:6380[1]> smembers temp
(empty list or set)
  • 上面例子中的temp是一个不存在的key

如果key2是已经存在的key,也可以进行复制,不过这个时候,就是将key1中所有内容都移动key2中。

127.0.0.1:6380[1]> SADD key1 "d"
(integer) 1
127.0.0.1:6380[1]> SADD key1 "e"
(integer) 1
127.0.0.1:6380[1]> smembers key1
1) "d"
2) "b"
3) "a"
4) "c"
5) "e"
127.0.0.1:6380[1]> SUNIONSTORE key2 key1 temp
(integer) 5
127.0.0.1:6380[1]> smembers key2
1) "a"
2) "b"
3) "d"
4) "c"
5) "e"
127.0.0.1:6380[1]> smembers temp
(empty list or set)

使用SUNIONSTORE命令可以很容易的实现Set的复制,下面我们看看SUNIONSTORE命令的使用方式:
语法:

SUNIONSTORE destination key [key ...]
  • destination:存放合并结果集的key。
  • key [key …]:一个或者多个集合

注意:
如果是已经存在的集合,会删除原来的数据,只会保留合并结果。
下面创建了一个key3,在key3中有一个成员 “g” ,但是将key1和key2使用SUNIONSTORE命令合并后,结果中不会有 “g” 。

127.0.0.1:6380[1]> sunionstore key3 key1 key2
(integer) 5
127.0.0.1:6380[1]> sadd key1 f h i
(integer) 3
127.0.0.1:6380[1]> sadd key3 g
(integer) 1
127.0.0.1:6380[1]> smembers key3
1) "b"
2) "a"
3) "e"
4) "d"
5) "c"
6) "g"
127.0.0.1:6380[1]> smembers key1
1) "a"
2) "b"
3) "e"
4) "d"
5) "i"
6) "h"
7) "c"
8) "f"
127.0.0.1:6380[1]> sunionstore key3 key1 key2
(integer) 8
127.0.0.1:6380[1]> smembers key3
1) "b"
2) "a"
3) "i"
4) "h"
5) "e"
6) "d"
7) "c"
8) "f"

SortSet有序集合的复制

首先也来创建一个有序集合zset1, 这时候没有zset2这个key

127.0.0.1:6380[1]> zadd zset1 1 a 2 b 3 c 4 d 5 e
(integer) 5
127.0.0.1:6380[1]> zrange zset1 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"

然后将zset1拷贝到zset2中

127.0.0.1:6380[1]> ZUNIONSTORE zset2 1 zset1
(integer) 5

提示有5条内容被处理,然后我们来看看zset2现在的内容:

127.0.0.1:6380[1]> zrange zset2 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"

太帅了!跟zset1的内容一模一样。
这一切都是ZUNIONSTORE这个命令的功劳,下面我们讲讲这个ZUNIONSTORE命令怎么用吧:
语法:

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [SUM|MIN|MAX]

ZUNIONSTORE命令其实就是求并集的命令,他的参数说明如下:

  • destination: 存放合并结果集的key。如果是已经存在的集合,会删除原来的数据,只会保留合并结果。
  • numkeys:有几个集合的内容需要合并
  • key [key …]: 一个或者多个集合
  • [WEIGHTS weight]:分数乘积因子,默认是1.如果设置以后,在合并时,会将待合并的集合中的分数乘以乘积因子,然后将结果保存到合并结果集中。
  • [SUM|MIN|MAX]:结果集的聚合方式。默认是SUM,如果要合并的集合中都有同一个名称的元素,它们的分数以何种方式存储到新的结果集中。SUM:相加;MIN:取最小的值;MAX:取最大的值。
### 使用 Redis Sorted Set 实现分布式锁 #### 设计思路 为了在 Redis 的 `Sorted Set` 中实现分布式锁,可以利用其成员分数(score)来控制锁的持有时间以及唯一性。通过原子操作确保同一时刻只有一个客户端能够成功获得锁。 #### 获取锁的过程 当尝试获取锁时,向指定键名对应的有序集合添加带有当前时间戳作为 score 和唯一标识符作为 member 的新元素: ```java // Java伪代码示例 String lockKey = "my_distributed_lock"; double currentTimestamp = System.currentTimeMillis(); String uniqueClientId = UUID.randomUUID().toString(); Jedis jedis = new Jedis("localhost"); Long result = jedis.zadd(lockKey, currentTimestamp, uniqueClientId); if (result != null && result == 1L) { // 成功插入表示获得了锁 } else { // 插入失败说明已经有其他客户端持有了这把锁 } ``` 此方法依赖于 `ZADD` 命令返回的结果判断是否成功取得锁[^1]。 #### 设置过期时间 为了避免死锁情况发生,在实际应用中还需要设定合理的超时期限,并定期更新已持有的锁的有效期限。可以通过 Lua 脚本来完成这一过程以保证整个流程在一个事务内执行完毕。 ```lua -- Lua脚本用于延长锁的时间 local key = KEYS[1] local clientId = ARGV[1] local expireTime = tonumber(ARGV[2]) if redis.call('zscore', key, clientId) then -- 更新该clientID对应项的新得分即新的到期时间 redis.call('zadd', key, 'xx', expireTime, clientId) end return true ``` 这段 Lua 脚本会先检查给定 ID 是否存在于有序集中,如果存在则将其 score 更新为最新的期望释放时间[^3]。 #### 释放锁的操作 要安全地移除不再需要使用的锁,应该再次借助 Lua 来确保即使有多个请求试图同时解锁也能保持一致性。 ```lua -- Lua脚本用于删除锁 local key = KEYS[1] local clientId = ARGV[1] if redis.call('zscore', key, clientId) ~= false then -- 只允许拥有者自己解除自己的锁 redis.call('zrem', key, clientId) else error("Cannot remove a non-existent element or not owned by this client.") end return true ``` 上述逻辑防止了非持有方误删他人所拥有的资源锁定状态[^4]。 #### 处理竞争条件 考虑到网络延迟等因素可能会造成竞态条件问题,因此建议配合 RedLock 算法或其他类似的多节点共识协议进一步增强系统的健壮性和可靠性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值