中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

招聘類網(wǎng)站該怎么做昆山優(yōu)化外包

招聘類網(wǎng)站該怎么做,昆山優(yōu)化外包,企業(yè)經(jīng)營(yíng)管理系統(tǒng),阿里巴巴做網(wǎng)站需要多少錢在redis集群模式下,我們會(huì)啟動(dòng)多個(gè)tomcat實(shí)例,每個(gè)tomcat實(shí)例都有一個(gè)JVM,且不共享。而synchronize鎖的作用范圍僅僅是當(dāng)前JVM,所以我們需要一個(gè)作用于集群下的鎖,也就是分布式鎖。(就是不能用JVM自帶的鎖了…

在redis集群模式下,我們會(huì)啟動(dòng)多個(gè)tomcat實(shí)例,每個(gè)tomcat實(shí)例都有一個(gè)JVM,且不共享。而synchronize鎖的作用范圍僅僅是當(dāng)前JVM,所以我們需要一個(gè)作用于集群下的鎖,也就是分布式鎖。(就是不能用JVM自帶的鎖了,需要一個(gè)第三方應(yīng)用實(shí)現(xiàn)鎖)

在redis集群中我們是用setnx實(shí)現(xiàn)互斥鎖來(lái)實(shí)現(xiàn)分布式鎖。

setnx key value NX EX? 時(shí)間 是往redis中創(chuàng)建一個(gè)key-value鍵值對(duì),如果redis中沒(méi)有該key,則創(chuàng)建成功,返回true;如果redis已經(jīng)有了該key,則創(chuàng)建失敗,返回null。NX是互斥,EX是超時(shí)時(shí)間,后跟具體時(shí)間+單位(s),EX用于過(guò)期時(shí)間,過(guò)了過(guò)期時(shí)間自動(dòng)刪除該key-value鍵值對(duì)。

我們用setnx命令實(shí)現(xiàn)分布式鎖時(shí),key和value都是String類型,key一般是特定前綴+該鎖的名字,

value為線程id。

為什么value要存線程id呢?

因?yàn)榇嬖谶@樣情況:線程一獲取鎖,去執(zhí)行邏輯,過(guò)程中遇到網(wǎng)絡(luò)動(dòng)蕩,線程一卡住了,然后一段時(shí)間后,線程一獲取的鎖的過(guò)期時(shí)間到了,線程一的鎖自動(dòng)釋放。然后線程二來(lái)獲取鎖,線程二獲取成功,去執(zhí)行邏輯,而在這個(gè)過(guò)程中線程一的網(wǎng)絡(luò)動(dòng)蕩恢復(fù)了,線程一繼續(xù)執(zhí)行,線程一先于線程二執(zhí)行完,線程一去釋放鎖,但此時(shí)線程一創(chuàng)建的鎖已經(jīng)因超時(shí)而自動(dòng)釋放了,所以此時(shí)線程一會(huì)去錯(cuò)誤的釋放線程二的鎖,所以我們要把線程id存入加以判斷,防止誤刪其他線程的id。

代碼實(shí)現(xiàn)獲取鎖和釋放鎖:

package com.hmdp.utils;import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;import java.util.Collections;
import java.util.concurrent.TimeUnit;public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name = name;this.stringRedisTemplate = stringRedisTemplate;}private static final String KEY_PREFIX = "lock:";//randomUUID生成的數(shù)字會(huì)帶一個(gè)橫線,toString(true)方法就是去掉橫線//因?yàn)椴煌琂VM中,可能存在線程號(hào)相同的情況,所以需要用UUID來(lái)區(qū)分不同的JVMprivate static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";@Overridepublic boolean tryLock(long timeoutSec) {// 獲取線程標(biāo)示String threadId = ID_PREFIX + Thread.currentThread().getId();// 獲取鎖Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);//不能直接返回success,因?yàn)闀?huì)有自動(dòng)拆箱的風(fēng)險(xiǎn),如果success是null,就會(huì)返回true,返回錯(cuò)誤數(shù)據(jù)return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {// 獲取線程標(biāo)示String threadId = ID_PREFIX + Thread.currentThread().getId();// 獲取鎖中的標(biāo)示String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);// 判斷標(biāo)示是否一致if(threadId.equals(id)) {// 釋放鎖stringRedisTemplate.delete(KEY_PREFIX + name);}}
}

我們需要新建一個(gè)類實(shí)現(xiàn)ILock接口,然后去重寫其中的tryLock獲取鎖、unlock釋放鎖方法。

往SimpleRedisLock的構(gòu)造方法傳入name變量,方便我們?cè)趯?shí)例化SimpleRedisLock類中設(shè)置該鎖的名字。我們后面用setnx命令創(chuàng)建鎖時(shí)的key值就是特定前綴KEY_PREFIX加上這個(gè)name;value值是randomUUID生成的唯一一串?dāng)?shù)字加上該線程id,因?yàn)椴煌琂VM中,可能存在線程號(hào)相同的情況,所以需要用UUID來(lái)區(qū)分不同的JVM。

問(wèn)題:

當(dāng)本線程1在進(jìn)入這個(gè)if判斷后(釋放鎖之前),突然阻塞(比如full GC,該JVM上全服務(wù)堵塞)阻塞時(shí)間過(guò)長(zhǎng),鎖超時(shí)釋放,這時(shí)另一個(gè)jvm的線程2獲取到鎖,然后線程1繼續(xù)執(zhí)行釋放鎖
這樣就又會(huì)出現(xiàn)同一個(gè)用戶會(huì)有倆個(gè)線程在同時(shí)運(yùn)行,所以需要保證判斷和釋放鎖這倆步為一個(gè)原子性,同成功或同失敗
這樣很容易想到事務(wù),redis也有事務(wù),但redis的事務(wù)可以保證原子性,但不能保證一致性,而且redis的事務(wù),是最后事務(wù)中的步驟同時(shí)完成。并不是一步一步的執(zhí)行,所以只能用樂(lè)觀鎖但不建議用樂(lè)觀鎖,推薦用lua腳本

一個(gè)lua腳本中可以編寫多條redis命令,確保多條命令的原子性。即實(shí)現(xiàn)判斷和釋放鎖一起執(zhí)行的原子性。

我們需要把這個(gè)腳本寫在resources目錄下

釋放鎖的lua腳本:

local key=KEYS[1]  -- 鎖的key
local threadId=ARGV[1]  --線程唯一標(biāo)識(shí)
-- 比較線程標(biāo)示與鎖中的標(biāo)示是否一致
if(redis.call('get', key) ==  threadId) then-- 釋放鎖 del keyreturn redis.call('del', key)
end
return 0;

if()??then? end 相當(dāng)于Java命令中的? if(? ) {? }? ?。

KEYS[1]:為需要傳入的key值,當(dāng)需要傳入多個(gè)key值時(shí),聲明KEYS[2]、KEYS[3]...等就行。

ARGV[1]:為需要傳入的其他非key的變量,聲明方法與key一樣。例如:

local key= KEYS[1] 
local key2= KEYS[2]
local threadId=ARGV[1]
local releaseTime=ARGV[2]

?

redis.call('? ',? ....)是執(zhí)行的redis命令,命令中單引號(hào)'? ?'中寫要執(zhí)行的redis操作,后面的參數(shù)為執(zhí)行該redis命令所需的參數(shù),例如,get命令,需要知道key值。

然后改寫我們的分布式鎖:

我們需要先加載我們的lua腳本:

private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); //加載的腳本的位置,如果腳本文件在resources目錄下,則只需寫腳本名稱即可。UNLOCK_SCRIPT.setResultType(Long.class); //返回值的類型}
@Overridepublic void unlock() {// 調(diào)用lua腳本  ,原來(lái)的多行代碼變成了現(xiàn)在的單行代碼就保證了原子性stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name), //生成單元素的集合,即腳本中的需要的KETS[1]參數(shù)ID_PREFIX + Thread.currentThread().getId()); //即腳本中需要的ARVG[1]參數(shù)}

完整代碼:

package com.hmdp.utils;import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;import java.util.Collections;
import java.util.concurrent.TimeUnit;public class SimpleRedisLock implements ILock {private String name;private StringRedisTemplate stringRedisTemplate;public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {this.name = name;this.stringRedisTemplate = stringRedisTemplate;}private static final String KEY_PREFIX = "lock:";//randomUUID生成的數(shù)字會(huì)帶一個(gè)橫線,toString(true)方法就是去掉橫線//因?yàn)椴煌琂VM中,可能存在線程號(hào)相同的情況,所以需要用UUID來(lái)區(qū)分不同的JVMprivate static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); //加載的腳本的位置UNLOCK_SCRIPT.setResultType(Long.class); //返回值的類型}@Overridepublic boolean tryLock(long timeoutSec) {// 獲取線程標(biāo)示String threadId = ID_PREFIX + Thread.currentThread().getId();// 獲取鎖Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);//不能直接返回success,因?yàn)闀?huì)有自動(dòng)拆箱的風(fēng)險(xiǎn),如果success是null,就會(huì)返回true,返回錯(cuò)誤數(shù)據(jù)return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {// 調(diào)用lua腳本  ,原來(lái)的多行代碼變成了現(xiàn)在的單行代碼就保證了原子性stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name), //生成單元素的集合,即腳本中的需要的KETS[1]參數(shù)ID_PREFIX + Thread.currentThread().getId()); //即腳本中需要的ARVG[1]參數(shù)}}

http://www.risenshineclean.com/news/3189.html

相關(guān)文章:

  • html 做網(wǎng)站案例簡(jiǎn)單網(wǎng)絡(luò)營(yíng)銷公司怎么注冊(cè)
  • 做網(wǎng)站瀏覽器標(biāo)簽一般放哪市場(chǎng)調(diào)研分析報(bào)告范文
  • 四川建設(shè)網(wǎng)站怎么做網(wǎng)站教程視頻
  • 什么網(wǎng)站做二手貨車it培訓(xùn)機(jī)構(gòu)口碑排名
  • 網(wǎng)站開(kāi)發(fā)怎么兼容瀏覽器seo教程搜索引擎優(yōu)化
  • 如何在工商局網(wǎng)站做身份確認(rèn)seo短視頻保密路線
  • 做軟件跟網(wǎng)站哪個(gè)難網(wǎng)頁(yè)制作公司排名
  • 銷售網(wǎng)站怎么做的瀏覽器正能量網(wǎng)站免費(fèi)
  • 哪個(gè)網(wǎng)絡(luò)公司做網(wǎng)站好2021網(wǎng)絡(luò)營(yíng)銷成功案例
  • 制作網(wǎng)頁(yè)的的網(wǎng)站torrentkitty磁力搜索引擎
  • 6.網(wǎng)站開(kāi)發(fā)流程是什么沈陽(yáng)seo收費(fèi)
  • 網(wǎng)站的排名與權(quán)重網(wǎng)絡(luò)推廣方法有幾種
  • 有了自己的域名怎么做網(wǎng)站公司專業(yè)網(wǎng)站建設(shè)
  • win7系統(tǒng)做網(wǎng)站服務(wù)器站長(zhǎng)素材網(wǎng)
  • 陜西企業(yè)營(yíng)銷型網(wǎng)站建設(shè)市場(chǎng)調(diào)研方法有哪些
  • 廣西建設(shè)廳官方網(wǎng)站文件通知廣州網(wǎng)絡(luò)推廣策劃公司
  • 網(wǎng)站qq交談怎么做的百度合作平臺(tái)
  • 網(wǎng)站建設(shè)前臺(tái)和后臺(tái)設(shè)計(jì)如何讓百度快速收錄新網(wǎng)站
  • 實(shí)驗(yàn)室網(wǎng)站建設(shè)的調(diào)查報(bào)告今日重大新聞?lì)^條財(cái)經(jīng)
  • 國(guó)外有哪些做服裝的網(wǎng)站百度指數(shù)對(duì)比
  • dede怎么設(shè)置wap網(wǎng)站云客網(wǎng)平臺(tái)
  • wordpress 手機(jī)注冊(cè)網(wǎng)站優(yōu)化推廣培訓(xùn)
  • 網(wǎng)站怎么做展現(xiàn)量網(wǎng)站運(yùn)營(yíng)推廣方案
  • 男女直接做的視頻網(wǎng)站北京關(guān)鍵詞優(yōu)化平臺(tái)
  • 湖南網(wǎng)站建設(shè) 安全還踏實(shí)磐石網(wǎng)絡(luò)百度平臺(tái)聯(lián)系方式
  • 湖南網(wǎng)站開(kāi)發(fā) 嵐鴻外貿(mào)營(yíng)銷網(wǎng)站
  • 照片做3d網(wǎng)站網(wǎng)絡(luò)平臺(tái)銷售
  • 一級(jí)a做爰片免費(fèi)網(wǎng)站孕交視頻開(kāi)封網(wǎng)站seo
  • 個(gè)人網(wǎng)站備案取消百度app客服電話
  • 聊城網(wǎng)站建設(shè)價(jià)位國(guó)外域名注冊(cè)網(wǎng)站