Shedlock kullanarak Distrubuted Scheduler yazmak

ümit Samimi
2 min readJan 1, 2023

--

Eğer bir uygulamanın birden fazla örneğini aynanda çalıştırıyorsanız(scale), çalışan her örneğin aynı veriyi okuyup, aynı veri üzerinde işlem yapması sizin veri güvenliğiniz için uygun olmayacaktır

Dağıtık sistemlerde bu sorun için geliştirilmiş bir çok farklı çözüm var. Ben daha önce kullandığım pratiği sizinle paylaşmak istiyorum.

Shedlock

Adından da anlaşılacağı üzere bir kilitleme operasyonudur. Java’da, shared variable’lar için olan lock’lama prensibinin çok benzeridir fakat java uygulaması birden fazla instance(örnek)’ta çalıştığında, diğer örnekler kilitlenen alanları görmez. Bunun için distributed bir çözüm gerekir. Shedlock bize bunu sağlıyor.

Bir örnek ile birlikte inceleyelim. Ben uygulamayı java:spring boot ile yazdım. Bunun üzerinden anlatmaya devam edeceğim

Gelin ilk olarak shedlock kütüphanelerini projemize maven aracılığı ile indirelim

<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.19.1</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>4.19.1</version>
</dependency>

Lock’lamayı mysql veritabanındaki bir tablo üzerinden veya couchbase üzerinden bir bucket ile veya redis cache üzerinden bir key ile yapabilirsiniz.

Ben tablo üzerinden örneğe devam edeceğim

CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP NOT NULL,  
locked_at TIMESTAMP NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));

INSERT INTO shedlock
VALUES ('MY_LOCK_NAME', NOW(),NOW(), 'MY_LOCK_NAME');

Şimdi sıra konfigürasyonlarda. Shedlock için basit bir konfigürasyon yapacağım. Kilit sağlayıcının veri kaynağını belirtmem gerekiyor. JdbcTemplateLockProvider ’a uygulamanın çalışma anındaki datasource’u tanıtıyorum.

@Configuration
public class ShedlockConfiguration {

@Bean
public LockProvider lockProvider(DataSource dataSource)
{
return new JdbcTemplateLockProvider(
JdbcTemplateLockProvider.Configuration.builder()
.withJdbcTemplate(new JdbcTemplate(dataSource))
.usingDbTime()
.build()
);
}
}

Schedular’ı yazmadan önce son olarak parametrelerimi properties doyasına eklemem gerekiyor. Aşağıda verdiğim değişkenler milisaniye cinsinden

initial.delay=10000
fixed.delay=3000

Artık Schedular’ı yazabilirim.

@Component  
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "5m")
public class Schedular {
@Scheduled(initialDelayString = "${initial.delay}", fixedDelayString = "${fixed.delay}")
@SchedulerLock(name = "MY_LOCK_NAME")
public void scheduledJob()
{
log.info("Schedular works {}", Calendar.getInstance().getTime());
}
}

Umarım faydalı olmuştur

--

--