1. 程式人生 > 其它 >用Javascript實現傳送簡訊驗證碼間隔

用Javascript實現傳送簡訊驗證碼間隔

技術標籤:redisspringboot

一、概念

在redis中沒有隔離級別的概念,都是序列化執行。

事務執行過程:是把事務過程中執行的命令放入佇列中(佇列中的命令要麼都執行,要麼都不執行),輸入exec命令開始執行事務

在redis中,單條命令是原子性執行的,但是事務不能保證原子性,且沒有回滾。事務中任意命令執行失敗,其餘命令仍會被執行。

事務的三個階段:

  1. 開始事務
  2. 執行的命令加入佇列
  3. 執行事務或回滾

事務命令:

  • watch key1 key2……:監視一個或多個key,如果事務執行之前,這些key被改動,則事務被打斷。(類似樂觀鎖)
  • multi:事務開始
  • exec:執行事務(執行後無論事務成功還是失敗,watch加的監控都會被取消掉)
  • discard:回滾事務
  • unwatch:取消監視

二、redis客戶端如何使用事務

(1)執行事務

(2)回滾事務

(3)事務中異常

1、事務佇列中存在命令錯誤(類似java編譯錯誤),佇列中所有命令都不執行

2、事務佇列中存在語法性錯誤(類似java執行時異常),出錯的命令不執行,其他命令正常執行

(4)使用watch

1、模擬watch k2 中資料未變動,正常執行的過程如下:

2、模擬watch k2 中資料發生變動,導致事務執行失敗,如圖:

事務中途使用其他客戶端修改k2的值,如下:

三、springboot如何使用事務

有兩種方式使用redis事務,手動開啟自動開啟

redis命令對應的RedisTemplate的方法如下:

        RedisTemplate.multi();
        RedisTemplate.exec();
        RedisTemplate.discard();
        RedisTemplate.watch("");
        RedisTemplate.unwatch()

(1)手動開啟

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void test() {
        //設定事務支援
        stringRedisTemplate.setEnableTransactionSupport(true);
        //開啟事務
        stringRedisTemplate.multi();
        try {
            stringRedisTemplate.opsForValue().set("k","v");
            stringRedisTemplate.opsForValue().set("k1","v1");
            //提交事務
            List<Object> exec = stringRedisTemplate.exec();
            for (Object o : exec) {
                System.out.println(o);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //回滾事務
            stringRedisTemplate.discard();
        }
        String k1 = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1:"+k1);
    }

執行結果列印:

(2)自動開啟

1、pom

        <!--redis客戶端-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--redis事務依賴JDBC事務管理-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--嵌入式資料庫h2。配置了jdbc必須要配置資料庫,為了方便配置h2。如果專案有mysql的話就不需要h2資料庫了-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

2、啟動類註冊StringRedisTemplate類,並開啟事務支援。

@SpringBootApplication
public class DemoApplication {
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        //開啟事務支援(預設是沒有關閉的)
        template.setEnableTransactionSupport(true);
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3、controller

@RestController
public class DemoController {
    @Autowired
   private DemoService demoService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/test")
    public void getValue() throws Exception {
        String k = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1原值:"+k);
        try {
            demoService.test();
        } catch (Exception e) {
            System.out.println("redis事務執行失敗");
        }
        String k1 = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1事務之後的值:"+k1);
    }
}

4、service

@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void test() throws Exception {
        stringRedisTemplate.opsForValue().set("k","v");
        stringRedisTemplate.opsForValue().increment("k1");
        throw new Exception();
    }
}

測試:模擬丟擲異常情況

事務執行失敗,資料沒有被修改