quartz - 資料庫鎖

來源:互聯網
上載者:User

標籤:有一個   選擇   needed   not   鎖表   ==   mys   釋放   cti   

其中,QRTZ_LOCKS就是Quartz叢集實現同步機制的行鎖表,其表結構如下:

點擊(此處)摺疊或開啟

  1. --QRTZ_LOCKS表結構
  2. CREATE TABLE `QRTZ_LOCKS` (
  3.   `LOCK_NAME` varchar(40) NOT NULL,
  4.    PRIMARY KEY (`LOCK_NAME`)
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  6. --QRTZ_LOCKS記錄
  7. +-----------------+
  8. | LOCK_NAME |
  9. +-----------------+
  10. | CALENDAR_ACCESS |
  11. | JOB_ACCESS |
  12. | MISFIRE_ACCESS |
  13. | STATE_ACCESS |
  14. | TRIGGER_ACCESS |
  15. +-----------------+

註:此表結構在2.2版本有新增欄位,這裡暫時不考慮。
可以看出QRTZ_LOCKS中有5條記錄,代表5把鎖,分別用於實現多個Quartz Node對Job、Trigger、Calendar訪問的同步控制。
關於行鎖的機制:
1、mysql >  set autocommit=0;    //先把mysql設定為不自動認可。
2、 select * from es_locks where lock_name = ‘TRIGGER_ACCESS‘ for update ;     //線程一通過for update 可以把這行鎖住
3、 select * from es_locks where lock_name = ‘TRIGGER_ACCESS‘ for update ;     //線程二通過for update 無法獲得鎖,線程等待。
4、commit;        //線程一通過commit 釋放鎖
5、 //線程二可以訪問到資料,線程不再等待。
所以,通過這個機制,一次只能有一個線程來操作 加鎖 -  操作 - 釋放鎖。  如果 操作 的時間過長的話,會帶來叢集間的主線程等待。
資料庫行鎖是一種悲觀鎖,鎖表時其它線程無法查詢。
源碼中關於資料庫叢集加鎖的方法有如下幾種:
1、executeInNonManagedTXLock方法的含義是自己管理事務,不讓容器管理事務的加鎖方法。

點擊(此處)摺疊或開啟

  1. executeInNonManagedTXLock(
  2. String lockName,
  3.             TransactionCallback<T> txCallback , final TransactionValidator<T> txValidator )

三個參數lockName的值是上面所說的TRIGGER_ACCESS,表示要加鎖的類型。
txCallback是加鎖後再回調的方法。
txValidator是驗證方法,一般為null
函數先執行加鎖,再回調要操作的方法,然後再解鎖。
看一下源碼:

點擊(此處)摺疊或開啟

  1. if (lockName != null) {
  2. // If we aren‘t using db locks, then delay getting DB connection
  3. // until after acquiring the lock since it isn‘t needed.
  4. if (getLockHandler().requiresConnection()) {
  5.                     conn = getNonManagedTXConnection();
  6. }
  7.                 transOwner = getLockHandler().obtainLock(conn, lockName);
  8. }
  9. if (conn == null) {
  10.                 conn = getNonManagedTXConnection();
  11. }
  12. final T result = txCallback.execute(conn);
  13. try {
  14.                 commitConnection(conn);
  15. } catch (JobPersistenceException e) {
  16.                 rollbackConnection(conn);
  17. if (txValidator == null || !retryExecuteInNonManagedTXLock(lockName, new TransactionCallback<Boolean>() {
  18.                     @Override
  19. public Boolean execute(Connection conn) throws JobPersistenceException {
  20. return txValidator.validate(conn, result);
  21. }
  22. })) {
  23. throw e;
  24. }
  25. }
  26. Long sigTime = clearAndGetSignalSchedulingChangeOnTxCompletion();
  27. if(sigTime != null && sigTime >= 0) {
  28.                 signalSchedulingChangeImmediately(sigTime);
  29. }
  30. return result;
  31. } catch (JobPersistenceException e) {
  32.             rollbackConnection(conn);
  33.     throw e;
  34.   } catch (RuntimeException e) {
                rollbackConnection(conn);
                throw new JobPersistenceException("Unexpected runtime exception: "
                        + e.getMessage(), e);
            } finally {
                try {
                    releaseLock(lockName, transOwner);
                } finally {
                    cleanupConnection(conn);
                }
            }

2、如果不是通過這種回調方法的加鎖,一般是:
getLockHandler().obtainLock
執行
commitConnection(conn)
releaseLock
cleanupConnection
二、源碼分析鎖

目前代碼中行鎖只用到了STATE_ACCESS 和TRIGGER_ACCESS 這兩種。

1、TRIGGER_ACCESS
先瞭解一篇文章,通過源碼來分析quartz是如何通過加鎖來實現叢集環境,觸發器狀態的一致性。
http://www.360doc.com/content/14/0926/08/15077656_412418636.shtml
可以看到觸發器的操作主要用主線程StdScheduleThread來完成,不管是擷取需要觸發的30S內的觸發器,還是觸發過程。select和update觸發器表時
都會先加鎖,後解鎖。如果資料庫資源競爭比較大的話,鎖會影響整個效能。可以考慮將任務資訊放在分布式記憶體,如redis上進行處理。資料庫只是定時從redis上load資料下來做統計。
參考:quartz詳解2:quartz由淺入深   查看第四章第1,2節
實現都在JobStoreSupport類

加鎖類型
加鎖方法
底層資料庫操作
備忘

executeInNonManagedTXLock
acquireNextTrigger
selectTriggerToAcquire
selectTrigger
selectJobDetail
insertFiredTrigger
查詢需要點火的trigger
選擇需要執行的trigger加入到fired_trigger表

for執行 triggerFired
selectJobDetail
selectCalendar
updateFiredTrigger
triggerExists updateTrigger
點火trigger
修改trigger狀態為可執行狀態。

recoverJobs
updateTriggerStatesFromOtherStates
hasMisfiredTriggersInState doUpdateOfMisfiredTrigger
selectTriggersForRecoveringJobs
selectTriggersInState
deleteFiredTriggers
非叢集環境下重新執行
failed與misfired的trigger

retryExecuteInNonManagedTXLock
releaseAcquiredTrigger
updateTriggerStateFromOtherState
deleteFiredTrigger
異常情況下重新釋放trigger到初使狀態。

triggeredJobComplete
selectTriggerStatus
removeTrigger   updateTriggerState
deleteFiredTrigger
觸發JOB任務完成後的處理。

obtainLock
recoverMisfiredJobs
hasMisfiredTriggersInState doUpdateOfMisfiredTrigger
重新執行misfired的trigger
可以在啟動時執行,也可以由misfired線程定期執行。

clusterRecover
selectInstancesFiredTriggerRecords
updateTriggerStatesForJobFromOtherState
storeTrigger
deleteFiredTriggers
selectFiredTriggerRecords
removeTrigger
deleteSchedulerState
叢集有結點faied,讓JOB能重新執行。

executeInLock
資料庫叢集裡等同於
executeInNonManagedTXLock
storeJobAndTrigger
updateJobDetail insertJobDetail
triggerExists
selectJobDetail
updateTrigger insertTrigger
儲存JOB和TRIGGER配置

storeJob
儲存JOB

removeJob
刪除JOB

removeJobs
大量刪除JOB

removeTriggers
大量刪除triggers

storeJobsAndTriggers
儲存JOB和多個trigger配置

removeTrigger
刪除trigger

replaceTrigger
替換trigger

storeCalendar
儲存定時日期

removeCalendar
刪除定時日期

clearAllSchedulingData
清除所有定時資料

pauseTrigger
停止觸發器

pauseJob
停止任務

pauseJobs
大量停止任務

resumeTrigger
恢複觸發器

resumeJob
恢複任務

resumeJobs
大量復原任務

pauseTriggers
大量停止觸發器

resumeTriggers
大量復原觸發器

pauseAll
停止所有

resumeAll
恢複所有

---
2、STATE_TRIGGER
實現都在JobStoreSupport類

加鎖類型
加鎖方法
底層資料庫操作
備忘

obtainLock
doCheckin
clusterCheckIn
判斷叢集狀態
先用LOCK_STATE_ACCESS鎖叢集狀態
再用LOCK_TRIGGER_ACCESS恢複叢集運行

---

quartz - 資料庫鎖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.