使用Redis HASH的VALUE存放了一段JSON字符串,在并发操作时怎么保证JSON字符串的原子性
高洛峰
高洛峰 2016-11-10 17:26:07
0
2
1242

假设我在Redis中存放了这样一条HASH

HSET player Mike  "{\"height\":180,\"isAlive\":true}"

接着假设php中有2个并发操作,都是HGET这段json,json_decode成php数组.然后对其中某个value进行操作.json_encode后再HSET回去.

比如
一个操作将isAlive设置成false,
另一个操作是将height改成181,
那么这下很可能发生意外情况-----第二个操作在前一个操作将数据HSET到数据库之前将数据HGET了去
哦..这下糟糕了
本来前一个操作已经将人给弄死了,结果后一个操作又将人复活了..

然后,试想一下更多并发操作更多的VALUE...

有没有什么好办法能保证这段JSON的原子性呢?


高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

Antworte allen(2)
学霸

redis是单线程模型,不用担心这个问题

hget和hset两个操作可以用事务控制


三叔

你说的问题的确存在,你这里涉及到的问题其实就是普遍的读-改-写,redis可以保证每个操作的原子性,但是无法保证多个操作的原子性,解决的方法可以使用redis提供的multi和watch命令,具体使用如下:
1.watch住你想要读取的key
2.multi开启事务
3.读取key的内容
4.修改value内容
5.更新key内容
6.exec提交事务,如果在2-6之间发生key的value发生了变化,那么会报错。

以上所说只是redis能够提供的最大的原子性操作,但是对于你的问题是没有任何帮助的,因为在事务中执行的命令只有等到事务提交之后才能获取返回值,但是你的更改需要基于前一步的结果进行操作,那么事务不提交你也就无法获取到原来的内容,所以无法更新。解决办法是把json格式字符串使用redis的hash结构进行保存,更新的时候直接更新hash下的一个key即可,这样也就不会出现并发了,但是如果你还是需要基于原始的值进行判断然后再修改,那么问题还是跟上面说的一样,没有任何变化。


Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage