使用Redis HASH的VALUE存放了一段JSON字串,在並行作業時怎麼保證JSON字串的原子性

來源:互聯網
上載者:User
假設我在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的原子性呢?

回複內容:

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

你說的問題的確存在,你這裡涉及到的問題其實就是普遍的讀-改-寫,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即可,這樣也就不會出現並發了,但是如果你還是需要基於原始的值進行判斷然後再修改,那麼問題還是跟上面說的一樣,沒有任何變化。

redis是單執行緒模式,不用擔心這個問題

hget和hset兩個操作可以用事務控制

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.