免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
緩存對(duì)事務(wù)的支持



本文節(jié)選自即將出版的《可伸縮服務(wù)架構(gòu):框架與中間件》一書,作者:李艷鵬、楊彪、李海亮、賈博巖、劉淏。


- 點(diǎn)擊文末原文鏈接可以直達(dá)《可伸縮服務(wù)架構(gòu):框架與中間件》書籍主頁。


在使用Redis緩存的業(yè)務(wù)場(chǎng)景時(shí)經(jīng)常會(huì)有這樣的需求:要求遞減一個(gè)變量,如果遞減后變量小于等于0,則返回一個(gè)標(biāo)志;如果成功,則返回剩余的值,類似于數(shù)據(jù)庫事務(wù)的實(shí)現(xiàn)。


在實(shí)現(xiàn)中需要注意服務(wù)器端的多線程問題及客戶端的多線程問題。在服務(wù)器端可以利用服務(wù)器單線程執(zhí)行LUA腳本來保證,或者通過WATCH、EXEC、DISCARD、EXEC來保證。


Redis中支持LUA腳本,由于Redis使用單線程實(shí)現(xiàn),因此我們首先給出LUA腳本的實(shí)現(xiàn)方案。在如下代碼中,我們看到變量被遞減,并判斷是否將小于0的操作放到LUA腳本里,利用Redis的單線程執(zhí)行的特性完成這個(gè)原子遞減的操作:

/**
* Implemented by LUA. Minus a key by a value, then return the left value.
* If the left value is less than 0, return -1; if error, return -1.
*
* @param key
*            the key of the redis variable.
* @param value
*            the value to minus off.
* @return the value left after minus. If it is less than 0, return -1; if
*         error, return -1.
*/

public long decrByUntil0Lua(String key, long value) {
   // If any error, return -1.
   if (value <=>0)
       return -1;

   // The logic is implemented in LUA script which is run in server thread,
   // which is single thread in one server.
   String script = ' local leftvalue = redis.call('get', KEYS[1]); '
           + ' if ARGV[1] - leftvalue > 0 then return nil; else '
           + ' return redis.call('decrby', KEYS[1], ARGV[1]); end; ';

   Long leftValue = (Long) jedis.eval(script, 1, key, '' + value);

   // If the left value is less than 0, return -1.
   if (leftValue == null)
       return -1;

   return leftValue;
}

還可以通過Redis對(duì)事務(wù)的支持方法watchmulti來實(shí)現(xiàn),類似于一個(gè)CAS方法的實(shí)現(xiàn),如果對(duì)熱數(shù)據(jù)有競(jìng)爭(zhēng),則會(huì)返回失敗,然后重試直到成功:

/**
* Implemented by CAS. Minus a key by a value, then return the left value.
* If the left value is less than 0, return -1; if error, return -1.
*
* No synchronization, because redis client is not shared among multiple
* threads.
*
* @param key
*            the key of the redis variable.
* @param value
*            the value to minus off.
* @return the value left after minus. If it is less than 0, return -1; if
*         error, return -1.
*/

public long decrByUntil0Cas(String key, long value) {
   // If any error, return -1.
   if (value <=>0)
       return -1;

   // Start the CAS operations.
   jedis.watch(key);

   // Start the transation.
   Transaction tx = jedis.multi();

   // Decide if the left value is less than 0, if no, terminate the
   // transation, return -1;
   String curr = tx.get(key).get();
   if (Long.valueOf(curr) - value <>0) {
       tx.discard();
       return -1;
   }

   // Minus the key by the value
   tx.decrBy(key, value);

   // Execute the transaction and then handle the result
   List result = tx.exec();

   // If error, return -1;
   if (result == null || result.isEmpty()) {
       return -1;
   }

   // Extract the first result
   for (Object rt : result) {
       return Long.valueOf(rt.toString());
   }

   // The program never comes here.
   return -1;
}

END


本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Redis集群 Java客戶端Jedis的使用
spring boot下JedisCluster方式連接Redis集群的配置
Redis整合Spring結(jié)合使用緩存實(shí)例
java架構(gòu)師-技術(shù)專家-練習(xí)手冊(cè)-第07周 分布式redis
用kafka和redis實(shí)現(xiàn)一個(gè)推送消息功能
Redis簡(jiǎn)介
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服