±à¼ÍƼö: |
Íò×Ö³¤ÎÄ£¬´øÄãÉîÈë½âÃܸ߲¢·¢»·¾³Ïµķֲ¼Ê½Ëø¼Ü¹¹£¬²»ÊÇËùÓеÄËø¶¼ÊÇ·Ö²¼Ê½Ëø£¡£¡ À´×ÔÓÚ΢ÐŹ«ÖںűùºÓ¼¼Êõ,ÓÉ»ðÁú¹ûÈí¼þAnna±à¼¡¢ÍƼö¡£ |
|
дÔÚÇ°Ãæ
¾¿¾¹Ê²Ã´ÑùµÄËø²ÅÄܸüºÃµÄÖ§³Ö¸ß²¢·¢³¡¾°ÄØ£¿½ñÌ죬ÎÒÃǾÍÒ»Æð½âÃܸ߲¢·¢»·¾³ÏµäÐ͵ķֲ¼Ê½Ëø¼Ü¹¹£¬½áºÏ¡¾¸ß²¢·¢¡¿×¨ÌâÏÂµÄÆäËûÎÄÕ£¬Ñ§ÒÔÖÂÓá£
ËøÓÃÀ´½â¾öʲôÎÊÌâÄØ£¿
ÔÚÎÒÃDZàдµÄÓ¦ÓóÌÐò»òÕ߸߲¢·¢³ÌÐòÖУ¬²»ÖªµÀ´ó¼ÒÓÐûÓÐÏë¹ýÒ»¸öÎÊÌ⣬¾ÍÊÇÎÒÃÇΪʲôÐèÒªÒýÈëËø£¿ËøÎªÎÒÃǽâ¾öÁËʲôÎÊÌâÄØ£¿
ÔںܶàÒµÎñ³¡¾°Ï£¬ÎÒÃDZàдµÄÓ¦ÓóÌÐòÖÐ»á´æÔںܶàµÄ ×ÊÔ´¾ºÕù µÄÎÊÌâ¡£¶øÎÒÃÇÔڸ߲¢·¢³ÌÐòÖУ¬ÒýÈëËø£¬¾ÍÊÇΪÁ˽â¾öÕâЩ×ÊÔ´¾ºÕùµÄÎÊÌâ¡£
µçÉ̳¬ÂôÎÊÌâ
ÕâÀÎÒÃÇ¿ÉÒÔÁоÙÒ»¸ö¼òµ¥µÄÒµÎñ³¡¾°¡£±ÈÈ磬ÔÚµç×ÓÉÌÎñ£¨É̳ǣ©µÄÒµÎñ³¡¾°ÖУ¬Ìá½»¶©µ¥¹ºÂòÉÌÆ·Ê±£¬Ê×ÏÈÐèÒª²éѯÏàÓ¦ÉÌÆ·µÄ¿â´æÊÇ·ñ×ã¹»£¬Ö»ÓÐÔÚÉÌÆ·¿â´æÊýÁ¿×ã¹»µÄǰÌáÏ£¬²ÅÄÜÈÃÓû§³É¹¦µÄϵ¥¡£Ïµ¥Ê±£¬ÎÒÃÇÐèÒªÔÚ¿â´æÊýÁ¿ÖмõÈ¥Óû§Ïµ¥µÄÉÌÆ·ÊýÁ¿£¬²¢½«¿â´æ²Ù×÷µÄ½á¹ûÊý¾Ý¸üе½Êý¾Ý¿âÖС£Õû¸öÁ÷³ÌÎÒÃÇ¿ÉÒÔ¼ò»¯³ÉÏÂͼËùʾ¡£

ºÜ¶àС»ï°éÒ²ÁôÑÔ˵£¬ÈÃÎÒ¸ø³ö´úÂ룬ÕâÑùÄܹ»¸üºÃµÄѧϰºÍÕÆÎÕÏà¹ØµÄ֪ʶ¡£ºÃ°É£¬ÕâÀÎÒÒ²¸ø³öÏàÓ¦µÄ´úÂëÆ¬¶Î°É¡£ÎÒÃÇ¿ÉÒÔʹÓÃÏÂÃæµÄ´úÂëÆ¬¶ÎÀ´±íʾÓû§µÄϵ¥²Ù×÷£¬ÎÒÕâÀォÉÌÆ·µÄ¿â´æÐÅÏ¢±£´æÔÚÁËRedisÖС£
RequestMapping("/submitOrder")
public String submitOrder(){
int stock = Integer.parseInt (stringRedisTemplate.opsForValue().get("stock"));
if(stock > 0){
stock -= 1;
stringRedisTemplate.opsForValue( ).set("stock",
String.valueOf(stock));
logger.debug("¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º{}", stock);
}else{
logger.debug("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
throw new OrderException("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
}
return "success";
} |
×¢Ò⣺ÉÏÊö´úÂëÆ¬¶Î±È½Ï¼òµ¥£¬Ö»ÊÇΪÁË·½±ã´ó¼ÒÀí½â£¬ÕæÕýÏîÄ¿ÖеĴúÂë¾Í²»ÄÜÕâôдÁË¡£
ÉÏÊöµÄ´úÂë¿´ËÆÊÇûɶÎÊÌâµÄ£¬µ«ÊÇÎÒÃDz»ÄÜÖ»´Ó´úÂë±íÃæÉÏÀ´¹Û²ì´úÂëµÄÖ´ÐÐ˳Ðò¡£ÕâÊÇÒòΪÔÚJVMÖдúÂëµÄÖ´ÐÐ˳Ðòδ±ØÊǰ´ÕÕÎÒÃÇÊéд´úÂëµÄ˳ÐòÖ´Ðеġ£¼´Ê¹ÔÚJVMÖдúÂëÊǰ´ÕÕÎÒÃÇÊéдµÄ˳ÐòÖ´ÐУ¬ÄÇÎÒÃǶÔÍâÌṩµÄ½Ó¿ÚÒ»µ©±©Â¶³öÈ¥£¬¾Í»áÓгÉǧÉÏÍòµÄ¿Í»§¶ËÀ´·ÃÎÊÎÒÃǵĽӿڡ£ËùÒÔ˵£¬ÎÒÃDZ©Â¶³öÈ¥µÄ½Ó¿ÚÊǻᱻ²¢·¢·ÃÎʵġ£
ÊÔÎÊ£¬ÉÏÃæµÄ´úÂëÔڸ߲¢·¢»·¾³ÏÂÊÇḬ̈߳²È«µÄÂ𣿴𰸿϶¨²»ÊÇḬ̈߳²È«µÄ£¬ÒòΪÉÏÊö¿Û¼õ¿â´æµÄ²Ù×÷»á³öÏÖ²¢ÐÐÖ´ÐеÄÇé¿ö¡£
ÎÒÃÇ¿ÉÒÔʹÓÃApache JMeterÀ´¶ÔÉÏÊö½Ó¿Ú½øÐвâÊÔ£¬ÕâÀÎÒʹÓÃApache JMeter¶ÔÉÏÊö½Ó¿Ú½øÐвâÊÔ¡£

ÔÚJmeterÖУ¬ÎÒ½«Ï̵߳IJ¢·¢¶ÈÉèÖÃΪ3£¬½ÓÏÂÀ´µÄÅäÖÃÈçÏÂËùʾ¡£

ÒÔHTTP GETÇëÇóµÄ·½Ê½À´²¢·¢·ÃÎÊÌá½»¶©µ¥µÄ½Ó¿Ú¡£´Ëʱ£¬ÔËÐÐJMeterÀ´·ÃÎʽӿڣ¬ÃüÁîÐлá´òÓ¡³öÏÂÃæµÄÈÕÖ¾ÐÅÏ¢¡£
¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º49
¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º49
¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º49 |
ÕâÀÎÒÃÇÃ÷Ã÷ÇëÇóÁË3´Î£¬Ò²¾ÍÊÇ˵£¬Ìá½»ÁË3±Ê¶©µ¥£¬ÎªÊ²Ã´¿Û¼õºóµÄ¿â´æ¶¼ÊÇÒ»ÑùµÄÄØ£¿ÕâÖÖÏÖÏóÔÚµçÉÌÁìÓòÓÐÒ»¸öרҵµÄÃû´Ê½Ð×ö
¡°³¬Âô¡± ¡£
Èç¹ûÒ»¸ö´óÐ͵ĸ߲¢·¢µçÉÌϵͳ£¬±ÈÈçÌÔ±¦¡¢Ììè¡¢¾©¶«µÈ£¬³öÏÖÁ˳¬ÂôÏÖÏó£¬ÄÇËðʧ¾ÍÎÞ·¨¹ÀÁ¿ÁË£¡¼Ü¹¹Éè¼ÆºÍ¿ª·¢µçÉÌϵͳµÄÈËÔ±¹À¼Æ¾ÍҪͨͨϸÚÁË¡£ËùÒÔ£¬×÷Ϊ¼¼ÊõÈËÔ±£¬ÎÒÃÇÒ»¶¨ÒªÑϽ÷µÄ¶Ô´ý¼¼Êõ£¬Ñϸñ×öºÃϵͳµÄÿһ¸ö¼¼Êõ»·½Ú¡£
JVMÖÐÌṩµÄËø
JVMÖÐÌṩµÄsynchronizedºÍLockËø£¬ÏàÐÅ´ó¼Ò²¢²»Ä°ÉúÁË£¬ºÜ¶àС»ï°é¶¼»áʹÓÃÕâÐ©Ëø£¬Ò²ÄÜʹÓÃÕâÐ©ËøÀ´ÊµÏÖһЩ¼òµ¥µÄÏ̻߳¥³â¹¦ÄÜ¡£ÄÇô£¬×÷ΪÁ¢Ö¾Òª³ÉΪ¼Ü¹¹Ê¦µÄÄ㣬ÊÇ·ñÁ˽â¹ýJVMËøµÄµ×²ãÔÀíÄØ£¿
JVMËøÔÀí
˵µ½JVMËøµÄÔÀí£¬ÎÒÃǾͲ»µÃ²»ÏÞ˵˵JavaÖеĶÔÏóÍ·ÁË¡£
JavaÖеĶÔÏóÍ·
ÿ¸öJava¶ÔÏó¶¼ÓжÔÏóÍ·¡£Èç¹ûÊÇ?Êý×éÀàÐÍ£¬Ôò?2¸ö×Ö¿íÀ´´æ´¢¶ÔÏóÍ·£¬Èç¹ûÊÇÊý×飬Ôò»á?3¸ö×Ö¿íÀ´´æ´¢¶ÔÏóÍ·¡£ÔÚ32λ´¦ÀíÆ÷ÖУ¬?¸ö×Ö¿íÊÇ32λ£»ÔÚ64λÐéÄâ»úÖУ¬?¸ö×Ö¿íÊÇ64λ¡£
¶ÔÏóÍ·µÄÄÚÈÝÈçÏÂ±í ¡£

Mark WorkµÄ¸ñʽÈçÏÂËùʾ¡£

¿ÉÒÔ¿´µ½£¬µ±¶ÔÏó״̬ΪƫÏòËøÊ±£¬ Mark Word ´æ´¢µÄÊÇÆ«ÏòµÄÏß³ÌID£»µ±×´Ì¬ÎªÇáÁ¿¼¶ËøÊ±£¬
Mark Word ´æ´¢µÄÊÇÖ¸ÏòÏß³ÌÕ»ÖÐ Lock Record µÄÖ¸Õ룻µ±×´Ì¬ÎªÖØÁ¿¼¶ËøÊ±£¬ Mark
Word ΪָÏò¶ÑÖеÄmonitor¶ÔÏóµÄÖ¸Õë ¡£
ÓйØJava¶ÔÏóÍ·µÄ֪ʶ£¬²Î¿¼¡¶ÉîÈëdz³öJava¶àÏ̡߳·¡£
JVMËøÔÀí
¼òµ¥µãÀ´Ëµ£¬JVMÖÐËøµÄÔÀíÈçÏ¡£
ÔÚJava¶ÔÏóµÄ¶ÔÏóÍ·ÉÏ£¬ÓÐÒ»¸öËøµÄ±ê¼Ç£¬±ÈÈ磬µÚÒ»¸öÏß³ÌÖ´ÐгÌÐòʱ£¬¼ì²éJava¶ÔÏóÍ·ÖеÄËø±ê¼Ç£¬·¢ÏÖJava¶ÔÏóÍ·ÖеÄËø±ê¼ÇΪδ¼ÓËø×´Ì¬£¬ÓÚÊÇΪJava¶ÔÏó½øÐÐÁ˼ÓËø²Ù×÷£¬½«¶ÔÏóÍ·ÖеÄËø±ê¼ÇÉèÖÃÎªËø¶¨×´Ì¬¡£µÚ¶þ¸öÏß³ÌÖ´ÐÐͬÑùµÄ³ÌÐòʱ£¬Ò²»á¼ì²éJava¶ÔÏóÍ·ÖеÄËø±ê¼Ç£¬´Ëʱ»á·¢ÏÖJava¶ÔÏóÍ·ÖеÄËø±ê¼ÇµÄ×´Ì¬ÎªËø¶¨×´Ì¬¡£ÓÚÊÇ£¬µÚ¶þ¸öÏß³Ì»á½øÈëÏàÓ¦µÄ×èÈû¶ÓÁÐÖнøÐеȴý¡£
ÕâÀïÓÐÒ»¸ö¹Ø¼üµã¾ÍÊÇJava¶ÔÏóÍ·ÖеÄËø±ê¼ÇÈçºÎʵÏÖ¡£
JVMËøµÄ¶Ì°å
JVMÖÐÌṩµÄsynchronizedºÍLockËø¶¼ÊÇJVM¼¶±ðµÄ£¬´ó¼Ò¶¼ÖªµÀ£¬µ±ÔËÐÐÒ»¸öJava³ÌÐòʱ£¬»áÆô¶¯Ò»¸öJVM½ø³ÌÀ´ÔËÐÐÎÒÃǵÄÓ¦ÓóÌÐò¡£synchronizedºÍLockÔÚJVM¼¶±ðÓÐЧ£¬Ò²¾ÍÊÇ˵£¬synchronizedºÍLockÔÚͬһJava½ø³ÌÄÚÓÐЧ¡£Èç¹ûÎÒÃÇ¿ª·¢µÄÓ¦ÓóÌÐòÊÇ·Ö²¼Ê½µÄ£¬ÄÇôֻÊÇʹÓÃsynchronizedºÍLockÀ´½â¾ö·Ö²¼Ê½³¡¾°Ïµĸ߲¢·¢ÎÊÌ⣬¾Í»áÏÔµÃÓеãÁ¦²»´ÓÐÄÁË¡£
synchronizedºÍLockÖ§³ÖJVMͬһ½ø³ÌÄÚ²¿µÄÏ̻߳¥³â
synchronizedºÍLockÔÚJVM¼¶±ðÄܹ»±£Ö¤¸ß²¢·¢³ÌÐòµÄ»¥³â£¬ÎÒÃÇ¿ÉÒÔʹÓÃÏÂͼÀ´±íʾ¡£

µ«ÊÇ£¬µ±ÎÒÃǽ«Ó¦ÓóÌÐò²¿Êð³É·Ö²¼Ê½¼Ü¹¹£¬»òÕß½«Ó¦ÓóÌÐòÔÚ²»Í¬µÄJVM½ø³ÌÖÐÔËÐÐʱ£¬synchronizedºÍLock¾Í²»Äܱ£Ö¤·Ö²¼Ê½¼Ü¹¹ºÍ¶àJVM½ø³ÌÏÂÓ¦ÓóÌÐòµÄ»¥³âÐÔÁË¡£
synchronizedºÍLock²»ÄÜʵÏÖ¶àJVM½ø³ÌÖ®¼äµÄÏ̻߳¥³â
·Ö²¼Ê½¼Ü¹¹ºÍ¶àJVM½ø³ÌµÄ±¾Öʶ¼Êǽ«Ó¦ÓóÌÐò²¿ÊðÔÚ²»Í¬µÄJVMʵÀýÖУ¬Ò²¾ÍÊÇ˵£¬Æä±¾ÖÊ»¹ÊǶàJVM½ø³Ì¡£

·Ö²¼Ê½Ëø
ÎÒÃÇÔÚʵÏÖ·Ö²¼Ê½ËøÊ±£¬¿ÉÒÔ²ÎÕÕJVMËøÊµÏÖµÄ˼Ï룬JVMËøÔÚΪ¶ÔÏó¼ÓËøÊ±£¬Í¨¹ý¸Ä±äJava¶ÔÏóµÄ¶ÔÏóÍ·ÖеÄËøµÄ±ê־λÀ´ÊµÏÖ£¬Ò²¾ÍÊÇ˵£¬ËùÓеÄÏ̶߳¼»á·ÃÎÊÕâ¸öJava¶ÔÏóµÄ¶ÔÏóÍ·ÖеÄËø±ê־λ¡£

ÎÒÃÇͬÑùÒÔÕâÖÖ˼ÏëÀ´ÊµÏÖ·Ö²¼Ê½Ëø£¬µ±ÎÒÃǽ«Ó¦ÓóÌÐò½øÐвð·Ö²¢²¿Êð³É·Ö²¼Ê½¼Ü¹¹Ê±£¬ËùÓÐÓ¦ÓóÌÐòÖеÄÏ̷߳ÃÎʹ²Ïí±äÁ¿Ê±£¬¶¼µ½Í¬Ò»¸öµØ·½È¥¼ì²éµ±Ç°³ÌÐòµÄÁÙ½çÇøÊÇ·ñ½øÐÐÁ˼ÓËø²Ù×÷£¬¶øÊÇ·ñ½øÐÐÁ˼ÓËø²Ù×÷£¬ÎÒÃÇÔÚͳһµÄµØ·½Ê¹ÓÃÏàÓ¦µÄ״̬À´½øÐбê¼Ç¡£

¿ÉÒÔ¿´µ½£¬ÔÚ·Ö²¼Ê½ËøµÄʵÏÖ˼ÏëÉÏ£¬ÓëJVMËøÏà²î²»´ó¡£¶øÔÚʵÏÖ·Ö²¼Ê½ËøÖУ¬±£´æ¼ÓËø×´Ì¬µÄ·þÎñ¿ÉÒÔʹÓÃMySQL¡¢RedisºÍZookeeperʵÏÖ¡£
µ«ÊÇ£¬ÔÚ»¥ÁªÍø¸ß²¢·¢»·¾³ÖУ¬ ʹÓÃRedisʵÏÖ·Ö²¼Ê½ËøµÄ·½°¸ÊÇʹÓõÄ×î¶àµÄ¡£ ½ÓÏÂÀ´£¬ÎÒÃǾÍʹÓÃRedisÀ´ÉîÈë½âÃÜ·Ö²¼Ê½ËøµÄ¼Ü¹¹Éè¼Æ¡£
RedisÈçºÎʵÏÖ·Ö²¼Ê½Ëø
RedisÃüÁî
ÔÚRedisÖУ¬ÓÐÒ»¸ö²»³£Ê¹ÓõÄÃüÁîÈçÏÂËùʾ¡£
ÕâÌõÃüÁîµÄº¬Òå¾ÍÊÇ¡°SET if Not Exists¡±£¬¼´²»´æÔÚµÄʱºò²Å»áÉèÖÃÖµ¡£
Ö»ÓÐÔÚkey²»´æÔÚµÄÇé¿öÏ£¬½«¼ükeyµÄÖµÉèÖÃΪvalue¡£Èç¹ûkeyÒѾ´æÔÚ£¬ÔòSETNXÃüÁî²»×öÈκβÙ×÷¡£
Õâ¸öÃüÁîµÄ·µ»ØÖµÈçÏ¡£
ÃüÁîÔÚÉèÖóɹ¦Ê±·µ»Ø1¡£
ÃüÁîÔÚÉèÖÃʧ°Üʱ·µ»Ø0¡£
ËùÒÔ£¬ÎÒÃÇÔÚ·Ö²¼Ê½¸ß²¢·¢»·¾³Ï£¬¿ÉÒÔʹÓÃRedisµÄSETNXÃüÁîÀ´ÊµÏÖ·Ö²¼Ê½Ëø¡£¼ÙÉè´ËʱÓÐÏß³ÌAºÍÏß³ÌBͬʱ·ÃÎÊÁÙ½çÇø´úÂ룬¼ÙÉèÏß³ÌAÊ×ÏÈÖ´ÐÐÁËSETNXÃüÁ²¢·µ»Ø½á¹û1£¬¼ÌÐøÏòÏÂÖ´ÐС£¶ø´ËʱÏß³ÌBÔÙ´ÎÖ´ÐÐSETNXÃüÁîʱ£¬·µ»ØµÄ½á¹ûΪ0£¬ÔòÏß³ÌB²»ÄܼÌÐøÏòÏÂÖ´ÐС£Ö»Óе±Ïß³ÌAÖ´ÐÐDELETEÃüÁÉèÖõÄËø×´Ì¬É¾³ýʱ£¬Ïß³ÌB²Å»á³É¹¦Ö´ÐÐSETNXÃüÁîÉèÖüÓËø×´Ì¬ºó¼ÌÐøÏòÏÂÖ´ÐС£
ÒýÈë·Ö²¼Ê½Ëø
Á˽âÁËÈçºÎʹÓÃRedisÖеÄÃüÁîʵÏÖ·Ö²¼Ê½Ëøºó£¬ÎÒÃǾͿÉÒÔ¶Ôϵ¥½Ó¿Ú½øÐиÄÔìÁË£¬¼ÓÈë·Ö²¼Ê½Ëø£¬ÈçÏÂËùʾ¡£
/**
* ΪÁËÑÝʾ·½±ã£¬ÎÒÕâÀï¾Í¼òµ¥¶¨ÒåÁËÒ»¸ö³£Á¿×÷ΪÉÌÆ·µÄid
* ʵ¼Ê¹¤×÷ÖУ¬Õâ¸öÉÌÆ·idÊÇǰ¶Ë½øÐÐϵ¥²Ù×÷´«µÝ¹ýÀ´µÄ²ÎÊý
*/
public static final String PRODUCT_ID = "100001";
@RequestMapping ("/submitOrder")
public String submitOrder(){
//ͨ¹ýstringRedisTemplateÀ´µ÷ÓÃRedisµÄSETNXÃüÁkeyΪÉÌÆ·µÄid£¬valueΪ×Ö·û´®¡°binghe¡±
//ʵ¼ÊÉÏ£¬value¿ÉÒÔΪÈÎÒâµÄ×Ö·û»»
Boolean isLocked = stringRedisTemplate.opsForValue(
).setIfAbsent (PRODUCT_ID, "binghe");
//ûÓÐÄõ½Ëø£¬·µ»ØÏµ¥Ê§°Ü
if(!isLock){
return "failure";
}
int stock = Integer.parseInt (stringRedisTemplate.opsForValue(
).get("stock"));
if(stock > 0){
stock -= 1;
stringRedisTemplate.opsForValue( ).set("stock",
String.valueOf(stock));
logger.debug("¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º{}", stock);
}else{
logger.debug("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
throw new OrderException ("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
}
//ÒµÎñÖ´ÐÐÍê³É£¬É¾³ýPRODUCT_ID key
stringRedisTemplate.delete ( PRODUCT_ID );
return "success";
} |
ÄÇô£¬ÔÚÉÏÊö´úÂëÖУ¬ÎÒÃǼÓÈëÁË·Ö²¼Ê½ËøµÄ²Ù×÷£¬ÄÇÉÏÊö´úÂëÊÇ·ñÄܹ»Ôڸ߲¢·¢³¡¾°Ï±£Ö¤ÒµÎñµÄÔ×ÓÐÔÄØ£¿´ð°¸ÊÇ¿ÉÒÔ±£Ö¤ÒµÎñµÄÔ×ÓÐÔ¡£µ«ÊÇ£¬ÔÚʵ¼Ê³¡¾°ÖУ¬ÉÏÃæÊµÏÖ·Ö²¼Ê½ËøµÄ´úÂëÊDz»¿ÉÓõģ¡£¡
¼ÙÉèµ±Ïß³ÌAÊ×ÏÈÖ´ÐÐstringRedisTemplate.opsForValue()µÄsetIfAbsent()·½·¨·µ»Øtrue£¬¼ÌÐøÏòÏÂÖ´ÐУ¬ÕýÔÚÖ´ÐÐÒµÎñ´úÂëʱ£¬Å׳öÁËÒì³££¬Ïß³ÌAÖ±½ÓÍ˳öÁËJVM¡£´Ëʱ£¬stringRedisTemplate.delete(PRODUCT_ID);´úÂ뻹ûÀ´µÃ¼°Ö´ÐУ¬Ö®ºóËùÓеÄÏ߳̽øÈëÌá½»¶©µ¥µÄ·½·¨Ê±£¬µ÷ÓÃstringRedisTemplate.opsForValue()µÄsetIfAbsent()·½·¨¶¼»á·µ»Øfalse¡£µ¼ÖºóÐøµÄËùÓÐϵ¥²Ù×÷¶¼»áʧ°Ü¡£Õâ¾ÍÊÇ·Ö²¼Ê½³¡¾°ÏµÄËÀËøÎÊÌâ¡£
ËùÒÔ£¬ÉÏÊö´úÂëÖÐʵÏÖ·Ö²¼Ê½ËøµÄ·½Ê½ÔÚʵ¼Ê³¡¾°ÏÂÊDz»¿ÉÈ¡µÄ£¡£¡
ÒýÈëtry-finally´úÂë¿é
˵µ½Õ⣬ÏàÐÅС»ï°éÃǶ¼Äܹ»Ïëµ½£¬Ê¹ÓÃtry-finall´úÂë¿é°¡£¬½ÓÏÂÀ´£¬ÎÒÃÇΪϵ¥½Ó¿ÚµÄ·½·¨¼ÓÉÏtry-finally´úÂë¿é¡£
/**
* ΪÁËÑÝʾ·½±ã£¬ÎÒÕâÀï¾Í¼òµ¥¶¨ÒåÁËÒ»¸ö³£Á¿×÷ΪÉÌÆ·µÄid
* ʵ¼Ê¹¤×÷ÖУ¬Õâ¸öÉÌÆ·idÊÇǰ¶Ë½øÐÐϵ¥²Ù×÷´«µÝ¹ýÀ´µÄ²ÎÊý
*/
public static final String PRODUCT_ID = "100001"; @RequestMapping("/submitOrder")
public String submitOrder(){
//ͨ¹ýstringRedisTemplateÀ´µ÷ÓÃRedisµÄSETNXÃüÁkeyΪÉÌÆ·µÄid£¬valueΪ×Ö·û´®¡°binghe¡±
//ʵ¼ÊÉÏ£¬value¿ÉÒÔΪÈÎÒâµÄ×Ö·û»»
Boolean isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent (PRODUCT_ID,
"binghe");
//ûÓÐÄõ½Ëø£¬·µ»ØÏµ¥Ê§°Ü
if(!isLock){
return "failure";
}
try{
int stock = Integer.parseInt (stringRedisTemplate.opsForValue().get ("stock"));
if(stock > 0){
stock -= 1;
stringRedisTemplate.opsForValue().set ("stock",
String.valueOf(stock));
logger.debug("¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º{}", stock);
}else{
logger.debug("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
throw new OrderException("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
}
}finally{
//ÒµÎñÖ´ÐÐÍê³É£¬É¾³ýPRODUCT_ID key
stringRedisTemplate.delete (PRODUCT_ID);
}
return "success";
} |
ÄÇô£¬ÉÏÊö´úÂëÊÇ·ñÕæÕý½â¾öÁËËÀËøµÄÎÊÌâÄØ£¿ÎÒÃÇÔÚд´úÂëʱ£¬²»ÄÜÖ»¶¢×Å´úÂë±¾Éí£¬¾õµÃÉÏÊö´úÂëûɶÎÊÌâÁË¡£Êµ¼ÊÉÏ£¬Éú²ú»·¾³ÊǷdz£¸´Ôӵġ£Èç¹ûÏß³ÌÔڳɹ¦¼ÓËøÖ®ºó£¬Ö´ÐÐÒµÎñ´úÂëʱ£¬»¹Ã»À´µÃ¼°Ö´ÐÐɾ³ýËø±êÖ¾µÄ´úÂ룬´Ëʱ£¬·þÎñÆ÷å´»úÁË£¬³ÌÐò²¢Ã»ÓÐÓÅÑŵÄÍ˳öJVM¡£Ò²»áʹµÃºóÐøµÄÏ߳̽øÈëÌá½»¶©µ¥µÄ·½·¨Ê±£¬ÒòÎÞ·¨³É¹¦µÄÉèÖÃËø±ê־λ¶øÏµ¥Ê§°Ü¡£ËùÒÔ˵£¬ÉÏÊöµÄ´úÂëÈÔÈ»´æÔÚÎÊÌâ¡£
ÒýÈëRedis³¬Ê±»úÖÆ
ÔÚRedisÖпÉÒÔÉèÖûº´æµÄ×Ô¶¯¹ýÆÚʱ¼ä£¬ÎÒÃÇ¿ÉÒÔ½«ÆäÒýÈëµ½·Ö²¼Ê½ËøµÄʵÏÖÖУ¬ÈçÏ´úÂëËùʾ¡£
/**
* ΪÁËÑÝʾ·½±ã£¬ÎÒÕâÀï¾Í¼òµ¥¶¨ÒåÁËÒ»¸ö³£Á¿×÷ΪÉÌÆ·µÄid
* ʵ¼Ê¹¤×÷ÖУ¬Õâ¸öÉÌÆ·idÊÇǰ¶Ë½øÐÐϵ¥²Ù×÷´«µÝ¹ýÀ´µÄ²ÎÊý
*/
public static final String PRODUCT_ID = "100001"; @RequestMapping ("/submitOrder")
public String submitOrder(){
//ͨ¹ýstringRedisTemplateÀ´µ÷ÓÃRedisµÄSETNXÃüÁkeyΪÉÌÆ·µÄid£¬valueΪ×Ö·û´®¡°binghe¡±
//ʵ¼ÊÉÏ£¬value¿ÉÒÔΪÈÎÒâµÄ×Ö·û»»
Boolean isLocked = stringRedisTemplate.opsForValue().setIfAbsent(PRODUCT_ID,
"binghe");
//ûÓÐÄõ½Ëø£¬·µ»ØÏµ¥Ê§°Ü
if(!isLock){
return "failure";
}
try{
stringRedisTemplate.expire (PRODUCT_ID, 30, TimeUnit.SECONDS);
int stock = Integer.parseInt (stringRedisTemplate.opsForValue().get ("stock"));
if(stock > 0){
stock -= 1;
stringRedisTemplate.opsForValue().set ("stock",
String.valueOf(stock));
logger.debug("¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º{}", stock);
}else{
logger.debug("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
throw new OrderException("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
}
}finally{
//ÒµÎñÖ´ÐÐÍê³É£¬É¾³ýPRODUCT_ID key
stringRedisTemplate.delete (PRODUCT_ID);
}
return "success";
} |
ÔÚÉÏÊö´úÂëÖУ¬ÎÒÃǼÓÈëÁËÈçÏÂÒ»ÐдúÂëÀ´ÎªRedisÖеÄËø±êÖ¾ÉèÖùýÆÚʱ¼ä¡£
stringRedisTemplate.expire
(PRODUCT_ID, 30, TimeUnit.SECONDS);
|
´Ëʱ£¬ÎÒÃÇÉèÖõĹýÆÚʱ¼äΪ30Ãë¡£
ÄÇôÎÊÌâÀ´ÁË£¬ÕâÑùÊÇ·ñ¾ÍÕæÕýµÄ½â¾öÁËÎÊÌâÄØ£¿ÉÏÊö³ÌÐò¾ÍÕæµÄûÓпÓÁËÂ𣿴ð°¸ÊÇ»¹ÊÇÓпӵģ¡£¡
¡°¿Óλ¡±·ÖÎö
ÎÒÃÇÔÚϵ¥²Ù×÷µÄ·½·¨ÖÐΪ·Ö²¼Ê½ËøÒýÈëÁ˳¬Ê±»úÖÆ£¬´ËʱµÄ´úÂ뻹ÊÇÎÞ·¨ÕæÕý±ÜÃâËÀËøµÄÎÊÌ⣬ÄÇ¡°¿Óλ¡±µ½µ×ÔÚÄÄÀïÄØ£¿ÊÔÏ룬µ±³ÌÐòÖ´ÐÐÍêstringRedisTemplate.opsForValue(
).setIfAbsent()·½·¨ºó£¬ÕýÒªÖ´ÐÐstringRedisTemplate.expire
(PRODUCT_ID, 30, TimeUnit.SECONDS)´úÂëʱ£¬·þÎñÆ÷å´»úÁË£¬Ä㻹±ð˵£¬Éú²ú»µ¾³µÄÇé¿ö·Ç³£¸´ÔÓ£¬¾ÍÊÇÕâôÇÉ£¬·þÎñÆ÷¾Íå´»úÁË¡£´Ëʱ£¬ºóÐøÇëÇó½øÈëÌá½»¶©µ¥µÄ·½·¨Ê±£¬¶¼»áÒòΪÎÞ·¨³É¹¦ÉèÖÃËø±êÖ¾¶øµ¼ÖºóÐøÏµ¥Á÷³ÌÎÞ·¨Õý³£Ö´ÐС£
¼ÈÈ»ÎÒÃÇÕÒµ½ÁËÉÏÊö´úÂëµÄ¡°¿Óλ¡±£¬ÄÇÎÒÃÇÈçºÎ½«Õâ¸ö¡±¿Ó¡°ÌîÉÏ£¿ÈçºÎ½â¾öÕâ¸öÎÊÌâÄØ£¿±ð¼±£¬RedisÒѾÌṩÁËÕâÑùµÄ¹¦ÄÜ¡£ÎÒÃÇ¿ÉÒÔÔÚÏòRedisÖб£´æÊý¾ÝµÄʱºò£¬¿ÉÒÔͬʱָ¶¨Êý¾ÝµÄ³¬Ê±Ê±¼ä¡£ËùÒÔ£¬ÎÒÃÇ¿ÉÒÔ½«´úÂë¸ÄÔì³ÉÈçÏÂËùʾ¡£
/**
* ΪÁËÑÝʾ·½±ã£¬ÎÒÕâÀï¾Í¼òµ¥¶¨ÒåÁËÒ»¸ö³£Á¿×÷ΪÉÌÆ·µÄid
* ʵ¼Ê¹¤×÷ÖУ¬Õâ¸öÉÌÆ·idÊÇǰ¶Ë½øÐÐϵ¥²Ù×÷´«µÝ¹ýÀ´µÄ²ÎÊý
*/
public static final String PRODUCT_ID = "100001"; @RequestMapping("/submitOrder")
public String submitOrder(){
//ͨ¹ýstringRedisTemplateÀ´µ÷ÓÃRedisµÄSETNXÃüÁkeyΪÉÌÆ·µÄid£¬valueΪ×Ö·û´®¡°binghe¡±
//ʵ¼ÊÉÏ£¬value¿ÉÒÔΪÈÎÒâµÄ×Ö·û»»
Boolean isLocked = s tringRedisTemplate.opsForValue( ).setIfAbsent(PRODUCT_ID,
"binghe", 30, TimeUnit.SECONDS);
//ûÓÐÄõ½Ëø£¬·µ»ØÏµ¥Ê§°Ü
if(!isLock){
return "failure";
}
try{
int stock = Integer.parseInt (stringRedisTemplate.opsForValue( ).get("stock"));
if(stock > 0){
stock -= 1;
stringRedisTemplate.opsForValue( ).set("stock",
String.valueOf(stock));
logger.debug("¿â´æ¿Û¼õ³É¹¦£¬µ±Ç°¿â´æÎª£º{}", stock);
}else{
logger.debug("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
throw new OrderException("¿â´æ²»×㣬¿Û¼õ¿â´æÊ§°Ü");
}
}finally{
//ÒµÎñÖ´ÐÐÍê³É£¬É¾³ýPRODUCT_ID key
stringRedisTemplate.delete (PRODUCT_ID);
}
return "success";
} |
ÔÚÉÏÊö´úÂëÖУ¬ÎÒÃÇÔÚÏòRedisÖÐÉèÖÃËø±ê־λµÄʱºò¾ÍÉèÖÃÁ˳¬Ê±Ê±¼ä¡£´Ëʱ£¬Ö»ÒªÏòRedisÖгɹ¦ÉèÖÃÁËÊý¾Ý£¬Ôò¼´Ê¹ÎÒÃǵÄÒµÎñϵͳ崻ú£¬RedisÖеÄÊý¾Ý¹ýÆÚºó£¬Ò²»á×Ô¶¯É¾³ý¡£ºóÐøµÄÏ߳̽øÈëÌá½»¶©µ¥µÄ·½·¨ºó£¬¾Í»á³É¹¦µÄÉèÖÃËø±ê־룬²¢ÏòÏÂÖ´ÐÐÕý³£µÄϵ¥Á÷³Ì¡£
µ½´Ë£¬ÉÏÊöµÄ´úÂë»ù±¾ÉÏÔÚ¹¦ÄܽǶȽâ¾öÁ˳ÌÐòµÄËÀËøÎÊÌ⣬ÄÇô£¬ÉÏÊö³ÌÐòÕæµÄ¾ÍÍêÃÀÁËÂ𣿹þ¹þ£¬ºÜ¶àС»ï°é¿Ï¶¨»á˵²»ÍêÃÀ£¡È·Êµ£¬ÉÏÃæµÄ´úÂ뻹²»ÊÇÍêÃÀµÄ£¬ÄÇ´ó¼ÒÖªµÀÄÄÀï²»ÍêÃÀÂ𣿽ÓÏÂÀ´£¬ÎÒÃǼÌÐø·ÖÎö¡£
ÔÚ¿ª·¢¼¯³É½Ç¶È·ÖÎö´úÂë
ÔÚÎÒÃÇ¿ª·¢¹«¹²µÄϵͳ×é¼þʱ£¬±ÈÈçÎÒÃÇÕâÀï˵µÄ·Ö²¼Ê½Ëø£¬ÎÒÃǿ϶¨»á³éȡһЩ¹«¹²µÄÀàÀ´Íê³ÉÏàÓ¦µÄ¹¦ÄÜÀ´¹©ÏµÍ³Ê¹Óá£
ÕâÀ¼ÙÉèÎÒÃǶ¨ÒåÁËÒ»¸öRedisLock½Ó¿Ú£¬ÈçÏÂËùʾ¡£
public interface
RedisLock{
//¼ÓËø²Ù×÷
boolean tryLock (String key, long timeout, TimeUnit
unit);
//½âËø²Ù×÷
void releaseLock(String key);
}
|
½ÓÏÂÀ´£¬Ê¹ÓÃRedisLockImplÀàʵÏÖRedisLock½Ó¿Ú£¬Ìṩ¾ßÌåµÄ¼ÓËøºÍ½âËøÊµÏÖ£¬ÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
return stringRedisTemplate.opsForValue( ).setIfAbsent(key,
"binghe", timeout, unit);
}
@Override
public void releaseLock(String key){
stringRedisTemplate.delete(key);
}
} |
ÔÚ¿ª·¢¼¯³ÉµÄ½Ç¶ÈÀ´Ëµ£¬µ±Ò»¸öÏ̴߳ÓÉϵ½ÏÂÖ´ÐÐʱ£¬Ê×ÏȶԳÌÐò½øÐмÓËø²Ù×÷£¬È»ºóÖ´ÐÐÒµÎñ´úÂ룬ִÐÐÍê³Éºó£¬ÔÙ½øÐÐÊÍ·ÅËøµÄ²Ù×÷¡£ÀíÂÛÉÏ£¬¼ÓËøºÍÊÍ·ÅËøÊ±£¬²Ù×÷µÄRedis
Key¶¼ÊÇÒ»ÑùµÄ¡£µ«ÊÇ£¬Èç¹ûÆäËû¿ª·¢ÈËÔ±ÔÚ±àд´úÂëʱ£¬²¢Ã»Óе÷ÓÃtryLock()·½·¨£¬¶øÊÇÖ±½Óµ÷ÓÃÁËreleaseLock()·½·¨£¬²¢ÇÒËûµ÷ÓÃreleaseLock()·½·¨´«µÝµÄkeyÓëÄãµ÷ÓÃtryLock()·½·¨´«µÝµÄkeyÊÇÒ»ÑùµÄ¡£ÄÇ´Ëʱ¾Í»á³öÏÖÎÊÌâÁË£¬ËûÔÚ±àд´úÂëʱ£¬Ó²ÉúÉúµÄ½«Äã¼ÓµÄËøÊÍ·ÅÁË£¡£¡£¡
ËùÒÔ£¬ÉÏÊö´úÂëÊDz»°²È«µÄ£¬±ðÈËÄܹ»ËæËæ±ã±ãµÄ½«Äã¼ÓµÄËøÉ¾³ý£¬Õâ¾ÍÊÇËøµÄÎóɾ²Ù×÷£¬ÕâÊǷdz£Î£Ïյģ¬ËùÒÔ£¬ÉÏÊöµÄ³ÌÐò´æÔÚºÜÑÏÖØµÄÎÊÌ⣡£¡
ÄÇÈçºÎʵÏÖÖ»ÓмÓËøµÄÏ̲߳ÅÄܽøÐÐÏàÓ¦µÄ½âËø²Ù×÷ÄØ£¿ ¼ÌÐøÏòÏ¿´¡£
ÈçºÎʵÏÖ¼ÓËøºÍ½âËøµÄ¹éÒ»»¯£¿
ʲôÊǼÓËøºÍ½âËøµÄ¹éÒ»»¯ÄØ£¿¼òµ¥µãÀ´Ëµ£¬¾ÍÊÇÒ»¸öÏß³ÌÖ´ÐÐÁ˼ÓËø²Ù×÷ºó£¬ºóÐø±ØÐëÓÉÕâ¸öÏß³ÌÖ´ÐнâËø²Ù×÷£¬¼ÓËøºÍ½âËø²Ù×÷ÓÉͬһ¸öÏß³ÌÀ´Íê³É¡£
ΪÁ˽â¾öÖ»ÓмÓËøµÄÏ̲߳ÅÄܽøÐÐÏàÓ¦µÄ½âËø²Ù×÷µÄÎÊÌ⣬ÄÇô£¬ÎÒÃǾÍÐèÒª½«¼ÓËøºÍ½âËø²Ù×÷°ó¶¨µ½Í¬Ò»¸öÏß³ÌÖУ¬ÄÇô£¬ÈçºÎ½«¼ÓËø²Ù×÷ºÍ½âËø²Ù×÷°ó¶¨µ½Í¬Ò»¸öÏß³ÌÄØ£¿ÆäʵºÜ¼òµ¥£¬ÏàÐźܶàС»ï°é¶¼Ïëµ½ÁË¡ª¡ª
ʹÓÃThreadLocalʵÏÖ ¡£Ã»´í£¬Ê¹ÓÃThreadLocalÀàȷʵÄܹ»½â¾öÕâ¸öÎÊÌâ¡£
´Ëʱ£¬ÎÒÃǽ«RedisLockImplÀàµÄ´úÂëÐ޸ijÉÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
= new ThreadLocal<String>(); @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
return stringRedisTemplate.opsForValue( ).setIfAbsent (key,
uuid, timeout, unit);
}
@Override
public void releaseLock(String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if(threadLocal.get( ).equals(stringRedisTemplate.opsForValue(
).get(key))){
stringRedisTemplate.delete(key);
}
}
} |
ÉÏÊö´úÂëµÄÖ÷ÒªÂ߼Ϊ£ºÔÚ¶Ô³ÌÐòÖ´Ðг¢ÊÔ¼ÓËø²Ù×÷ʱ£¬Ê×ÏÈÉú³ÉÒ»¸öuuid£¬½«Éú³ÉµÄuuid°ó¶¨µ½µ±Ç°Ị̈߳¬²¢½«´«µÝµÄkey²ÎÊý²Ù×÷RedisÖеÄkey£¬Éú³ÉµÄuuid×÷ΪRedisÖеÄValue£¬±£´æµ½RedisÖУ¬Í¬Ê±ÉèÖó¬Ê±Ê±¼ä¡£µ±Ö´ÐнâËø²Ù×÷ʱ£¬Ê×ÏÈ£¬Åжϵ±Ç°Ïß³ÌÖа󶨵ÄuuidÊÇ·ñºÍRedisÖд洢µÄuuidÏàµÈ£¬Ö»ÓжþÕßÏàµÈʱ£¬²Å»áÖ´ÐÐɾ³ýËø±ê־λµÄ²Ù×÷¡£Õâ¾Í±ÜÃâÁËÒ»¸öÏ̶߳ԳÌÐò½øÐÐÁ˼ÓËø²Ù×÷ºó£¬ÆäËûÏ̶߳ÔÕâ¸öËø½øÐÐÁ˽âËø²Ù×÷µÄÎÊÌâ¡£
¼ÌÐø·ÖÎö
ÎÒÃǽ«¼ÓËøºÍ½âËøµÄ·½·¨¸Ä³ÉÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate;
private ThreadLocal<String> threadLocal
= new ThreadLocal<String>();
private String lockUUID;
@Override
public boolean tryLock(String key, long timeout,
TimeUnit unit){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
lockUUID = uuid;
return stringRedisTemplate.opsForValue( ).setIfAbsent (key,
uuid, timeout, unit);
}
@Override
public void releaseLock(String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if(lockUUID.equals (stringRedisTemplate.opsForValue( ).get(key))){
stringRedisTemplate.delete(key);
}
}
}
|
ÏàÐźܶàС»ï°é¶¼»á¿´³öÉÏÊö´úÂë´æÔÚʲôÎÊÌâÁË£¡£¡Ã»´í£¬ÄǾÍÊÇ Ḭ̈߳²È«µÄÎÊÌâ¡£
ËùÒÔ£¬ÕâÀÎÒÃÇÐèҪʹÓÃThreadLocalÀ´½â¾öḬ̈߳²È«ÎÊÌâ¡£
¿ÉÖØÈëÐÔ·ÖÎö
ÔÚÉÏÃæµÄ´úÂëÖУ¬µ±Ò»¸öÏ̳߳ɹ¦ÉèÖÃÁËËø±ê־λºó£¬ÆäËûµÄÏß³ÌÔÙÉèÖÃËø±ê־λʱ£¬¾Í»á·µ»ØÊ§°Ü¡£»¹ÓÐÒ»ÖÖ³¡¾°¾ÍÊÇÔÚÌá½»¶©µ¥µÄ½Ó¿Ú·½·¨ÖУ¬µ÷ÓÃÁË·þÎñA£¬·þÎñAµ÷ÓÃÁË·þÎñB£¬¶ø·þÎñBµÄ·½·¨ÖдæÔÚ¶Ôͬһ¸öÉÌÆ·µÄ¼ÓËøºÍ½âËø²Ù×÷¡£
ËùÒÔ£¬·þÎñB³É¹¦ÉèÖÃËø±ê־λºó£¬Ìá½»¶©µ¥µÄ½Ó¿Ú·½·¨¼ÌÐøÖ´ÐÐʱ£¬Ò²²»Äܳɹ¦ÉèÖÃËø±ê־λÁË¡£Ò²¾ÍÊÇ˵£¬Ä¿Ç°ÊµÏֵķֲ¼Ê½ËøÃ»ÓпÉÖØÈëÐÔ¡£
ÕâÀ¾Í´æÔÚ¿ÉÖØÈëÐÔµÄÎÊÌâÁË¡£ÎÒÃÇÏ£ÍûÉè¼ÆµÄ·Ö²¼Ê½Ëø ¾ßÓпÉÖØÈëÐÔ £¬ÄÇʲôÊÇ¿ÉÖØÈëÐÔÄØ£¿¼òµ¥µãÀ´Ëµ£¬¾ÍÊÇͬһ¸öỊ̈߳¬Äܹ»¶à´Î»ñȡͬһ°ÑËø£¬²¢ÇÒÄܹ»°´ÕÕ˳Ðò½øÐнâ¾ö²Ù×÷¡£
Æäʵ£¬ÔÚJDK 1.5Ö®ºóÌṩµÄËøºÜ¶à¶¼Ö§³Ö¿ÉÖØÈëÐÔ£¬±ÈÈçsynchronizedºÍLock¡£
ÈçºÎʵÏÖ¿ÉÖØÈëÐÔÄØ£¿
Ó³Éäµ½ÎÒÃǼÓËøºÍ½âËø·½·¨Ê±£¬ÎÒÃÇÈçºÎÖ§³Öͬһ¸öÏß³ÌÄܹ»¶à´Î»ñÈ¡µ½Ëø£¨ÉèÖÃËø±ê־λ£©ÄØ£¿¿ÉÒÔÕâÑù¼òµ¥µÄÉè¼Æ£ºÈç¹ûµ±Ç°Ïß³ÌûÓаó¶¨uuid£¬ÔòÉú³Éuuid°ó¶¨µ½µ±Ç°Ị̈߳¬²¢ÇÒÔÚRedisÖÐÉèÖÃËø±ê־λ¡£Èç¹ûµ±Ç°Ïß³ÌÒѾ°ó¶¨ÁËuuid£¬ÔòÖ±½Ó·µ»Øtrue£¬Ö¤Ã÷µ±Ç°Ïß³Ì֮ǰÒѾÉèÖÃÁËËø±ê־룬Ҳ¾ÍÊÇ˵ÒѾ»ñÈ¡µ½ÁËËø£¬Ö±½Ó·µ»Øtrue¡£
½áºÏÒÔÉÏ·ÖÎö£¬ÎÒÃǽ«Ìá½»¶©µ¥µÄ½Ó¿Ú·½·¨´úÂë¸ÄÔì³ÉÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
=
new ThreadLocal<String>(); @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
Boolean isLocked = false;
if(threadLocal.get() == null){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent(key,
uuid, timeout, unit);
}else{
isLocked = true;
}
return isLocked;
}
@Override
public void releaseLock (String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if (threadLocal.get().equals (stringRedisTemplate.opsForValue(
).get(key))){
stringRedisTemplate.delete(key);
}
}
} |
ÕâÑùд¿´ËÆÃ»ÓÐɶÎÊÌ⣬µ«ÊÇ´ó¼ÒϸÏëһϣ¬ÕâÑùд¾ÍÕæµÄOKÁËÂð£¿
¿ÉÖØÈëÐÔµÄÎÊÌâ·ÖÎö
¼ÈÈ»ÉÏÃæ·Ö²¼Ê½ËøµÄ¿ÉÖØÈëÐÔÊÇ´æÔÚÎÊÌâµÄ£¬ÄÇÎÒÃǾÍÀ´·ÖÎöÏÂÎÊÌâµÄ¸ùÔ´ÔÚÄÄÀ
¼ÙÉèÎÒÃÇÌá½»¶©µ¥µÄ·½·¨ÖУ¬Ê×ÏÈʹÓÃRedisLock½Ó¿Ú¶Ô´úÂë¿éÌí¼ÓÁË·Ö²¼Ê½Ëø£¬ÔÚ¼ÓËøºóµÄ´úÂëÖе÷ÓÃÁË·þÎñA£¬¶ø·þÎñAÖÐÒ²´æÔÚµ÷ÓÃRedisLock½Ó¿ÚµÄ¼ÓËøºÍ½âËø²Ù×÷¡£¶ø¶à´Îµ÷ÓÃRedisLock½Ó¿ÚµÄ¼ÓËø²Ù×÷ʱ£¬Ö»ÒªÖ®Ç°µÄËøÃ»ÓÐʧЧ£¬Ôò»áÖ±½Ó·µ»Øtrue£¬±íʾ³É¹¦»ñÈ¡Ëø¡£Ò²¾ÍÊÇ˵£¬ÎÞÂÛµ÷ÓüÓËø²Ù×÷¶àÉٴΣ¬×îÖÕÖ»»á³É¹¦¼ÓËøÒ»´Î¡£¶øÖ´ÐÐÍê·þÎñAÖеÄÂß¼ºó£¬ÔÚ·þÎñAÖе÷ÓÃRedisLock½Ó¿ÚµÄ½âËø·½·¨£¬´Ëʱ£¬»á½«µ±Ç°Ïß³ÌËùÓеļÓËø²Ù×÷»ñµÃµÄËøÈ«²¿Êͷŵô¡£
ÎÒÃÇ¿ÉÒÔʹÓÃÏÂͼÀ´¼òµ¥µÄ±íʾÕâ¸ö¹ý³Ì¡£

ÄÇôÎÊÌâÀ´ÁË£¬ÈçºÎ½â¾ö¿ÉÖØÈëÐÔµÄÎÊÌâÄØ£¿
½â¾ö¿ÉÖØÈëÐÔÎÊÌâ
ÏàÐźܶàС»ï°é¶¼Äܹ»Ïë³öʹÓüÆÊýÆ÷µÄ·½Ê½À´½â¾öÉÏÃæ¿ÉÖØÈëÐÔµÄÎÊÌ⣬û´í£¬¾ÍÊÇʹÓüÆÊýÆ÷À´½â¾ö¡£ ÕûÌåÁ÷³ÌÈçÏÂËùʾ¡£

ÄÇô£¬ÌåÏÖÔÚ³ÌÐò´úÂëÉÏÊÇʲôÑù×ÓÄØ£¿ÎÒÃÇÀ´ÐÞ¸ÄRedisLockImplÀàµÄ´úÂ룬ÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
= new ThreadLocal<String>(); private ThreadLocal< Integer> threadLocalInteger
= new ThreadLocal<Integer>(); @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
Boolean isLocked = false;
if(threadLocal.get() == null){
String uuid = UUID.randomUUID( ).toString();
threadLocal.set(uuid);
isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key,
uuid, timeout, unit);
}else{
isLocked = true;
}
//¼ÓËø³É¹¦ºó½«¼ÆÊýÆ÷¼Ó1
if(isLocked){
Integer count = threadLocalInteger.get() ==
null ? 0 : threadLocalInteger.get();
threadLocalInteger.set(count++);
}
return isLocked;
}
@Override
public void releaseLock (String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if(threadLocal.get().equals (stringRedisTemplate.opsForValue(
).get(key))){
Integer count = threadLocalInteger.get();
//¼ÆÊýÆ÷¼õΪ0ʱÊÍ·ÅËø
if(count == null || --count <= 0){
stringRedisTemplate.delete(key);
}
}
}
} |
ÖÁ´Ë£¬ÎÒÃÇ»ù±¾ÉϽâ¾öÁË·Ö²¼Ê½ËøµÄ¿ÉÖØÈëÐÔÎÊÌâ¡£
˵µ½ÕâÀÎÒ»¹ÒªÎÊ´ó¼ÒÒ»¾ä£¬ÉÏÃæµÄ½â¾öÎÊÌâµÄ·½°¸ÕæµÄûÎÊÌâÁËÂð£¿
×èÈûÓë·Ç×èÈûËø
ÔÚÌá½»¶©µ¥µÄ·½·¨ÖУ¬µ±»ñÈ¡Redis·Ö²¼Ê½ËøÊ§°Üʱ£¬ÎÒÃÇÖ±½Ó·µ»ØÁËfailureÀ´±íʾµ±Ç°ÇëÇóϵ¥µÄ²Ù×÷ʧ°ÜÁË¡£ÊÔÏ룬Ôڸ߲¢·¢»·¾³Ï£¬Ò»µ©Ä³¸öÇëÇó»ñµÃÁË·Ö²¼Ê½Ëø£¬ÄÇô£¬ÔÚÕâ¸öÇëÇóÊÍ·ÅËøÖ®Ç°£¬ÆäËûµÄÇëÇóµ÷ÓÃϵ¥·½·¨Ê±£¬¶¼»á·µ»ØÏµ¥Ê§°ÜµÄÐÅÏ¢¡£ÔÚÕæÊµ³¡¾°ÖУ¬ÕâÊǷdz£²»ÓѺõġ£ÎÒÃÇ¿ÉÒÔ½«ºóÐøµÄÇëÇó½øÐÐ×èÈû£¬Ö±µ½µ±Ç°ÇëÇóÊÍ·ÅËøºó£¬ÔÙ»½ÐÑ×èÈûµÄÇëÇó»ñµÃ·Ö²¼Ê½ËøÀ´Ö´Ðз½·¨¡£
ËùÒÔ£¬ÎÒÃÇÉè¼ÆµÄ·Ö²¼Ê½ËøÐèÒªÖ§³Ö ×èÈûºÍ·Ç×èÈû µÄÌØÐÔ¡£
ÄÇô£¬ÈçºÎʵÏÖ×èÈûÄØ£¿ÎÒÃÇ¿ÉÒÔʹÓÃ×ÔÐýÀ´ÊµÏÖ£¬¼ÌÐøÐÞ¸ÄRedisLockImplµÄ´úÂëÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
= new ThreadLocal<String>(); private ThreadLocal<Integer> threadLocalInteger
= new ThreadLocal<Integer>(); @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
Boolean isLocked = false;
if(threadLocal.get() == null){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent(key,
uuid, timeout, unit);
//Èç¹û»ñÈ¡ËøÊ§°Ü£¬Ôò×ÔÐý»ñÈ¡Ëø£¬Ö±µ½³É¹¦
if(!isLocked){
for(;;){
isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent(key,
uuid, timeout, unit);
if(isLocked){
break;
}
}
}
}else{
isLocked = true;
}
//¼ÓËø³É¹¦ºó½«¼ÆÊýÆ÷¼Ó1
if(isLocked){
Integer count = threadLocalInteger.get() ==
null ? 0 : threadLocalInteger.get();
threadLocalInteger.set(count++);
}
return isLocked;
}
@Override
public void releaseLock(String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if(threadLocal.get().equals (stringRedisTemplate.opsForValue().get(key))){
Integer count = threadLocalInteger.get();
//¼ÆÊýÆ÷¼õΪ0ʱÊÍ·ÅËø
if (count == null || --count <= 0){
stringRedisTemplate.delete(key);
}
}
}
} |
ÔÚ·Ö²¼Ê½ËøµÄÉè¼ÆÖУ¬×èÈûËøºÍ·Ç×èÈûËø ÊǷdz£ÖØÒªµÄ¸ÅÄ´ó¼ÒÒ»¶¨Òª¼ÇסÕâ¸ö֪ʶµã¡£
ËøÊ§Ð§ÎÊÌâ
¾¡¹ÜÎÒÃÇʵÏÖÁË·Ö²¼Ê½ËøµÄ×èÈûÌØÐÔ£¬µ«ÊÇ»¹ÓÐÒ»¸öÎÊÌâÊÇÎÒÃDz»µÃ²»¿¼Âǵġ£ÄǾÍÊÇ ËøÊ§Ð§ µÄÎÊÌâ¡£
µ±³ÌÐòÖ´ÐÐÒµÎñµÄʱ¼ä³¬¹ýÁËËøµÄ¹ýÆÚʱ¼ä»á·¢ÉúÊ²Ã´ÄØ£¿ Ïë±ØºÜ¶àС»ï°é¶¼Äܹ»Ïëµ½£¬ÄǾÍÊÇÇ°ÃæµÄÇëÇóûִÐÐÍê£¬Ëø¹ýÆÚʧЧÁË£¬ºóÃæµÄÇëÇó»ñÈ¡µ½·Ö²¼Ê½Ëø£¬¼ÌÐøÏòÏÂÖ´ÐÐÁË£¬³ÌÐòÎÞ·¨×öµ½ÕæÕýµÄ»¥³â£¬ÎÞ·¨±£Ö¤ÒµÎñµÄÔ×ÓÐÔÁË¡£
ÄÇÈçºÎ½â¾öÕâ¸öÎÊÌâÄØ£¿´ð°¸¾ÍÊÇ£ºÎÒÃDZØÐë±£Ö¤ÔÚÒµÎñ´úÂëÖ´ÐÐÍê±Ïºó£¬²ÅÄÜÊÍ·Å·Ö²¼Ê½Ëø¡£ ·½°¸ÊÇÓÐÁË£¬ÄÇÈçºÎʵÏÖÄØ£¿
˵°×ÁË£¬ÎÒÃÇÐèÒªÔÚÒµÎñ´úÂëÖУ¬Ê±²»Ê±µÄÖ´ÐÐÏÂÃæµÄ´úÂëÀ´±£Ö¤ÔÚÒµÎñ´úÂëûִÐÐÍêʱ£¬·Ö²¼Ê½Ëø²»»áÒò³¬Ê±¶ø±»ÊÍ·Å¡£
springRedisTemplate.expire(PRODUCT_ID,
30, TimeUnit.SECONDS);
|
ÕâÀÎÒÃÇÐèÒª¶¨ÒåÒ»¸ö¶¨Ê±²ßÂÔÀ´Ö´ÐÐÉÏÃæµÄ´úÂ룬ÐèҪעÒâµÄÊÇ£ºÎÒÃDz»Äܵȵ½30ÃëºóÔÙÖ´ÐÐÉÏÊö´úÂ룬ÒòΪ30Ãëʱ£¬ËøÒѾʧЧÁË¡£ÀýÈ磬ÎÒÃÇ¿ÉÒÔÿ10ÃëÖ´ÐÐÒ»´ÎÉÏÃæµÄ´úÂë¡£
ÓÐЩС»ï°é˵£¬Ö±½ÓÔÚRedisLockImplÀàÖÐÌí¼ÓÒ»¸öwhile(true)Ñ»·À´½â¾öÕâ¸öÎÊÌ⣬ÄÇÎÒÃǾÍÕâÑùÐÞ¸ÄÏÂRedisLockImplÀàµÄ´úÂ룬¿´¿´ÓÐûÓÐɶÎÊÌâ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
= new ThreadLocal<String>(); private ThreadLocal< Integer> threadLocalInteger
= new ThreadLocal<Integer>(); @Override
public boolean tryLock (String key, long timeout,
TimeUnit unit){
Boolean isLocked = false;
if(threadLocal.get() == null){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent(key,
uuid, timeout, unit);
//Èç¹û»ñÈ¡ËøÊ§°Ü£¬Ôò×ÔÐý»ñÈ¡Ëø£¬Ö±µ½³É¹¦
if(!isLocked){
for(;;){
isLocked = stringRedisTemplate.opsForValue( ).setIfAbsent(key,
uuid, timeout, unit);
if(isLocked){
break;
}
}
}
//¶¨Òå¸üÐÂËøµÄ¹ýÆÚʱ¼ä
while(true){
Integer count = threadLocalInteger.get();
//µ±Ç°ËøÒѾ±»ÊÍ·Å£¬ÔòÍ˳öÑ»·
if(count == 0 || count <= 0){
break;
}
springRedisTemplate.expire (key, 30, TimeUnit.SECONDS);
try{
//ÿ¸ô10ÃëÖ´ÐÐÒ»´Î
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}else{
isLocked = true;
}
//¼ÓËø³É¹¦ºó½«¼ÆÊýÆ÷¼Ó1
if(isLocked){
Integer count = threadLocalInteger.get( ) ==
null ? 0 : threadLocalInteger.get();
threadLocalInteger.set (count++);
}
return isLocked;
}
@Override
public void releaseLock (String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
if (threadLocal.get().equals (stringRedisTemplate.opsForValue().get(key))){
Integer count = threadLocalInteger.get();
//¼ÆÊýÆ÷¼õΪ0ʱÊÍ·ÅËø
if (count == null || --count <= 0){
stringRedisTemplate.delete( key);
}
}
}
} |
ÏàÐÅС»ï°éÃÇ¿´ÁË´úÂë¾Í»á·¢ÏÖÄÄÀïÓÐÎÊÌâÁË£º¸üÐÂËø¹ýÆÚʱ¼äµÄ´úÂë¿Ï¶¨²»ÄÜÕâôȥд¡£ÒòΪÕâôд»á µ¼Öµ±Ç°Ïß³ÌÔÚ¸üÐÂËø³¬Ê±Ê±¼äµÄwhile(true)Ñ»·ÖÐÒ»Ö±×èÈû¶øÎÞ·¨·µ»Ø½á¹û¡£
ËùÒÔ£¬ÎÒÃDz»Äܽ«µ±Ç°Ïß³Ì×èÈû£¬ÐèÒªÒì²½Ö´Ðж¨Ê±ÈÎÎñÀ´¸üÐÂËøµÄ¹ýÆÚʱ¼ä¡£
´Ëʱ£¬ÎÒÃǼÌÐøÐÞ¸ÄRedisLockImplÀàµÄ´úÂ룬½«¶¨Ê±¸üÐÂËø³¬Ê±µÄ´úÂë·Åµ½Ò»¸öµ¥¶ÀµÄÏß³ÌÖÐÖ´ÐУ¬ÈçÏÂËùʾ¡£
public class
RedisLockImpl implements RedisLock{
@Autowired
private StringRedisTemplate stringRedisTemplate; private ThreadLocal<String> threadLocal
= new ThreadLocal<String>(); private ThreadLocal<Integer> threadLocalInteger
= new ThreadLocal<Integer>(); @Override
public boolean tryLock(String key, long timeout,
TimeUnit unit){
Boolean isLocked = false;
if(threadLocal.get() == null){
String uuid = UUID.randomUUID().toString();
threadLocal.set(uuid);
isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key,
uuid, timeout, unit);
//Èç¹û»ñÈ¡ËøÊ§°Ü£¬Ôò×ÔÐý»ñÈ¡Ëø£¬Ö±µ½³É¹¦
if(!isLocked){
for(;;){
isLocked = stringRedisTemplate.opsForValue().setIfAbsent(key,
uuid, timeout, unit);
if(isLocked){
break;
}
}
}
//Æô¶¯ÐÂÏß³ÌÀ´Ö´Ðж¨Ê±ÈÎÎñ£¬¸üÐÂËø¹ýÆÚʱ¼ä
new Thread(new UpdateLockTimeoutTask(uuid, stringRedisTemplate)).start();
}else{
isLocked = true;
}
//¼ÓËø³É¹¦ºó½«¼ÆÊýÆ÷¼Ó1
if(isLocked){
Integer count = threadLocalInteger.get() ==
null ? 0 : threadLocalInteger.get();
threadLocalInteger.set (count++);
}
return isLocked;
}
@Override
public void releaseLock (String key){
//µ±Ç°Ïß³ÌÖа󶨵ÄuuidÓëRedisÖеÄuuidÏàͬʱ£¬ÔÙÖ´ÐÐɾ³ýËøµÄ²Ù×÷
String uuid = stringRedisTemplate.opsForValue( ).get(key);
if (threadLocal.get( ).equals(uuid)){
Integer count = threadLocalInteger.get();
//¼ÆÊýÆ÷¼õΪ0ʱÊÍ·ÅËø
if(count == null || --count <= 0){
stringRedisTemplate.delete (key);
//»ñÈ¡¸üÐÂËø³¬Ê±Ê±¼äµÄÏ̲߳¢ÖжÏ
long threadId = stringRedisTemplate.opsForValue( ).get(uuid);
Thread updateLockTimeoutThread = ThreadUtils.getThreadByThreadId (threadId);
if(updateLockTimeoutThread != null){
//ÖжϸüÐÂËø³¬Ê±Ê±¼äµÄÏß³Ì
updateLockTimeoutThread.interrupt();
stringRedisTemplate.delete(uuid);
}
}
}
}
} |
´´½¨UpdateLockTimeoutTaskÀàÀ´Ö´ÐиüÐÂËø³¬Ê±µÄʱ¼ä¡£
public class
UpdateLockTimeoutTask implements Runnable{
//uuid
private long uuid;
private StringRedisTemplate stringRedisTemplate;
public UpdateLockTimeoutTask (long uuid, StringRedisTemplate
stringRedisTemplate){
this.uuid = uuid;
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
public void run(){
//ÒÔuuidΪkey£¬µ±Ç°Ïß³ÌidΪvalue±£´æµ½RedisÖÐ
stringRedisTemplate.opsForValue( ).set(uuid,
Thread.currentThread( ).getId());
//¶¨Òå¸üÐÂËøµÄ¹ýÆÚʱ¼ä
while(true){
springRedisTemplate.expire (key, 30, TimeUnit.SECONDS);
try{
//ÿ¸ô10ÃëÖ´ÐÐÒ»´Î
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
|
½ÓÏÂÀ´£¬ÎÒÃǶ¨ÒåÒ»¸öThreadUtils¹¤¾ßÀ࣬Õâ¸ö¹¤¾ßÀàÖÐÓÐÒ»¸ö¸ù¾ÝÏß³Ìid»ñÈ¡Ï̵߳ķ½·¨getThreadByThreadId(long
threadId)¡£
public class
ThreadUtils{
//¸ù¾ÝÏß³Ìid»ñÈ¡Ï߳̾ä±ú
public static Thread getThreadByThreadId(long
threadId){
ThreadGroup group = Thread.currentThread().getThreadGroup();
while(group != null){
Thread[] threads = new Thread[(int)(group.activeCount()
* 1.2)];
int count = group.enumerate(threads, true);
for(int i = 0; i < count; i++){
if(threadId == threads[i].getId()){
return threads[i];
}
}
}
}
} |
ÉÏÊö½â¾ö·Ö²¼Ê½ËøÊ§Ð§µÄÎÊÌâÔÚ·Ö²¼Ê½ËøÁìÓòÓÐÒ»¸öרҵµÄÊõÓï½Ð×ö ¡°Òì²½ÐøÃü¡± ¡£ÐèҪעÒâµÄÊÇ£ºµ±ÒµÎñ´úÂëÖ´ÐÐÍê±Ïºó£¬ÎÒÃÇÐèҪֹͣ¸üÐÂËø³¬Ê±Ê±¼äµÄÏ̡߳£ËùÒÔ£¬ÕâÀÎÒ¶Ô³ÌÐòµÄ¸Ä¶¯ÊDZȽϴóµÄ£¬Ê×ÏÈ£¬½«¸üÐÂËø³¬Ê±µÄʱ¼äÈÎÎñÖØÐ¶¨ÒåΪһ¸öUpdateLockTimeoutTaskÀ࣬²¢½«uuidºÍStringRedisTemplate×¢Èëµ½ÈÎÎñÀàÖУ¬ÔÚÖ´Ðж¨Ê±¸üÐÂËø³¬Ê±Ê±¼äʱ£¬Ê×ÏȽ«µ±Ç°Ï̱߳£´æµ½RedisÖУ¬ÆäÖÐKeyΪ´«µÝ½øÀ´µÄuuid¡£
ÔÚÊ×ÏÈ»ñÈ¡·Ö²¼Ê½Ëøºó£¬ÖØÐÂÆô¶¯Ị̈߳¬²¢½«uuidºÍStringRedisTemplate´«µÝµ½ÈÎÎñÀàÖÐÖ´ÐÐÈÎÎñ¡£µ±ÒµÎñ´úÂëÖ´ÐÐÍê±Ïºó£¬µ÷ÓÃreleaseLock()·½·¨ÊÍ·ÅËøÊ±£¬ÎÒÃÇ»áͨ¹ýuuid´ÓRedisÖлñÈ¡¸üÐÂËø³¬Ê±Ê±¼äµÄÏß³Ìid£¬²¢Í¨¹ýÏß³Ìid»ñÈ¡µ½¸üÐÂËø³¬Ê±Ê±¼äµÄỊ̈߳¬µ÷ÓÃÏ̵߳Äinterrupt()·½·¨À´ÖжÏÏ̡߳£
´Ëʱ£¬µ±·Ö²¼Ê½ËøÊͷź󣬸üÐÂËø³¬Ê±µÄÏ߳̾ͻáÓÉÓÚÏß³ÌÖж϶øÍ˳öÁË¡£
ʵÏÖ·Ö²¼Ê½ËøµÄ»ù±¾ÒªÇó
½áºÏÉÏÊöµÄ°¸Àý£¬ÎÒÃÇ¿ÉÒԵóöʵÏÖ·Ö²¼Ê½ËøµÄ»ù±¾ÒªÇó£º
Ö§³Ö»¥³âÐÔ
Ö§³ÖËø³¬Ê±
Ö§³Ö×èÈûºÍ·Ç×èÈûÌØÐÔ
Ö§³Ö¿ÉÖØÈëÐÔ
Ö§³Ö¸ß¿ÉÓÃ
ͨÓ÷ֲ¼Ê½½â¾ö·½°¸
ÔÚ»¥ÁªÍøÐÐÒµ£¬·Ö²¼Ê½ËøÊÇÒ»¸öÈÆ²»¿ªµÄ»°Ì⣬ͬʱ£¬Ò²ÓкܶàͨÓõķֲ¼Ê½Ëø½â¾ö·½°¸£¬ÆäÖУ¬ÓõıȽ϶àµÄÒ»ÖÖ·½°¸¾ÍÊÇʹÓÿªÔ´µÄRedisson¿ò¼ÜÀ´½â¾ö·Ö²¼Ê½ËøÎÊÌâ¡£
ÓйØRedisson·Ö²¼Ê½ËøµÄʹÓ÷½°¸´ó¼Ò¿ÉÒԲο¼¡¶¡¾¸ß²¢·¢¡¿ÄãÖªµÀÂ𣿴ó¼Ò¶¼ÔÚʹÓÃRedissonʵÏÖ·Ö²¼Ê½ËøÁË£¡£¡¡·
¼ÈÈ»Redisson¿ò¼ÜÒѾºÜÅ£±ÆÁË£¬ÎÒÃÇÖ±½ÓʹÓÃRedisson¿ò¼ÜÊÇ·ñÄܹ»100%µÄ±£Ö¤·Ö²¼Ê½Ëø²»³öÎÊÌâÄØ£¿´ð°¸ÊÇÎÞ·¨100%µÄ±£Ö¤¡£ÒòΪÔÚ·Ö²¼Ê½ÁìÓòûÓÐÄÄÒ»¼Ò¹«Ë¾»òÕ߼ܹ¹Ê¦Äܹ»±£Ö¤100%µÄ²»³öÎÊÌ⣬¾ÍÁ¬°¢ÀïÕâÑùµÄ´ó¹«Ë¾¡¢°¢ÀïµÄÊ×ϯ¼Ü¹¹Ê¦ÕâÑùµÄ¼¼Êõ´óÅ£Ò²²»¸Ò±£Ö¤100%µÄ²»³öÎÊÌâ¡£
ÔÚ·Ö²¼Ê½ÁìÓò£¬ÎÞ·¨×öµ½100%ÎÞ¹ÊÕÏ£¬ÎÒÃÇ×·ÇóµÄÊǼ¸¸ö9µÄÄ¿±ê£¬ÀýÈç99.999%ÎÞ¹ÊÕÏ¡£
CAPÀíÂÛ
ÔÚ·Ö²¼Ê½ÁìÓò£¬ÓÐÒ»¸ö·Ç³£ÖØÒªµÄÀíÂÛ½Ð×öCAPÀíÂÛ¡£
C£ºConsistency£¨Ò»ÖÂÐÔ£©
A£ºAvailability£¨¿ÉÓÃÐÔ£©
P£ºPartition tolerance£¨·ÖÇøÈÝ´íÐÔ£©
ÔÚ·Ö²¼Ê½ÁìÓòÖУ¬ÊDZØÐëÒª±£Ö¤·ÖÇøÈÝ´íÐԵģ¬Ò²¾ÍÊDZØÐëÒª±£Ö¤¡°P¡±£¬ËùÒÔ£¬ÎÒÃÇÖ»Äܱ£Ö¤CP»òÕßAP¡£
ÕâÀÎÒÃÇ¿ÉÒÔʹÓÃRedisºÍZookeeperÀ´½øÐмòµ¥µÄ¶Ô±È£¬ÎÒÃÇ¿ÉÒÔʹÓÃRedisʵÏÖAP¼Ü¹¹µÄ·Ö²¼Ê½Ëø£¬Ê¹ÓÃZookeeperʵÏÖCP¼Ü¹¹µÄ·Ö²¼Ê½Ëø¡£
»ùÓÚRedisµÄAP¼Ü¹¹µÄ·Ö²¼Ê½ËøÄ£ÐÍ

ÔÚ»ùÓÚRedisʵÏÖµÄAP¼Ü¹¹µÄ·Ö²¼Ê½ËøÄ£ÐÍÖУ¬ÏòRedis½Úµã1дÈëÊý¾Ýºó£¬»áÁ¢¼´·µ»Ø½á¹û£¬Ö®ºóÔÚRedisÖлáÒÔÒì²½µÄ·½Ê½À´Í¬²½Êý¾Ý¡£
»ùÓÚZookeeperµÄCP¼Ü¹¹µÄ·Ö²¼Ê½ËøÄ£ÐÍ

ÔÚ»ùÓÚZookeeperʵÏÖµÄCP¼Ü¹¹µÄ·Ö²¼Ê½Ä£ÐÍÖУ¬Ïò½Úµã1дÈëÊý¾Ýºó£¬»áµÈ´ýÊý¾ÝµÄͬ²½½á¹û£¬µ±Êý¾ÝÔÚ´ó¶àÊýZookeeper½Úµã¼äͬ²½³É¹¦ºó£¬²Å»á·µ»Ø½á¹ûÊý¾Ý¡£
µ±ÎÒÃÇʹÓûùÓÚRedisµÄAP¼Ü¹¹ÊµÏÖ·Ö²¼Ê½ËøÊ±£¬ÐèҪעÒâÒ»¸öÎÊÌ⣬Õâ¸öÎÊÌâ¿ÉÒÔʹÓÃÏÂͼÀ´±íʾ¡£

Ò²¾ÍÊÇRedisÖ÷´Ó½ÚµãÖ®¼äµÄÊý¾Ýͬ²½Ê§°Ü£¬¼ÙÉèÏß³ÌÏòMaster½ÚµãдÈëÁËÊý¾Ý£¬¶øRedisÖÐMaster½ÚµãÏòSlave½Úµãͬ²½Êý¾Ýʧ°ÜÁË¡£´Ëʱ£¬ÁíÒ»¸öÏ̶߳ÁÈ¡µÄSlave½ÚµãÖеÄÊý¾Ý£¬·¢ÏÖûÓÐÌí¼Ó·Ö²¼Ê½Ëø£¬´Ëʱ¾Í»á³öÏÖÎÊÌâÁË£¡£¡£¡
ËùÒÔ£¬ÔÚÉè¼Æ·Ö²¼Ê½Ëø·½°¸Ê±£¬Ò²ÐèҪעÒâRedis½ÚµãÖ®¼äµÄÊý¾Ýͬ²½ÎÊÌâ¡£
ºìËøµÄʵÏÖ
ÔÚRedisson¿ò¼ÜÖУ¬ÊµÏÖÁ˺ìËøµÄ»úÖÆ£¬RedissonµÄRedissonRedLock¶ÔÏóʵÏÖÁËRedlock½éÉܵļÓËøËã·¨¡£¸Ã¶ÔÏóÒ²¿ÉÒÔÓÃÀ´½«¶à¸öRLock¶ÔÏó¹ØÁªÎªÒ»¸öºìËø£¬Ã¿¸öRLock¶ÔÏóʵÀý¿ÉÒÔÀ´×ÔÓÚ²»Í¬µÄRedissonʵÀý¡£µ±ºìËøÖг¬¹ý°ëÊýµÄRLock¼ÓËø³É¹¦ºó£¬²Å»áÈÏΪ¼ÓËøÊdzɹ¦µÄ£¬Õâ¾ÍÌá¸ßÁË·Ö²¼Ê½ËøµÄ¸ß¿ÉÓá£
ÎÒÃÇ¿ÉÒÔʹÓÃRedisson¿ò¼ÜÀ´ÊµÏÖºìËø¡£
public void
testRedLock (RedissonClient redisson1,RedissonClient
redisson2, RedissonClient redisson3){
RLock lock1 = redisson1.getLock ("lock1");
RLock lock2 = redisson2.getLock ("lock2");
RLock lock3 = redisson3.getLock ("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1,
lock2, lock3);
try {
// ͬʱ¼ÓËø£ºlock1 lock2 lock3, ºìËøÔڴ󲿷ֽڵãÉϼÓËø³É¹¦¾ÍËã³É¹¦¡£
lock.lock();
// ³¢ÊÔ¼ÓËø£¬×î¶àµÈ´ý100Ã룬ÉÏËøÒÔºó10Ãë×Ô¶¯½âËø
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} |
Æäʵ£¬ÔÚʵ¼Ê³¡¾°ÖУ¬ºìËøÊǺÜÉÙʹÓõġ£ÕâÊÇÒòΪʹÓÃÁ˺ìËøºó»áÓ°Ïì¸ß²¢·¢»·¾³ÏµÄÐÔÄÜ£¬Ê¹µÃ³ÌÐòµÄÌåÑé¸ü²î¡£ËùÒÔ£¬ÔÚʵ¼Ê³¡¾°ÖУ¬ÎÒÃÇÒ»°ã¶¼ÊÇÒª±£Ö¤Redis¼¯ÈºµÄ¿É¿¿ÐÔ¡£Í¬Ê±£¬Ê¹ÓúìËøºó£¬µ±¼ÓËø³É¹¦µÄRLock¸öÊý²»³¬¹ý×ÜÊýµÄÒ»°ëʱ£¬»á·µ»Ø¼ÓËøÊ§°Ü£¬¼´Ê¹ÔÚÒµÎñ²ãÃæÈÎÎñ¼ÓËø³É¹¦ÁË£¬µ«ÊǺìËøÒ²»á·µ»Ø¼ÓËøÊ§°ÜµÄ½á¹û¡£ÁíÍ⣬ʹÓúìËøÊ±£¬ÐèÒªÌṩ¶àÌ×RedisµÄÖ÷´Ó²¿Êð¼Ü¹¹£¬Í¬Ê±£¬Õâ¶àÌ×RedisÖ÷´Ó¼Ü¹¹ÖеÄMaster½Úµã±ØÐë¶¼ÊǶÀÁ¢µÄ£¬Ï໥֮¼äûÓÐÈκÎÊý¾Ý½»»¥¡£
¸ß²¢·¢¡°ºÚ¿Æ¼¼¡±ÓëÖÂÊ¤ÆæÕÐ
¼ÙÉ裬ÎÒÃǾÍÊÇʹÓÃRedisÀ´ÊµÏÖ·Ö²¼Ê½Ëø£¬¼ÙÉèRedisµÄ¶Áд²¢·¢Á¿ÔÚ5Íò×óÓÒ¡£ÎÒÃǵÄÉ̳ÇÒµÎñÐèÒªÖ§³ÖµÄ²¢·¢Á¿ÔÚ100Íò×óÓÒ¡£Èç¹ûÕâ100ÍòµÄ²¢·¢È«²¿´òÈëRedisÖУ¬RedisºÜ¿ÉÄܾͻá¹Òµô£¬ÄÇô£¬ÎÒÃÇÈçºÎ½â¾öÕâ¸öÎÊÌâÄØ£¿½ÓÏÂÀ´£¬ÎÒÃǾÍÒ»ÆðÀ´Ì½ÌÖÕâ¸öÎÊÌâ¡£
Ôڸ߲¢·¢µÄÉ̳ÇϵͳÖУ¬Èç¹û²ÉÓÃRedis»º´æÊý¾Ý£¬ÔòRedis»º´æµÄ²¢·¢´¦ÀíÄÜÁ¦Êǹؼü£¬ÒòΪºÜ¶àµÄǰ׺²Ù×÷¶¼ÐèÒª·ÃÎÊRedis¡£¶øÒì²½Ï÷·åÖ»ÊÇ»ù±¾µÄ²Ù×÷£¬¹Ø¼ü»¹ÊÇÒª±£Ö¤RedisµÄ²¢·¢´¦ÀíÄÜÁ¦¡£
½â¾öÕâ¸öÎÊÌâµÄ¹Ø¼ü˼Ïë¾ÍÊÇ£º·Ö¶øÖÎÖ®£¬½«ÉÌÆ·¿â´æ·Ö¿ª·Å¡£
°µ¶È³Â²Ö
ÎÒÃÇÔÚRedisÖд洢ÉÌÆ·µÄ¿â´æÊýÁ¿Ê±£¬¿ÉÒÔ½«ÉÌÆ·µÄ¿â´æ½øÐС°·Ö¸î¡±´æ´¢À´ÌáÉýRedisµÄ¶Áд²¢·¢Á¿¡£
ÀýÈ磬ÔÀ´µÄÉÌÆ·µÄidΪ10001£¬¿â´æÎª1000¼þ£¬ÔÚRedisÖеĴ洢Ϊ(10001, 1000)£¬ÎÒÃǽ«ÔÓÐµÄ¿â´æ·Ö¸îΪ5·Ý£¬Ôòÿ·ÝµÄ¿â´æÎª200¼þ£¬´Ëʱ£¬ÎÒÃÇÔÚRediaÖд洢µÄÐÅϢΪ(10001_0,
200)£¬(10001_1, 200)£¬(10001_2, 200)£¬(10001_3, 200)£¬(10001_4,
200)¡£

´Ëʱ£¬ÎÒÃǽ«¿â´æ½øÐзָîºó£¬Ã¿¸ö·Ö¸îºóµÄ¿â´æÊ¹ÓÃÉÌÆ·id¼ÓÉÏÒ»¸öÊý×Ö±êʶÀ´´æ´¢£¬ÕâÑù£¬ÔÚ¶Ô´æ´¢ÉÌÆ·¿â´æµÄÿ¸öKey½øÐÐHashÔËËãʱ£¬µÃ³öµÄHash½á¹ûÊDz»Í¬µÄ£¬Õâ¾Í˵Ã÷£¬´æ´¢ÉÌÆ·¿â´æµÄKeyÓкܴó¸ÅÂʲ»ÔÚRedisµÄͬһ¸ö²ÛλÖУ¬Õâ¾ÍÄܹ»ÌáÉýRedis´¦ÀíÇëÇóµÄÐÔÄܺͲ¢·¢Á¿¡£
·Ö¸î¿â´æºó£¬ÎÒÃÇ»¹ÐèÒªÔÚRedisÖд洢һ·ÝÉÌÆ·idºÍ·Ö¸î¿â´æºóµÄKeyµÄÓ³Éä¹ØÏµ£¬´ËʱӳÉä¹ØÏµµÄKeyΪÉÌÆ·µÄid£¬Ò²¾ÍÊÇ10001£¬ValueΪ·Ö¸î¿â´æºó´æ´¢¿â´æÐÅÏ¢µÄKey£¬Ò²¾ÍÊÇ10001_0£¬10001_1£¬10001_2£¬10001_3£¬10001_4¡£ÔÚRedisÖÐÎÒÃÇ¿ÉÒÔʹÓÃListÀ´´æ´¢ÕâЩֵ¡£
ÔÚÕæÕý´¦Àí¿â´æÐÅϢʱ£¬ÎÒÃÇ¿ÉÒÔÏÈ´ÓRedisÖвéѯ³öÉÌÆ·¶ÔÓ¦µÄ·Ö¸î¿â´æºóµÄËùÓÐKey£¬Í¬Ê±Ê¹ÓÃAtomicLongÀ´¼Ç¼µ±Ç°µÄÇëÇóÊýÁ¿£¬Ê¹ÓÃÇëÇóÊýÁ¿¶Ô´ÓRediaÖвéѯ³öµÄÉÌÆ·¶ÔÓ¦µÄ·Ö¸î¿â´æºóµÄËùÓÐKeyµÄ³¤¶È½øÐÐÇóÄ£ÔËË㣬µÃ³öµÄ½á¹ûΪ0£¬1£¬2£¬3£¬4¡£ÔÙÔÚÇ°ÃæÆ´½ÓÉÏÉÌÆ·id¾Í¿ÉÒԵóöÕæÕýµÄ¿â´æ»º´æµÄKey¡£´Ëʱ£¬¾Í¿ÉÒÔ¸ù¾ÝÕâ¸öKeyÖ±½Óµ½RedisÖлñÈ¡ÏàÓ¦µÄ¿â´æÐÅÏ¢¡£
ͬʱ£¬ÎÒÃÇ¿ÉÒÔ½«·Ö¸ôµÄ²»Í¬µÄ¿â´æÊý¾Ý·Ö±ð´æ´¢µ½²»Í¬µÄRedis·þÎñÆ÷ÖУ¬½øÒ»²½ÌáÉýRedisµÄ²¢·¢Á¿¡£
ÒÆ»¨½Óľ
Ôڸ߲¢·¢ÒµÎñ³¡¾°ÖУ¬ÎÒÃÇ¿ÉÒÔÖ±½ÓʹÓÃLua½Å±¾¿â£¨OpenResty£©´Ó¸ºÔؾùºâ²ãÖ±½Ó·ÃÎÊ»º´æ¡£
ÕâÀÎÒÃÇ˼¿¼Ò»¸ö³¡¾°£ºÈç¹ûÔڸ߲¢·¢ÒµÎñ³¡¾°ÖУ¬ÉÌÆ·±»Ë²¼äÇÀ¹ºÒ»¿Õ¡£´Ëʱ£¬Óû§ÔÙ·¢ÆðÇëÇóʱ£¬Èç¹ûϵͳÓɸºÔؾùºâ²ãÇëÇóÓ¦ÓòãµÄ¸÷¸ö·þÎñ£¬ÔÙÓÉÓ¦ÓòãµÄ¸÷¸ö·þÎñ·ÃÎÊ»º´æºÍÊý¾Ý¿â£¬Æäʵ£¬±¾ÖÊÉÏÒѾûÓÐÈκÎÒâÒåÁË£¬ÒòΪÉÌÆ·ÒѾÂôÍêÁË£¬ÔÙͨ¹ýϵͳµÄÓ¦ÓÃ²ã½øÐвã²ãУÑéÒѾûÓÐÌ«¶àÒâÒåÁË£¡£¡¶øÓ¦ÓòãµÄ²¢·¢·ÃÎÊÁ¿ÊÇÒÔ°ÙΪµ¥Î»µÄ£¬ÕâÓÖÔÚÒ»¶¨³Ì¶ÈÉϻήµÍϵͳµÄ²¢·¢¶È¡£
ΪÁ˽â¾öÕâ¸öÎÊÌ⣬´Ëʱ£¬ÎÒÃÇ¿ÉÒÔÔÚϵͳµÄ¸ºÔؾùºâ²ãÈ¡³öÓû§·¢ËÍÇëÇóʱЯ´øµÄÓû§id£¬ÉÌÆ·idºÍ»î¶¯idµÈÐÅÏ¢£¬Ö±½Óͨ¹ýLua½Å±¾µÈ¼¼ÊõÀ´·ÃÎÊ»º´æÖÐµÄ¿â´æÐÅÏ¢¡£Èç¹ûÉÌÆ·µÄ¿â´æÐ¡ÓÚ»òÕßµÈÓÚ0£¬ÔòÖ±½Ó·µ»ØÓû§ÉÌÆ·ÒÑÊÛÍêµÄÌáʾÐÅÏ¢£¬¶ø²»ÓÃÔÙ¾¹ýÓ¦ÓòãµÄ²ã²ãУÑéÁË¡£
|