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

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

網(wǎng)站制作怎樣做背景贛州seo唐三

網(wǎng)站制作怎樣做背景,贛州seo唐三,廣州微信網(wǎng)站建設(shè)效果,網(wǎng)站系統(tǒng)分析的步驟有哪些分布式鎖mysql實(shí)現(xiàn)方式 方式1:唯一索引 創(chuàng)建鎖表,內(nèi)部存在字段表示資源名及資源描述,同一資源名使用數(shù)據(jù)庫(kù)唯一性限制。多個(gè)進(jìn)程同時(shí)往數(shù)據(jù)庫(kù)鎖表中寫入對(duì)某個(gè)資源的占有記錄,當(dāng)某個(gè)進(jìn)程成功寫入時(shí)則表示其獲取鎖成功其他進(jìn)程由于…

分布式鎖mysql實(shí)現(xiàn)方式
方式1:唯一索引

  • 創(chuàng)建鎖表,內(nèi)部存在字段表示資源名及資源描述,同一資源名使用數(shù)據(jù)庫(kù)唯一性限制。
  • 多個(gè)進(jìn)程同時(shí)往數(shù)據(jù)庫(kù)鎖表中寫入對(duì)某個(gè)資源的占有記錄,當(dāng)某個(gè)進(jìn)程成功寫入時(shí)則表示其獲取鎖成功
  • 其他進(jìn)程由于資源字段唯一性限制插入失敗陷入自旋并且失敗重試。
  • 當(dāng)執(zhí)行完業(yè)務(wù)后持有該鎖的進(jìn)程則刪除該表內(nèi)的記錄,此時(shí)回到步驟一。
    在這里插入圖片描述
    表數(shù)據(jù)
create table `database_lock`(`id` BIGINT NOT NULL AUTO_INCREMENT,`resource` INT NOT NULL COMMENT '鎖資源',`description` varchar(1024) NOT NULL DEFAULT "" COMMENT '描述',PRIMARY KEY (`id`),UNIQUE KEY `resource` (`resource`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='數(shù)據(jù)庫(kù)分布式鎖表';

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/distribute_lock?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
user=root
password=123456
  • PropertiesReader
@Slf4j
public class PropertiesReader {// Properties緩存文件private static final Map<String, Properties> propertiesCache = new HashMap<String, Properties>();public static Properties getProperties(String propertiesName) throws IOException {if (propertiesCache.containsKey(propertiesName)) {return propertiesCache.get(propertiesName);}loadProperties(propertiesName);return propertiesCache.get(propertiesName);}private synchronized static void loadProperties(String propertiesName) throws IOException {FileReader fileReader = null;try {// 創(chuàng)建Properties集合類Properties pro = new Properties();// 獲取src路徑下的文件--->ClassLoader類加載器ClassLoader classLoader = PropertiesReader.class.getClassLoader();URL resource = classLoader.getResource(propertiesName);// 獲取配置路徑String path = resource.getPath();// 讀取文件fileReader = new FileReader(path);// 加載文件pro.load(fileReader);// 初始化propertiesCache.put(propertiesName, pro);} catch (IOException e) {log.error("讀取Properties文件失敗,Properties名為:" + propertiesName);throw e;} finally {try {if (fileReader != null) {fileReader.close();}} catch (IOException e) {log.error("fileReader關(guān)閉失敗!", e);}}}
}
  • JDBCUtils
@Slf4j
public class JDBCUtils {private static String url;private static String user;private static String password;static {//讀取文件,獲取值try {Properties properties = PropertiesReader.getProperties("db.properties");url = properties.getProperty("url");user = properties.getProperty("user");password = properties.getProperty("password");String driver = properties.getProperty("driver");//4.注冊(cè)驅(qū)動(dòng)Class.forName(driver);} catch (IOException | ClassNotFoundException e) {log.error("初始化jdbc連接失敗!", e);}}/*** 獲取連接* @return 連接對(duì)象*/public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, user, password);}/*** 釋放資源* @param rs* @param st* @param conn*/public static void close(ResultSet rs, Statement st, Connection conn) {if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (st != null) {try {st.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}

數(shù)據(jù)庫(kù)操作類

/*** MySQL 鎖操作類(加鎖+釋放鎖)*/
@Slf4j
public class MySQLDistributedLockService {private static Connection connection;private static Statement statement;private static ResultSet resultSet;static{try {connection = JDBCUtils.getConnection();statement = connection.createStatement();resultSet = null;} catch (SQLException e) {log.error("數(shù)據(jù)庫(kù)連接失敗!");}}/*** 鎖表 - 獲取鎖* @param resource      資源* @param description   鎖描述* @return  是否操作成功*/public static boolean tryLock(int resource,String description){String sql = "insert into database_lock (resource,description) values (" + resource + ", '" + description + "');";//獲取數(shù)據(jù)庫(kù)連接try {int stat = statement.executeUpdate(sql);return stat == 1;} catch (SQLException e) {return false;}}/*** 鎖表-釋放鎖* @return*/public static boolean releaseLock(int resource) throws SQLException {String sql = "delete from database_lock where resource = " + resource;//獲取數(shù)據(jù)庫(kù)連接int stat = statement.executeUpdate(sql);return stat == 1;}/*** 關(guān)閉連接*/public static void close(){log.info("當(dāng)前線程: " + ManagementFactory.getRuntimeMXBean().getName().split("@")[0] +",關(guān)閉了數(shù)據(jù)庫(kù)連接!");JDBCUtils.close(resultSet,statement,connection);}
}

LockTable

/*** mysql分布式鎖*      執(zhí)行流程: 多進(jìn)程搶占數(shù)據(jù)庫(kù)某個(gè)資源,然后執(zhí)行業(yè)務(wù),執(zhí)行完釋放資源*      鎖機(jī)制: 單一進(jìn)程獲取鎖時(shí),則其他進(jìn)程提交失敗*/
@Slf4j
public class LockTable extends Thread {@Overridepublic void run() {super.run();//獲取Java虛擬機(jī)的進(jìn)程IDString pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];try{while(true){log.info("當(dāng)前進(jìn)程PID:" + pid + ",嘗試獲取鎖資源!");if(MySQLDistributedLockService.tryLock(1,"測(cè)試鎖")){log.info("當(dāng)前進(jìn)程PID:" + pid + ",獲取鎖資源成功!");//sleep模擬業(yè)務(wù)處理過程log.info("開始處理業(yè)務(wù)!");Thread.sleep(10*1000);log.info("業(yè)務(wù)處理完成!");MySQLDistributedLockService.releaseLock(1);log.info("當(dāng)前進(jìn)程PID: " + pid + ",釋放了鎖資源!");break;}else{log.info("當(dāng)前進(jìn)程PID: " + pid + ",獲取鎖資源失敗!");Thread.sleep(2000);}}}catch (Exception e){log.error("搶占鎖發(fā)生錯(cuò)誤!",e);}finally {MySQLDistributedLockService.close();}}// 程序入口public static void main(String[] args) {new LockTable().start();}
}

測(cè)試
運(yùn)行時(shí)開啟并行執(zhí)行選項(xiàng),每次運(yùn)行三個(gè)或三個(gè)以上進(jìn)程. Allow parallel run 運(yùn)行并行執(zhí)行
image.png
image.png
注意事項(xiàng):

  • 該鎖為非阻塞的
  • 當(dāng)某進(jìn)程持有鎖并且掛死時(shí)候會(huì)造成資源一直不釋放的情況,造成死鎖,因此需要維護(hù)一個(gè)定時(shí)清理任務(wù)去清理持有過久的鎖
  • 要注意數(shù)據(jù)庫(kù)的單點(diǎn)問題,最好設(shè)置備庫(kù),進(jìn)一步提高可靠性
  • 該鎖為非可重入鎖,如果要設(shè)置成可重入鎖需要添加數(shù)據(jù)庫(kù)字段記錄持有該鎖的設(shè)備信息以及加鎖次數(shù)

方式二:基于樂觀鎖

  • 每次執(zhí)行業(yè)務(wù)前首先進(jìn)行數(shù)據(jù)庫(kù)查詢,查詢當(dāng)前的需要修改的資源值(或版本號(hào))。
  • 進(jìn)行資源的修改操作,并且修改前進(jìn)行資源(或版本號(hào))的比對(duì)操作,比較此時(shí)數(shù)據(jù)庫(kù)中的值是否和上一步查詢結(jié)果相同。
  • 查詢結(jié)果相同則修改對(duì)應(yīng)資源值,不同則回到第一步。
    image.png

例子:數(shù)據(jù)庫(kù)中設(shè)定某商品基本信息(名為外科口罩,數(shù)量為10),多進(jìn)程對(duì)該商品進(jìn)行搶購(gòu),當(dāng)商品數(shù)量為0時(shí)結(jié)束搶購(gòu)。
在這里插入圖片描述
代碼實(shí)現(xiàn)

    /*** 樂觀鎖-獲取資源* @param id 資源ID* @return result*/public static ResultSet getGoodCount(int id) throws SQLException {String sql = "select  * from  database_lock_2 where id = " + id;//查詢數(shù)據(jù)resultSet = statement.executeQuery(sql);return resultSet;}/*** 樂觀鎖-修改資源* @param id        資源ID* @param goodCount 資源* @return  修改狀態(tài)*/public static boolean setGoodCount(int id, int goodCount) throws SQLException {String sql = "update database_lock_2 set good_count = good_count - 1 where id =" + id +"  and good_count = " + goodCount;int stat = statement.executeUpdate(sql);return stat == 1;}/*** 樂觀鎖-開啟事務(wù)自動(dòng)提交*/public static void AutoCommit(){try {connection.setAutoCommit(true);} catch (SQLException e) {log.error("開啟自動(dòng)提交!",e);}}

OptimisticLock測(cè)試類

/*** mysql分布式鎖-樂觀鎖*  執(zhí)行流程: 多進(jìn)程搶購(gòu)?fù)簧唐?#xff0c;每次搶購(gòu)成功商品數(shù)量-1,商品數(shù)據(jù)量為0時(shí)退出*  鎖機(jī)制: 單一進(jìn)程獲取鎖時(shí),則其他進(jìn)程提交失敗*/
@Slf4j
public class OptimisticLock extends Thread{@Overridepublic void run() {super.run();String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];ResultSet resultSet = null;String goodName = null;int goodCount = 0;try {while(true){log.info("當(dāng)前線程:" + pid + ",開始搶購(gòu)商品!");//獲取當(dāng)前商品信息resultSet = MySQLDistributedLockService.getGoodCount(1);while (resultSet.next()){goodName = resultSet.getString("good_name");goodCount = resultSet.getInt("good_count");}log.info("獲取庫(kù)存成功,當(dāng)前商品名為:" + goodName + ",當(dāng)前庫(kù)存剩余量為:" + goodCount);//模擬執(zhí)行業(yè)務(wù)操作Thread.sleep(2*3000);if(0 == goodCount){log.info("搶購(gòu)失敗,當(dāng)前庫(kù)存為0! ");break;}//修改庫(kù)存信息,庫(kù)存量-1if(MySQLDistributedLockService.setGoodCount(1,goodCount)){log.info("當(dāng)前線程:" + pid + " 搶購(gòu)商品:" + goodName + "成功,剩余庫(kù)存為:" + (goodCount -1));//模擬延遲,防止鎖每次被同一進(jìn)程獲取Thread.sleep(2 * 1000);}else{log.error("搶購(gòu)商品:" + goodName +"失敗,商品數(shù)量已被修改");}}}catch (Exception e){log.error("搶購(gòu)商品發(fā)生錯(cuò)誤!",e);}finally {if(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();log.error("關(guān)閉Result失敗!" , e);}}MySQLDistributedLockService.close();}}public static void main(String[] args) {new OptimisticLock().start();}
}

代碼測(cè)試
開啟三個(gè)進(jìn)程,查看執(zhí)行情況
image.png
image.png
image.png
注意事項(xiàng):

  • 該鎖為非阻塞的
  • 該鎖對(duì)于業(yè)務(wù)具有侵入式,如果設(shè)置版本號(hào)校驗(yàn)則增加的額外的字段,增加了數(shù)據(jù)庫(kù)冗余
  • 當(dāng)并發(fā)量過高時(shí)會(huì)有大量請(qǐng)求訪問數(shù)據(jù)庫(kù)的某行記錄,對(duì)數(shù)據(jù)庫(kù)造成很大的寫壓力
  • 因此樂觀鎖適用于并發(fā)量不高,并且寫操作不頻繁的場(chǎng)景

方式三:悲觀鎖實(shí)現(xiàn)方式(利用事務(wù)加上行/表鎖)
在這里插入圖片描述
實(shí)現(xiàn)思路

  • 關(guān)閉jdbc連接自動(dòng)commit屬性
  • 每次執(zhí)行業(yè)務(wù)前先使用查詢語(yǔ)句后接for update表示鎖定該行數(shù)據(jù)(注意查詢條件如果未命中主鍵或索引,此時(shí)將會(huì)從行鎖變?yōu)楸礞i)
  • 執(zhí)行業(yè)務(wù)流程修改表資源
  • 執(zhí)行commit操作

代碼實(shí)現(xiàn)
MySQLDistributedLockService

/*** 悲觀鎖-獲取資源* @param id 資源ID* @return result*/public static ResultSet getGoodCount2(int id) throws SQLException {String sql = "select  * from  database_lock_2 where id = " + id + "for update";//查詢數(shù)據(jù)resultSet = statement.executeQuery(sql);return resultSet;}/*** 悲觀鎖-修改資源* @param id        資源ID* @return  修改狀態(tài)*/public static boolean setGoodCount2(int id) throws SQLException {String sql = "update database_lock_2 set good_count = good_count - 1 where id =" + id;int stat = statement.executeUpdate(sql);return stat == 1;}/*** 悲觀鎖-關(guān)閉事務(wù)自動(dòng)提交*/public static void closeAutoCommit(){try {connection.setAutoCommit(false);} catch (SQLException e) {log.error("關(guān)閉自動(dòng)提交失敗!",e);}}/*** 悲觀鎖-提交事務(wù)*/public static void commit(String pid,String goodName,int goodCount) throws SQLException {connection.commit();log.info("當(dāng)前線程:" + pid + "搶購(gòu)商品: " + goodName + "成功,剩余庫(kù)存為:" + (goodCount-1));}/*** 悲觀鎖-回滾*/public static void rollBack() throws SQLException {connection.rollback();}

PessimisticLock

/*** mysql 分布式鎖-悲觀鎖*     執(zhí)行流程:多個(gè)進(jìn)程搶占同一個(gè)商品,執(zhí)行業(yè)務(wù)完畢則通過connection.commit() 釋放鎖*     鎖機(jī)制:單一進(jìn)程獲取鎖時(shí),則其他進(jìn)程將阻塞等待*/
@Slf4j
public class PessimisticLock extends Thread {@Overridepublic void run() {super.run();ResultSet resultSet = null;String goodName = null;int goodCount = 0;String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];//關(guān)閉自動(dòng)提交MySQLDistributedLockService.closeAutoCommit();try{while(true){log.info("當(dāng)前線程:" + pid + "");//獲取庫(kù)存resultSet = MySQLDistributedLockService.getGoodCount2(1);while (resultSet.next()) {goodName = resultSet.getString("good_name");goodCount = resultSet.getInt("good_count");}log.info("獲取庫(kù)存成功,當(dāng)前商品名稱為:" + goodName + ",當(dāng)前庫(kù)存剩余量為:" + goodCount);// 模擬執(zhí)行業(yè)務(wù)事件Thread.sleep(2 * 1000);if (0 == goodCount) {log.info("搶購(gòu)失敗,當(dāng)前庫(kù)存為0!");break;}// 搶購(gòu)商品if (MySQLDistributedLockService.setGoodCount2(1)) {// 模擬延時(shí),防止鎖每次被同一進(jìn)程獲取MySQLDistributedLockService.commit(pid, goodName, goodCount);Thread.sleep(2 * 1000);} else {log.error("搶購(gòu)商品:" + goodName + "失敗!");}}}catch (Exception e){//搶購(gòu)失敗log.error("搶購(gòu)商品發(fā)生錯(cuò)誤!",e);try {MySQLDistributedLockService.rollBack();} catch (SQLException ex) {log.error("回滾失敗! ",e);}}finally {if(resultSet != null){try {resultSet.close();} catch (SQLException e) {log.error("Result關(guān)閉失敗!",e);}}MySQLDistributedLockService.close();}}public static void main(String[] args) {new PessimisticLock().start();}
}

測(cè)試結(jié)果
image.png
image.png
image.png
注意事項(xiàng):

  • 該鎖為阻塞鎖
  • 每次請(qǐng)求存在額外加鎖的開銷
  • 在并發(fā)量很高的情況下會(huì)造成系統(tǒng)中存在大量阻塞的請(qǐng)求,影響系統(tǒng)的可用性
  • 因此悲觀鎖適用于并發(fā)量不高,讀操作不頻繁的寫場(chǎng)景

總結(jié):

  • 在實(shí)際使用中,由于受到性能以及穩(wěn)定性約束,對(duì)于關(guān)系型數(shù)據(jù)庫(kù)實(shí)現(xiàn)的分布式鎖一般很少被用到。但是對(duì)于一些并發(fā)量不高、系統(tǒng)僅提供給內(nèi)部人員使用的單一業(yè)務(wù)場(chǎng)景可以考慮使用關(guān)系型數(shù)據(jù)庫(kù)分布式鎖,因?yàn)槠鋸?fù)雜度較低,可靠性也能夠得到保證。
http://www.risenshineclean.com/news/30591.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)公司相關(guān)資質(zhì)精準(zhǔn)客源app
  • 做百度網(wǎng)上搜索引擎推廣最好網(wǎng)站杭州seo網(wǎng)站排名優(yōu)化
  • 攝影網(wǎng)站建設(shè)內(nèi)容網(wǎng)站運(yùn)營(yíng)一個(gè)月多少錢
  • 怎么做網(wǎng)站多少錢蘇州網(wǎng)站制作推廣
  • 做網(wǎng)站劃算還是做app劃算營(yíng)銷型網(wǎng)站和普通網(wǎng)站
  • 做模版網(wǎng)站打開百度網(wǎng)站首頁(yè)
  • 優(yōu)化網(wǎng)站哪家好競(jìng)價(jià)排名是按照什么來計(jì)費(fèi)的
  • 視頻網(wǎng)站seo實(shí)戰(zhàn)免費(fèi)私人網(wǎng)站建設(shè)軟件
  • 中山建設(shè)監(jiān)理有限公司 網(wǎng)站如何提高網(wǎng)站的搜索排名
  • wordpress上傳函數(shù)四川seo哪里有
  • 很好用的炫酷WordPress主題上海seo顧問
  • dede新聞網(wǎng)站源碼營(yíng)銷課程培訓(xùn)視頻
  • 晉州做網(wǎng)站響應(yīng)式模版移動(dòng)優(yōu)化
  • 建材公司網(wǎng)站建設(shè)方案點(diǎn)擊器 百度網(wǎng)盤
  • 深圳官方網(wǎng)站設(shè)計(jì)長(zhǎng)沙網(wǎng)站策劃
  • 太原營(yíng)銷網(wǎng)站建設(shè)制作平臺(tái)網(wǎng)站監(jiān)測(cè)
  • 學(xué)網(wǎng)站開發(fā)培訓(xùn)班seo為什么要進(jìn)行外部?jī)?yōu)化
  • 網(wǎng)站建設(shè)源代碼上傳百度網(wǎng)頁(yè)怎么制作
  • 企業(yè)網(wǎng)站制作簡(jiǎn)介bt螞蟻
  • 深圳網(wǎng)絡(luò)公司做網(wǎng)站臺(tái)州網(wǎng)站seo
  • 一對(duì)一直播軟件開發(fā)夫唯老師seo
  • 購(gòu)物網(wǎng)站最重要的功能我要登錄百度
  • 保定哪做網(wǎng)站好企業(yè)查詢信息平臺(tái)
  • 做網(wǎng)站切圖網(wǎng)址怎么申請(qǐng)注冊(cè)
  • 黃山做網(wǎng)站公司關(guān)鍵詞搜索神器
  • 建網(wǎng)站比較靠譜的公司新媒體營(yíng)銷推廣方案
  • 泰安網(wǎng)站制作服務(wù)2000元代理微信朋友圈廣告
  • 更改wordpress主題百度關(guān)鍵詞優(yōu)化多久上首頁(yè)
  • 專門做二手書網(wǎng)站或app百度云搜索引擎入口網(wǎng)盤搜索神器
  • 國(guó)外做燈的網(wǎng)站市場(chǎng)推廣方案