Redisæä¸ç³»åçå½ä»¤ï¼ç¹ç¹æ¯ä»¥NXç»å°¾ï¼NXæ¯Not eXistsç缩åï¼å¦SETNXå½ä»¤å°±åºè¯¥ç解为ï¼SET if Not eXistsãè¿ç³»åçå½ä»¤é常æç¨ï¼è¿é讲使ç¨SETNXæ¥å®ç°åå¸å¼éã
ç¨SETNXå®ç°åå¸å¼é
å©ç¨SETNXé常ç®åå°å®ç°åå¸å¼éãä¾å¦ï¼æ客æ·ç«¯è¦è·å¾ä¸ä¸ªååfooçéï¼å®¢æ·ç«¯ä½¿ç¨ä¸é¢çå½ä»¤è¿è¡è·åï¼
SETNX lock.foo <current Unix time + lock timeout + 1>
å¦è¿å1ï¼å该客æ·ç«¯è·å¾éï¼ælock.fooçé®å¼è®¾ç½®ä¸ºæ¶é´å¼è¡¨ç¤ºè¯¥é®å·²è¢«éå®ï¼è¯¥å®¢æ·ç«¯æåå¯ä»¥éè¿DEL lock.fooæ¥éæ¾è¯¥éã
å¦è¿å0ï¼è¡¨æ该é已被å
¶ä»å®¢æ·ç«¯åå¾ï¼è¿æ¶æ们å¯ä»¥å
è¿åæè¿è¡éè¯ç对æ¹å®ææçå¾
éè¶
æ¶ã
解å³æ»é
ä¸é¢çéå®é»è¾æä¸ä¸ªé®é¢ï¼å¦æä¸ä¸ªææéç客æ·ç«¯å¤±è´¥æå´©æºäºä¸è½éæ¾éï¼è¯¥æä¹è§£å³ï¼æ们å¯ä»¥éè¿éçé®å¯¹åºçæ¶é´æ³æ¥å¤æè¿ç§æ
åµæ¯å¦åçäºï¼å¦æå½åçæ¶é´å·²ç»å¤§äºlock.fooçå¼ï¼è¯´æ该é已失æï¼å¯ä»¥è¢«éæ°ä½¿ç¨ã
åçè¿ç§æ
åµæ¶ï¼å¯ä¸è½ç®åçéè¿DELæ¥å é¤éï¼ç¶ååSETNXä¸æ¬¡ï¼å½å¤ä¸ªå®¢æ·ç«¯æ£æµå°éè¶
æ¶åé½ä¼å°è¯å»éæ¾å®ï¼è¿éå°±å¯è½åºç°ä¸ä¸ªç«ææ¡ä»¶,让æ们模æä¸ä¸è¿ä¸ªåºæ¯ï¼
C0æä½è¶
æ¶äºï¼ä½å®è¿ææçéï¼C1åC2读ålock.fooæ£æ¥æ¶é´æ³ï¼å
ååç°è¶
æ¶äºã
C1 åéDEL lock.foo
C1 åéSETNX lock.foo 并ä¸æåäºã
C2 åéDEL lock.foo
C2 åéSETNX lock.foo 并ä¸æåäºã
è¿æ ·ä¸æ¥ï¼C1ï¼C2é½æ¿å°äºéï¼é®é¢å¤§äºï¼
幸好è¿ç§é®é¢æ¯å¯ä»¥é¿å
Dï¼è®©æ们æ¥ççC3è¿ä¸ªå®¢æ·ç«¯æ¯ææ ·åçï¼
C3åéSETNX lock.foo æ³è¦è·å¾éï¼ç±äºC0è¿ææéï¼æ以Redisè¿åç»C3ä¸ä¸ª0
C3åéGET lock.foo 以æ£æ¥éæ¯å¦è¶
æ¶äºï¼å¦æ没è¶
æ¶ï¼åçå¾
æéè¯ã
åä¹ï¼å¦æå·²è¶
æ¶ï¼C3éè¿ä¸é¢çæä½æ¥å°è¯è·å¾éï¼
GETSET lock.foo <current Unix time + lock timeout + 1>
éè¿GETSETï¼C3æ¿å°çæ¶é´æ³å¦æä»ç¶æ¯è¶
æ¶çï¼é£å°±è¯´æï¼C3å¦æ¿ä»¥å¿æ¿å°éäºã
å¦æå¨C3ä¹åï¼æ个å«C4ç客æ·ç«¯æ¯C3å¿«ä¸æ¥æ§è¡äºä¸é¢çæä½ï¼é£ä¹C3æ¿å°çæ¶é´æ³æ¯ä¸ªæªè¶
æ¶çå¼ï¼è¿æ¶ï¼C3没æå¦æè·å¾éï¼éè¦å次çå¾
æéè¯ãçæä¸ä¸ï¼å°½ç®¡C3没æ¿å°éï¼ä½å®æ¹åäºC4设置çéçè¶
æ¶å¼ï¼ä¸è¿è¿ä¸ç¹é常微å°ç误差带æ¥çå½±åå¯ä»¥å¿½ç¥ä¸è®¡ã
注æï¼ä¸ºäºè®©åå¸å¼éçç®æ³æ´ç¨³é®äºï¼ææéç客æ·ç«¯å¨è§£éä¹ååºè¯¥åæ£æ¥ä¸æ¬¡èªå·±çéæ¯å¦å·²ç»è¶
æ¶ï¼åå»åDELæä½ï¼å 为å¯è½å®¢æ·ç«¯å 为æ个èæ¶çæä½èæèµ·ï¼æä½å®çæ¶åéå 为è¶
æ¶å·²ç»è¢«å«äººè·å¾ï¼è¿æ¶å°±ä¸å¿
解éäºã
示ä¾ä¼ªä»£ç
æ ¹æ®ä¸é¢ç代ç ï¼æåäºä¸å°æ®µFake代ç æ¥æ述使ç¨åå¸å¼éçå
¨è¿ç¨ï¼
# get lock
lock = 0
while lock != 1:
timestamp = current Unix time + lock timeout + 1
lock = SETNX lock.foo timestamp
if lock == 1 or (now() > (GET lock.foo) and now() > (GETSET lock.foo timestamp)):
break;
else:
sleep(10ms)
# do your job
do_job()
# release
if now() < GET lock.foo:
DEL lock.foo
æ¯çï¼è¦æ³è¿æ®µé»è¾å¯ä»¥éç¨ï¼ä½¿ç¨pythonçä½ é©¬ä¸å°±æ³å°äºDecoratorï¼èç¨Javaçä½ æ¯ä¸æ¯ä¹æ³å°äºé£è°ï¼AOP + annotationï¼è¡ï¼ææ ·èæææ ·ç¨å§ï¼å«éå¤ä»£ç å°±è¡ã
温馨提示:答案为网友推荐,仅供参考