redis使用watch秒殺搶購(gòu)實(shí)現(xiàn)思路
本文實(shí)例為大家分享了redis使用watch秒殺搶購(gòu)的具體代碼,供大家參考,具體內(nèi)容如下
1、使用watch,采用樂(lè)觀鎖
2、不使用悲觀鎖,因?yàn)榈却龝r(shí)間非常長(zhǎng),響應(yīng)慢
3、不使用隊(duì)列,因?yàn)椴l(fā)量會(huì)讓隊(duì)列內(nèi)存瞬間升高
代碼:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import redis.clients.jedis.Jedis;
/**
* redis測(cè)試搶購(gòu)
*
* @author 10255_000
*
*/
public class RedisTest {
public static void main(String[] args) {
final String watchkeys = "watchkeys";
ExecutorService executor = Executors.newFixedThreadPool(20);
final Jedis jedis = new Jedis("192.168.3.202", 6379);
jedis.set(watchkeys, "0");// 重置watchkeys為0
jedis.del("setsucc", "setfail");// 清空搶成功的,與沒(méi)有成功的
jedis.close();
for (int i = 0; i < 10000; i++) {// 測(cè)試一萬(wàn)人同時(shí)訪問(wèn)
executor.execute(new MyRunnable());
}
executor.shutdown();
}
}
import java.util.List;
import java.util.UUID;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class MyRunnable implements Runnable {
String watchkeys = "watchkeys";// 監(jiān)視keys
Jedis jedis = new Jedis("192.168.3.202", 6379);
public MyRunnable() {
}
@Override
public void run() {
try {
jedis.watch(watchkeys);// watchkeys
String val = jedis.get(watchkeys);
int valint = Integer.valueOf(val);
String userifo = UUID.randomUUID().toString();
if (valint < 10) {
Transaction tx = jedis.multi();// 開啟事務(wù)
tx.incr("watchkeys");
List<Object> list = tx.exec();// 提交事務(wù),如果此時(shí)watchkeys被改動(dòng)了,則返回null
if (list != null) {
System.out.println("用戶:" + userifo + "搶購(gòu)成功,當(dāng)前搶購(gòu)成功人數(shù):"
+ (valint + 1));
/* 搶購(gòu)成功業(yè)務(wù)邏輯 */
jedis.sadd("setsucc", userifo);
} else {
System.out.println("用戶:" + userifo + "搶購(gòu)失敗");
/* 搶購(gòu)失敗業(yè)務(wù)邏輯 */
jedis.sadd("setfail", userifo);
}
} else {
System.out.println("用戶:" + userifo + "搶購(gòu)失敗");
jedis.sadd("setfail", userifo);
// Thread.sleep(500);
return;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jedis.close();
}
}
}
Redis對(duì)事物的支持目前比較簡(jiǎn)單。Redis只能保證一個(gè)client發(fā)起的事務(wù)中的命令可以連續(xù)的執(zhí)行,但后面命令出錯(cuò)前面不會(huì)回滾。而中間不會(huì)插入其他client的命令。當(dāng)一個(gè)client在找一個(gè)連續(xù)中發(fā)出multi命令時(shí),這個(gè)鏈接會(huì)進(jìn)入一個(gè)事務(wù)上下文,該鏈接后續(xù)的命令不會(huì)立即執(zhí)行,而是先放到隊(duì)列中,當(dāng)執(zhí)行exec命令是,redis會(huì)順序的執(zhí)行隊(duì)列中的所有命令。當(dāng)如果隊(duì)列中有命令錯(cuò)誤,不會(huì)回滾。
樂(lè)觀鎖:大多數(shù)是基于數(shù)據(jù)版本(version)的記錄機(jī)制實(shí)現(xiàn)的。即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表添加一個(gè)”version”字段來(lái)實(shí)現(xiàn)讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)+1。此時(shí),將提交數(shù)據(jù)的版本號(hào)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄版本號(hào)進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)去數(shù)據(jù)。
在Redis中,使用watch命令實(shí)現(xiàn)樂(lè)觀鎖(watch key):
watch命令會(huì)監(jiān)視給定的key,當(dāng)exec時(shí),如果監(jiān)視的key從調(diào)用watch后發(fā)生過(guò)變化,則事務(wù)會(huì)失敗,也可以調(diào)用wathc多長(zhǎng)監(jiān)視多個(gè)key。這樣就可以對(duì)指定key加樂(lè)觀鎖了。注意watch的可以是對(duì)整個(gè)連接有效的。事務(wù)也一樣。如果連接斷開,監(jiān)視和事務(wù)都會(huì)被自動(dòng)清除。當(dāng)然exec,discard,unwatch命令都會(huì)清除連接中的所有監(jiān)視。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
高并發(fā)下Redis精確計(jì)數(shù)與時(shí)間窗口過(guò)期的方法詳解
在實(shí)時(shí)數(shù)據(jù)處理系統(tǒng)中,我們經(jīng)常需要統(tǒng)計(jì)某個(gè)事件在特定時(shí)間窗口內(nèi)的發(fā)生次數(shù),本文將詳細(xì)介紹如何基于 Redis 實(shí)現(xiàn)高性能、高可用的計(jì)數(shù)方案,需要的可以參考下2025-03-03
Redis核心原理與實(shí)踐之字符串實(shí)現(xiàn)原理
這本書深入地分析了Redis常用特性的內(nèi)部機(jī)制與實(shí)現(xiàn)方式,內(nèi)容源自對(duì)Redis源碼的分析,并從中總結(jié)出設(shè)計(jì)思路、實(shí)現(xiàn)原理。對(duì)Redis字符串實(shí)現(xiàn)原理相關(guān)知識(shí)感興趣的朋友一起看看吧2021-09-09
Redis批量生成數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了Redis批量生成數(shù)據(jù)的實(shí)現(xiàn),主要介紹了兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
windows下通過(guò)批處理腳本啟動(dòng)redis的操作
本文主要給大家介紹了windows下通過(guò)批處理腳本啟動(dòng)redis的操作,windows下redis啟動(dòng),需要進(jìn)入redis安裝目錄,然后shift+右鍵,選擇“在此處打開命令窗口”,然后輸入redis-server.exe redis.conf,就可以啟動(dòng)redis了,文中有詳細(xì)的圖文參考,感興趣的朋友可以參考下2023-12-12
Redis 數(shù)據(jù)庫(kù)忘記密碼找回或重置的解決方法
對(duì)于 Redis 數(shù)據(jù)庫(kù),如果忘記了密碼,可以通過(guò)密碼重置來(lái)找回密碼,今天通過(guò)本文給大家分享Redis 數(shù)據(jù)庫(kù)忘記密碼找回或重置的解決方法,感興趣的朋友一起看看吧2024-01-01
Redis定期刪除過(guò)期數(shù)據(jù)的操作流程
Redis是一種內(nèi)存級(jí)數(shù)據(jù)庫(kù),所有數(shù)據(jù)均存放在內(nèi)存中,內(nèi)存中的數(shù)據(jù)可以通過(guò)TTL指令獲取其狀態(tài),本文給大家介紹了Redis定期刪除過(guò)期數(shù)據(jù)的操作流程,文中通過(guò)代碼示例介紹的講解的非常詳細(xì),需要的朋友可以參考下2024-05-05
Redis?鍵值對(duì)(key-value)數(shù)據(jù)庫(kù)實(shí)現(xiàn)方法
Redis 的鍵值對(duì)中的 key 就是字符串對(duì)象,而 value 可以是字符串對(duì)象,也可以是集合數(shù)據(jù)類型的對(duì)象,比如 List 對(duì)象,Hash 對(duì)象、Set 對(duì)象和 Zset 對(duì)象,這篇文章主要介紹了Redis?鍵值對(duì)數(shù)據(jù)庫(kù)是怎么實(shí)現(xiàn)的,需要的朋友可以參考下2024-05-05
Quarkus集成redis操作Redisson實(shí)現(xiàn)數(shù)據(jù)互通
這篇文章主要為大家介紹了Quarkus集成redis操作Redisson實(shí)現(xiàn)數(shù)據(jù)互通的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02

