這期內(nèi)容當中小編將會給大家?guī)碛嘘P(guān)redis實現(xiàn)分布式鎖的原理,以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都網(wǎng)站建設(shè)公司更懂你!創(chuàng)新互聯(lián)建站只做搜索引擎喜歡的網(wǎng)站!成都網(wǎng)站制作前臺采用搜索引擎認可的DIV+CSS架構(gòu),全站HTML靜態(tài),H5頁面制作+CSS3網(wǎng)站,提供:網(wǎng)站建設(shè),微信開發(fā),小程序開發(fā),成都做商城網(wǎng)站,成都App定制開發(fā),國際域名空間,服務(wù)器租售,網(wǎng)站代托管運營,微信公眾號代托管運營。
分布式鎖,是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。
在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動作。如果不同的系統(tǒng)或是同一個系統(tǒng)的不同主機之間共享了一個或一組資源,那么訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分布式鎖。
使用setnx、getset、expire、del這4個redis命令實現(xiàn)
setnx 是『SET if Not eXists』(如果不存在,則 SET)的簡寫。 命令格式:SETNX key value;使用:只在鍵 key 不存在的情況下,將鍵 key 的值設(shè)置為 value 。若鍵 key 已經(jīng)存在, 則 SETNX 命令不做任何動作。返回值:命令在設(shè)置成功時返回 1 ,設(shè)置失敗時返回 0 。
getset 命令格式:GETSET key value,將鍵 key 的值設(shè)為 value ,并返回鍵 key 在被設(shè)置之前的舊的value。返回值:如果鍵 key 沒有舊值, 也即是說, 鍵 key 在被設(shè)置之前并不存在, 那么命令返回 nil 。當鍵 key 存在但不是字符串類型時,命令返回一個錯誤。
expire 命令格式:EXPIRE key seconds,使用:為給定 key 設(shè)置生存時間,當 key 過期時(生存時間為 0 ),它會被自動刪除。返回值:設(shè)置成功返回 1 。 當 key 不存在或者不能為 key 設(shè)置生存時間時(比如在低于 2.1.3 版本的 Redis 中你嘗試更新 key 的生存時間),返回 0 。
del 命令格式:DEL key [key …],使用:刪除給定的一個或多個 key ,不存在的 key 會被忽略。返回值:被刪除 key 的數(shù)量。
Redis實現(xiàn)分布式鎖的原理:
1.通過setnx(lock_timeout)實現(xiàn),如果設(shè)置了鎖返回1, 已經(jīng)有值沒有設(shè)置成功返回0
2.死鎖問題:通過實踐來判斷是否過期,如果已經(jīng)過期,獲取到過期時間get(lockKey),然后getset(lock_timeout)判斷是否和get相同,相同則證明已經(jīng)加鎖成功,因為可能導(dǎo)致多線程同時執(zhí)行g(shù)etset(lock_timeout)方法,這可能導(dǎo)致多線程都只需getset后,對于判斷加鎖成功的線程, 再加expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS)過期時間,防止多個線程同時疊加時間,導(dǎo)致鎖時效時間翻倍
代碼:
/** * @author yaoxin * @date 2018/8/13下午5:04 */ public class RedisLockTest { public static final String url = "jdbc:MySQL://127.0.0.1:3306/ly?characterEncoding=UTF-8"; public static final String name = "com.mysql.jdbc.Driver"; public static final String user = "root"; public static final String password = ""; public static void main(String[] args) { Integer count = 50; while (count > 0) { count--; new Thread(new Runnable() { @Override public void run() { Jedis jedis = new Jedis("127.0.0.1", 6379); jedis.auth("1234"); String lock = lock(jedis); if (lock != null) { Statement statement = null; Connection conn = null; ResultSet resultSet = null; try { Class.forName(name);// 指定連接類型 conn = DriverManager.getConnection(url, user, password);// 獲取連接 statement = conn.createStatement();// 準備執(zhí)行語句 String querySql = "SELECT id,name,count FROM production WHERE id=2"; resultSet = statement.executeQuery(querySql); int count = 0; while (resultSet.next()) { System.out.println(Thread.currentThread().getName() + "搶到了鎖 id: " + resultSet.getString("id") + " name: " + resultSet.getString("name") + " count: " + resultSet.getString("count")); count = Integer.valueOf(resultSet.getString("count")); } String updateSql = "UPDATE production SET count=" + (count - 1) + " WHERE id=2"; int rows = statement.executeUpdate(updateSql); if (rows > 0) { System.out.println("更新成功" + Thread.currentThread().getName() + " 庫存剩余:" + (count - 1)); System.out.println(Thread.currentThread().getName() + " === > >開始解鎖"); boolean unlock = unlock(jedis, lock); if (unlock) System.out.println(Thread.currentThread().getName() + " === > >解鎖成功"); } else { System.out.println("更新失敗" + Thread.currentThread().getName()); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (conn != null) conn.close(); if (statement != null) statement.close(); if (resultSet != null) resultSet.close(); } catch (Exception e) { e.printStackTrace(); } } } } }, "線程" + count).start(); } } public static String lock(Jedis jedis) { try { while (true) { String lockTime = Long.valueOf(jedis.time().get(0)) + 5 + ""; if (jedis.setnx("lock", lockTime) == 1) { jedis.expire("lock", 5); return lockTime; } String lock = jedis.get("lock"); if (!StringUtils.isEmpty(lock) && Long.valueOf(lock) < Long.valueOf(jedis.time().get(0))) { String oldLockTime = jedis.getSet("lock", lockTime); if (!StringUtils.isEmpty(oldLockTime) && oldLockTime.equals(lock)) { return lockTime; } } Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } return null; } public static boolean unlock(Jedis jedis, String lockTag) { if (lockTag.equals(jedis.get("lock"))) { jedis.del("lock"); return true; } return false; } }
運行結(jié)果如下圖:
上述就是小編為大家分享的redis實現(xiàn)分布式鎖的原理,如果您也有類似的疑惑,不妨參照上述方法進行嘗試。如果想了解更多相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊。
當前名稱:redis實現(xiàn)分布式鎖的原理是什么
URL網(wǎng)址:http://www.rwnh.cn/article6/jejjog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計、外貿(mào)網(wǎng)站建設(shè)、域名注冊、建站公司、品牌網(wǎng)站建設(shè)、網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)