redis对hash字段加锁

评论中有人指出文案不对,修正一下

之前提了一个问题 , 见 问答:redis中,只能对key加锁吗

现在我大概清楚了,redis可以针对hash里面的某一个k-v加过期机制,因此不用对整个hash加过期机制,减少并发时的报错次数;提高体验;

下面演示具体的实现

# 先添加一个hash数据
> HMSET 1:item 10001_10 "{'a':1,'b':3}" 10002_20 "{'a':5, 'c':10}"

# 查看一下
127.0.0.1:6379> HGETALL 1:item
1) "10001_10"   //字段
2) "{'a':1,'b':3}"  // 值
3) "10002_20"  // 字段
4) "{'a':5, 'c':10}"  // 值
每个字段和值组成一条数据

# 假如我现在要操作 1:item 的 10001_10 这条数据,为了避免并发问题,需要给其加锁; 
# 为了针对这一条数据加锁,我们可以将其field字段名包含到加锁的set的键名中去;
> set 1:item:10001_10:lock 1 EX 5 NX  
可以看这里的键名称,很关键, 值可以随便给一个, 过期时间是5秒, 如果不存在才创建; 不能创建则表示别人正在使用这条数据,已经加锁了;
ttl key  可以查看过期时间还剩多少

当我们处理完业务后,需要解锁,也就是
> del 1:item:10001_10:lock

设置过期时间,是为了避免意外造成死锁问题

补上一个图

redis对hash字段加锁

我对f1加锁了, 此时别人操作f3的数据,是没有锁冲突的,可以直接去操作的

不对之处,欢迎大家纠正和评论!

本作品采用《CC 协议》,转载必须注明作者和本文链接
六月的风
Junwind
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 5

有点不太理解。可以理解为 根据hash每个字段单独SET 一个Key,然后将其设置EX,业务进来首先检测这个Key是否存在或者过期,存在则进行等待,不操作hash。 不知道这样理解对不对?这样的话,感觉灵魂变味了 :see_no_evil:

2年前 评论
Junwind (楼主) 2年前

我理解 set key value nx ex, 我理解 hset , 但我就是不理解这句话的后半句。

redis 可以针对单个数据加锁, 比如 hash 的一行数据 key-value

我处理业务加锁(非分布式)都是这么加的,这也就是一个很正常的redis-lock , 怎么就变成了“比如hash的一行数据”。 同理是不是也可以说 redis支持对list单独某行数据加锁, set 里面value一样的 子集合 加锁

sadd setName name1, name2, name1
set setName-name1 1 ex 5  nx

发散一下, 可以对 mysql 数据加锁, 对 mongodb数据加锁,对memcache 数据加锁,对万物加锁

首先, 我认同你对于这个问题的解决方案,的确可行。但我建议修改文案

比如 hash 的一行数据 key-value

其实我看过你之前的问题,当时我的想法就是拆出来,而不是你描述的文案,给人的感觉好像 redis 原生支持一样。

发散一下, redis 支持对 hash 中单独的一个 key-value 过期 :dog: :dog: :dog:

2年前 评论
Junwind (楼主) 2年前
Junwind

向大家描述一下问题,我现在有一个hash数据,里面的field-value是唯一的一行,我不希望操作这个hash时,对整个hash加锁,造成体验差,我希望是只针对单一的一个field-value加锁;
hash的结构是这样的

main-key
    filed1 :  val1  //这就是一行数据
    field2 : val2

val同时也可以存字符串,json,序列化等
2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!