Spring Boot + Redis, arayüz idempotansına ulaşmak için aslında özel açıklamalar + dağıtılmış kilitler kullanır

Sahneler

Geleneksel endüstri veya İnternet endüstrisi ne olursa olsun, çoğu işlemin idempotent olmasını sağlamalıyız Basitçe söylemek gerekirse, kullanıcı kaç kez tıklarsa tıklasın, kaç işlem olursa olsun, sonuç aynı ve benzersizdir. Ve bu şirketin projesinde, böyle idempotent bir sorunla karşılaştım, yani kullanıcının bakiyesi yeniden yükleme, sipariş oluşturma ve sipariş ödemesi Kullanıcı kaç kez tıklarsa tıklasın, sadece bir yeniden yükleme kaydı ve bir yeni sipariş kaydı olacak. Bir sipariş ödeme kaydı.

Teknik çözümler

En çok kullanılan çözümler Redis'e dayanmaktadır.

Çözüm: Redis + token

İşleme akışı: Verileri göndermeden önce, ön uç sunucudan bir jeton için başvurmalı ve jetonu (sona erme süreli) redise koymalıdır; veri gönderildiğinde jetonu getirin, jeton başarıyla silinirse jetonun süresinin dolmadığı anlamına gelir ve daha sonra iş mantığı gerçekleştirilir, aksi takdirde Diğer bir deyişle, jetonun süresi dolmuştur ve ön uçtan verileri tekrar tekrar göndermemesini ister.

Ve farklı bir şema kullanacağım. Ön uç ve arka uç yerleştirme şu anda yarı yolda olduğundan, ön uçun belirteç istemek için arabirimi artırmasını istemiyorum (sonuçta arka uç bunu halledebilir, bu nedenle ön uç öğrencileri rahatsız etmeyin).

Çözüm: özel açıklama + dağıtılmış kilit

İşleme akışı: idempotence gerektiren arabirimlere özel açıklamalar ekleyin. Ardından, etrafındaki yöntemde bir yön, mantık yazın: dağıtılmış bir kilit elde etmeye çalışın (sona erme süresi ile), başarı tekrarlanan bir gönderimin olmadığını gösterir, aksi takdirde tekrarlanan gönderme.

Açıklama başlangıcı

1. Redis bağımlılığı ekleyin:

< bağımlılık >

< Grup kimliği > org.springframework.boot < /Grup kimliği >

< artifactId > Spring-boot-starter-data-redis < / artifactId >

< /bağımlılık >

2. Özel ek açıklamalar:

/ **

* @author Howinfun

* @desc özel açıklama: dağıtılmış kilit

* @tarih 2019/11/12

* /

@Target (ElementType.METHOD)

@Retention (RetentionPolicy.RUNTIME)

public @interface CacheLock {

/ ** anahtar öneki * /

Dize öneki () varsayılan "";

/ ** Süresi dolacak saniye sayısı, varsayılan 5 saniyedir * /

int expire () varsayılan 5;

/ ** Zaman aşımı birimi, varsayılan saniye * /

TimeUnit timeUnit () varsayılan TimeUnit.SECONDS;

/ ** Anahtar ayırıcı (varsayılan :) * /

Dize sınırlayıcı () varsayılan ":";

}

3. Özel durum:

/ **

* @author Howinfun

* @desc özel yönü

* @tarih 2019/11/12

* /

@Görünüş

@Bileşen

public class LockCheckAspect {

/ ** lua * /

private static final String RELEASE_LOCK_LUA_SCRIPT = "redis.call ('get', KEYS) == ARGV ise redis.call ('del', KEYS) döndürürse 0 end döndür";

@Autowired

özel RedisTemplate < Dize, Nesne > redisTemplate;

// Yöntemi CacheLock ek açıklamasıyla geliştirin

@Pointcut ("@ annotation (cn.gdmcmc.system.api.config.aop.CacheLock)")

public void pointCut () {}

@Around ("pointCut ()")

public Object around (ProceedingJoinPoint joinPoint) Throwable {

// Kullanıcının benzersiz kişisel bilgileri, cep telefonu numarası gibi işletmeye göre elde edilebilir

Dize telefon = .....;

MethodSignature imzası = (MethodSignature) joinPoint.getSignature ();

Yöntem yöntemi = imza.getMethod ();

CacheLock cacheLock = method.getAnnotation (CacheLock.class);

Dize öneki = cacheLock.prefix ();

if (StringUtils.isBlank (önek)) {

yeni GlobalException ("CacheLock öneki boş olamaz");

}

// ekleme anahtarı

Dize sınırlayıcı = cacheLock.delimiter ();

StringBuilder sb = new StringBuilder ();

sb.append (önek) .append (sınırlayıcı) .append (telefon);

final String lockKey = sb.toString ();

final String UUID = cn.hutool.core.lang.UUID.fastUUID (). toString ();

Deneyin {

// Kilidi al

boole başarısı = redisTemplate.opsForValue (). setIfAbsent (lockKey, UUID, cacheLock.expire (), cacheLock.timeUnit ());

eğer (! başarılı) {

yeni CustomDeniedException oluştur ("Tekrar tekrar göndermeyin");

}

Nesne sonucu = joinPoint.proceed ();

dönüş sonucu;

}en sonunda {

// Son olarak kilidi açmayı unutmayın

DefaultRedisScript < Uzun > redisScript = yeni DefaultRedisScript < > (RELEASE_LOCK_LUA_SCRIPT, Long.class);

Uzun sonuç = redisTemplate.execute (redisScript, Collections.singletonList (lockKey), UUID);

}

}

}

4. Bu noktada idempotent olması gereken arabirimlere @CacheLock ek açıklamalarını ekleyin.

@Filmdenkare

@RequestMapping (value = "/ charge")

@AllArgsConstructor

public class ChargeController {

@PostMapping ("/ startCharge")

@CacheLock (prefix = "şarj")

public Result startCharge (@RequestBody @Validated ({ChargeQuery.QRCodeNotBlank.class}) ChargeQuery sorgusu) {

this.chargeChargeService.startCharge (sorgu) döndür;

}

}

Orijinal: https://blog.csdn.net/Howinfun/article/details/103062184

CCTV'nin "saf endüstri" belgeseli, büyük ülkelerin "süper ekipmanlarında" yaşamın ritmini filme aldı
önceki
Fujian'daki en düşük sıcaklık 3,6 ! Bir sonraki soğuk hava dalgası 62 saat içinde gelecek ... Ayağa kalkmakta güçlük çeken hanelerin bu haritası toplandı
Sonraki
Yerli litografi makinesinde büyük bir atılım olan Hollandalı ASML sonunda ödün verdi ve en gelişmiş litografi makinesini satmak zorunda kaldı
7,7 ° C! Soğuk dalga patronu geliyor! Önümüzdeki hafta Xiamen'de şiddetli rüzgar + soğuk olacak ve yağmur yağabilir ...
Korkunç! Tavan aniden yaklaşık 40 kilo piton düştü! Keşfedilmeden önce 10 yıl saklanıyor
Sakinleşin ve "gerçekten oynayın"! Önümüzdeki haftanın başında, sıcaklık günde üç mevsim "düşecek".
Hu Xijin: Hong Kong medyası tarafından röportaj yapılan Hong Kong Üniversitesi kızının görüşlerine katılmıyorum, ancak toplu olarak kınanmamalı
"Üç elektrikli sistem" Golf'ün ödün vermeyen temel güvenlik tasarımı · Saf Elektrikli Bora · Saf Elektrikli Set bir endüstri modeli
6 'ye düştü! "Overlord" güçlü soğuk hava Hunan'a gelecek! Uzun pantolon + aşağı ceket yeterli değil ...
Hevesli vatandaşlar zamanında polisi arar Xuhui polisi bir kablo hırsızlığı davasını çözdü
Programcı: Sonunda post ve get arasındaki farkı anladım
"Double Eleven" ekspres kamyonu alev aldı, En iyi yanıt: aktif olarak yeniden yayınlanıyor ve ödeme yapıyor
Yabancı medya: Çin'in mobil ödemeleri teknolojinin zirvesine ulaştı mı? Çinli netizenler: Aslında savunmasız
Ülkenin ilk soğuk dalga mavi uyarısı burada! Sichuan'ın sıcaklığı önümüzdeki üç gün içinde 5-8 düşecek
To Top