我們都知道,memcached的協議中是沒有任何一個協議提供給我們檢查某個key是否存在的。但是我們可能會有這樣的需求。
一些開源的客戶端提供了KeyExists()這樣的方法,但是其實現原理是調用了memcached的get協議,以此來達到判斷某個key是否存在的目的:能取到表示這個key存在,取不到則不存在。這樣的效率是比較低的,特別是當數據包比較大的情況下。
在不讀取memcached的數據的情況下,如何高效的判斷某個key是否存在呢?
大家都知道memcached的cas(check and set)協議吧,該協議在寫memcached時先判斷是否有人在你之前更新過數據,如果有更新過,則此次寫memcached失敗。
那我們來看一下cas的語法:
cas key flag exptime bytes version\r\n
其中的version是memcached內部維護的一個版本號,是個uint64_t的值,這個值是調用memcached的gets協議獲得的,version從1開始,memcached剛啟動的時候,節點數為0,從存儲第一個節點開始,version不斷累加。因此,version是不可能出現0這個情況,這點很重要,是達到我們的目的的一個關鍵點。
好了,我們已經知道了cas的用法,根據它的特性可以實現我們檢查一個key是否存在的目的,聰明的讀者可能已經知道該怎么做了吧。
比如要檢查foo這個key是否存在,可以構造這樣的命令
cas foo 0 0 1 0\r\n
這里構造一個字節的數據包,將version字段設置成0,嘗試寫memcached。
如果foo已經存在,因為它的version不可能等於0,所以memcached提示EXISTS
如果foo不存在,memcached提示NOT_FOUND
------------------------------------------
set foo 0 0 3 # 先寫入
bar
STORED
cas foo 0 0 1 0 # 判斷foo是否存在,系統提示EXISTS
a
EXISTS
delete foo # 將foo刪除
DELETED
cas foo 0 0 1 0 # 判斷foo是否存在,系統提示NOT_FOUND
a
NOT_FOUND
------------------------------------------
這樣,我們就知道foo這個key是否存在了。