在學習Redis的經常使用操做時,常常看到介紹說,Redis的set、get以及hset等等命令的執行都是原子性的,可是令本身百思不得其解的是,爲何這些操做是原子性的?php
原子性是數據庫的事務中的特性。在數據庫事務的情景下,原子性指的是:一個事務(transaction)中的全部操做,要麼所有完成,要麼所有不完成,不會結束在中間某個環節。【維基百科】mysql
對於Redis而言,命令的原子性指的是:一個操做的不能夠再分,操做要麼執行,要麼不執行。redis
Redis的操做之因此是原子性的,是由於Redis是單線程的。sql
因爲對操做系統相關的知識不是很熟悉,從上面這句話並不能真正理解Redis操做是原子性的緣由,進一步查閱進程與線程的概念及其區別。數據庫
計算機中已執行程序的實體。【維基百科】。好比,一個啓動了的php-fpm,就是一個進程。併發
操做系統可以進行運算調度的最小單元。它被包含在進程之中,是進程的實際運做單位。一條線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。【維基百科】。好比,mysql運行時,mysql啓動後,該mysql服務就是一個進程,而mysql的鏈接、查詢的操做,就是線程。php-fpm
資源(如打開文件):進程間的資源相互獨立,同一進程的各線程間共享資源。某進程的線程在其餘進程不可見。學習
通訊:進程間通訊:消息傳遞、同步、共享內存、遠程過程調用、管道。線程間通訊:直接讀寫進程數據段(須要進程同步和互斥手段的輔助,以保證數據的一致性)。操作系統
調度和切換:線程上下文切換比進程上下文切換要快得多。線程
線程,是操做系統最小的執行單元,在單線程程序中,任務一個一個地作,必須作完一個任務後,纔會去作另外一個任務。
Redis的API是原子性的操做,那麼多個命令在併發中也是原子性的嗎?
看看下面這段代碼:
$redis = new Redis(); $redis->connect('127.0.0.1', 6379); for($i = 0; $i < 1000; $i++) { $num = (int) $redis->get('val'); $num++; $redis->set('val', $num); usleep(10000); }
用兩個終端執行上面的程序,發現val的結果是小於2000的值,那麼能夠知道,在程序中執行多個Redis命令並不是是原子性的,這也和普通數據庫的表現是同樣的。
若是想在上面的程序中實現原子性,能夠將get和set改爲單命令操做,好比incr,或者使用Redis的事務,或者使用Redis+Lua的方式實現。
綜上所述,對Redis來講,執行get、set以及eval等API,都是一個一個的任務,這些任務都會由Redis的線程去負責執行,任務要麼執行成功,要麼執行失敗,這就是Redis的命令是原子性的緣由。
Redis自己提供的全部API都是原子操做,Redis中的事務實際上是要保證批量操做的原子性。
原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。
若是本文對你有幫助,請點下推薦吧,謝謝^_^