和大家分享我的經驗,如何用redis提供的一個簡單介面,輕鬆實現redis分散式鎖。
在開始之前,我先簡單介紹下redis的效能。
Redis本身是單執行緒的,這樣帶來的好處是能夠提高讀寫效率。多執行緒通常來說會有上下文切換帶來的時間損耗,而redis透過繫結單個CPU到某塊記憶體,實現了上下文切換的最小開銷,因此這種場景反而比多執行緒還要高效。
但是,如果有不同的節點同時要對Redis中的同一個資料進行操作,由於是來自不同Redis伺服器,就會發生執行緒不安全的情況。
舉例有兩個功能函式X和Y(也可以看做是兩個伺服器節點),二者功能相同,都要執行讀取Redis中變數P,並且對其加一的操作。如果是執行緒安全的,那麼X和Y分別執行完之後,P的值應該比原來增加2,但是由於函式XY互相獨立,那就可能發生下面這種情況:
1 X讀取P
2 Y讀取P
3 X將P+1寫回Redis
4 Y將P+1寫回Redis
執行結束後,P的值卻變成了P+1,而不是P+2。
這就是執行緒不安全導致的結果。
那麼如何用Redis來避免上面的情況呢。
Redis對外開放了一個非常厲害的api,目前經常被大家用來做分散式鎖,是絕對的執行緒安全,這個函式就是SET key field value加上NX引數。這個NX引數可是了不得,通常來說,set函式是不管field欄位是否存在,只要寫入成功就會返回1,但是如果增加了NX引數,那麼如果field值在redis中已經存在,就會返回nil,否則才返回1。因此可以透過這個函式來執行加鎖操作,如果返回值不為nil,則加鎖成功,否則代表有其他執行緒在操作資料,當前請求需要等待。
不僅如此,為了避免死鎖,SET還有一個引數為EX,即EX毫秒後,field會自動清空。
此外,還有PX,XX引數,具體含義見如下文件。
和大家分享我的經驗,如何用redis提供的一個簡單介面,輕鬆實現redis分散式鎖。
在開始之前,我先簡單介紹下redis的效能。
高效的RedisRedis本身是單執行緒的,這樣帶來的好處是能夠提高讀寫效率。多執行緒通常來說會有上下文切換帶來的時間損耗,而redis透過繫結單個CPU到某塊記憶體,實現了上下文切換的最小開銷,因此這種場景反而比多執行緒還要高效。
不安全的Redis但是,如果有不同的節點同時要對Redis中的同一個資料進行操作,由於是來自不同Redis伺服器,就會發生執行緒不安全的情況。
舉例有兩個功能函式X和Y(也可以看做是兩個伺服器節點),二者功能相同,都要執行讀取Redis中變數P,並且對其加一的操作。如果是執行緒安全的,那麼X和Y分別執行完之後,P的值應該比原來增加2,但是由於函式XY互相獨立,那就可能發生下面這種情況:
1 X讀取P
2 Y讀取P
3 X將P+1寫回Redis
4 Y將P+1寫回Redis
執行結束後,P的值卻變成了P+1,而不是P+2。
這就是執行緒不安全導致的結果。
redis的分散式鎖那麼如何用Redis來避免上面的情況呢。
Redis對外開放了一個非常厲害的api,目前經常被大家用來做分散式鎖,是絕對的執行緒安全,這個函式就是SET key field value加上NX引數。這個NX引數可是了不得,通常來說,set函式是不管field欄位是否存在,只要寫入成功就會返回1,但是如果增加了NX引數,那麼如果field值在redis中已經存在,就會返回nil,否則才返回1。因此可以透過這個函式來執行加鎖操作,如果返回值不為nil,則加鎖成功,否則代表有其他執行緒在操作資料,當前請求需要等待。
不僅如此,為了避免死鎖,SET還有一個引數為EX,即EX毫秒後,field會自動清空。
此外,還有PX,XX引數,具體含義見如下文件。