redis實(shí)現(xiàn)分布式鎖的原理是什么

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)redis實(shí)現(xiàn)分布式鎖的原理,以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

成都網(wǎng)站建設(shè)公司更懂你!創(chuàng)新互聯(lián)建站只做搜索引擎喜歡的網(wǎng)站!成都網(wǎng)站制作前臺(tái)采用搜索引擎認(rèn)可的DIV+CSS架構(gòu),全站HTML靜態(tài),H5頁(yè)面制作+CSS3網(wǎng)站,提供:網(wǎng)站建設(shè),微信開(kāi)發(fā),小程序開(kāi)發(fā),成都做商城網(wǎng)站,成都App定制開(kāi)發(fā),國(guó)際域名空間,服務(wù)器租售,網(wǎng)站代托管運(yùn)營(yíng),微信公眾號(hào)代托管運(yùn)營(yíng)。

分布式鎖,是控制分布式系統(tǒng)之間同步訪(fǎng)問(wèn)共享資源的一種方式。

在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪(fǎng)問(wèn)這些資源的時(shí)候,往往需要互斥來(lái)防止彼此干擾來(lái)保證一致性,在這種情況下,便需要使用到分布式鎖。

使用setnx、getset、expire、del這4個(gè)redis命令實(shí)現(xiàn) 

setnx 是『SET if Not eXists』(如果不存在,則 SET)的簡(jiǎn)寫(xiě)。 命令格式:SETNX key value;使用:只在鍵 key 不存在的情況下,將鍵 key 的值設(shè)置為 value 。若鍵 key 已經(jīng)存在, 則 SETNX 命令不做任何動(dòng)作。返回值:命令在設(shè)置成功時(shí)返回 1 ,設(shè)置失敗時(shí)返回 0 。

getset 命令格式:GETSET key value,將鍵 key 的值設(shè)為 value ,并返回鍵 key 在被設(shè)置之前的舊的value。返回值:如果鍵 key 沒(méi)有舊值, 也即是說(shuō), 鍵 key 在被設(shè)置之前并不存在, 那么命令返回 nil 。當(dāng)鍵 key 存在但不是字符串類(lèi)型時(shí),命令返回一個(gè)錯(cuò)誤。

expire 命令格式:EXPIRE key seconds,使用:為給定 key 設(shè)置生存時(shí)間,當(dāng) key 過(guò)期時(shí)(生存時(shí)間為 0 ),它會(huì)被自動(dòng)刪除。返回值:設(shè)置成功返回 1 。 當(dāng) key 不存在或者不能為 key 設(shè)置生存時(shí)間時(shí)(比如在低于 2.1.3 版本的 Redis 中你嘗試更新 key 的生存時(shí)間),返回 0 。

del 命令格式:DEL key [key …],使用:刪除給定的一個(gè)或多個(gè) key ,不存在的 key 會(huì)被忽略。返回值:被刪除 key 的數(shù)量。

Redis實(shí)現(xiàn)分布式鎖的原理:

1.通過(guò)setnx(lock_timeout)實(shí)現(xiàn),如果設(shè)置了鎖返回1, 已經(jīng)有值沒(méi)有設(shè)置成功返回0

2.死鎖問(wèn)題:通過(guò)實(shí)踐來(lái)判斷是否過(guò)期,如果已經(jīng)過(guò)期,獲取到過(guò)期時(shí)間get(lockKey),然后getset(lock_timeout)判斷是否和get相同,相同則證明已經(jīng)加鎖成功,因?yàn)榭赡軐?dǎo)致多線(xiàn)程同時(shí)執(zhí)行g(shù)etset(lock_timeout)方法,這可能導(dǎo)致多線(xiàn)程都只需getset后,對(duì)于判斷加鎖成功的線(xiàn)程, 再加expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS)過(guò)期時(shí)間,防止多個(gè)線(xiàn)程同時(shí)疊加時(shí)間,導(dǎo)致鎖時(shí)效時(shí)間翻倍

redis實(shí)現(xiàn)分布式鎖的原理是什么代碼:

/**
 * @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);// 指定連接類(lèi)型
                            conn = DriverManager.getConnection(url, user, password);// 獲取連接
                            statement = conn.createStatement();// 準(zhǔn)備執(zhí)行語(yǔ)句
                            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() + "  庫(kù)存剩余:" + (count - 1));
                                System.out.println(Thread.currentThread().getName() + " === > >開(kāi)始解鎖");
                                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();
                            }
                        }
                    }
                }
            }, "線(xiàn)程" + 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;
    }
 
}

運(yùn)行結(jié)果如下圖:

redis實(shí)現(xiàn)分布式鎖的原理是什么

上述就是小編為大家分享的redis實(shí)現(xiàn)分布式鎖的原理,如果您也有類(lèi)似的疑惑,不妨參照上述方法進(jìn)行嘗試。如果想了解更多相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊。

當(dāng)前名稱(chēng):redis實(shí)現(xiàn)分布式鎖的原理是什么
URL網(wǎng)址:http://muchs.cn/article6/jejjog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)外貿(mào)網(wǎng)站建設(shè)、域名注冊(cè)建站公司、品牌網(wǎng)站建設(shè)網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司