ホームページ  >  に質問  >  本文

使用Redis HASH的VALUE存放了一段JSON字符串,在并发操作时怎么保证JSON字符串的原子性

假设我在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的原子性呢?


高洛峰高洛峰2922日前1232

全員に返信(2)返信します

  • 欧阳克

    欧阳克2016-11-10 17:26:33

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

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


    返事
    0
  • 三叔

    三叔2016-11-10 17:26:21

    你说的问题的确存在,你这里涉及到的问题其实就是普遍的读-改-写,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即可,这样也就不会出现并发了,但是如果你还是需要基于原始的值进行判断然后再修改,那么问题还是跟上面说的一样,没有任何变化。


    返事
    0
  • キャンセル返事