欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

redis哨兵模式分布式鎖實(shí)現(xiàn)與實(shí)踐方式(redisson)

 更新時間:2024年03月05日 14:38:32   作者:喵喵@香菜  
這篇文章主要介紹了redis哨兵模式分布式鎖實(shí)現(xiàn)與實(shí)踐方式(redisson),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

一、前言

在某個線程操作數(shù)據(jù)庫中的某條數(shù)據(jù)時,我們需要確保當(dāng)前時刻只有一個線程在操作這條記錄,如果有兩個線程競爭同一個數(shù)據(jù),就需要在考慮先后執(zhí)行順序以后,那么怎樣在一個線程拿到這條數(shù)據(jù)時,阻塞其他線程操作呢?

分布式鎖就可以解決上述難題。

以下演示是利用分布式鎖,確保同一時間只有一個線程在操作數(shù)據(jù)庫,阻塞其他線程。

環(huán)境:

  • redis(哨兵模式)
  • spring boot

二、redis的配置(注意是哨兵模式)

1)依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zlc</groupId>
    <artifactId>distributedlock-a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>distributedlock-a</name>
    <description>分布式鎖(哨兵模式)</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.3.2</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2)redis配置

server:
  port: 8081
spring:
  redis:
    sentinel:
      master: testmaster
      nodes: 127.0.0.1:26379,127.0.0.1:36379,127.0.0.1:16379
    timeout: 3000          # 超時時間(數(shù)據(jù)處理超時時間,不是連接超時時間)
    lettuce:
      pool:
        max-active: 200     #連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
        max-idle: 20        #連接池中的最大空閑連接
        min-idle: 5         #連接池中的最小空閑連接
        max-wait: -1        #連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)
    password: 123456        #redis 密碼
    database: 1             # 使用的是庫1,如果不配置,則使用默認(rèn)的0

三、代碼實(shí)戰(zhàn)

根據(jù)上面的配置文件,將redis的各個配置轉(zhuǎn)換為實(shí)體對象

1)sentinel 節(jié)點(diǎn)

package com.zlc.distributedlocka.model.redis;

import lombok.Data;
import lombok.ToString;

/**
 * @author : 追到烏云的盡頭找太陽-(Jacob)
 * @date : 2020/1/20 11:13
 **/
@Data
@ToString
public class RedisSentinelModel {
    
    private String master;

    private String nodes;
}

2)pool節(jié)點(diǎn)

package com.zlc.distributedlocka.model.redis;

import lombok.Data;
import lombok.ToString;

/**
 * @author : 追到烏云的盡頭找太陽-(Jacob)
 * @date : 2020/1/20 11:16
 **/
@Data
@ToString
public class RedisPoolModel {

    private int maxIdle;

    private int minIdle;

    private int maxActive;

    private int maxWait;
    
}

3)Lettuce 節(jié)點(diǎn)

package com.zlc.distributedlocka.model.redis;

import lombok.Data;

/**
 * @author : 追到烏云的盡頭找太陽-(Jacob)
 * @date : 2020/1/20 11:18
 **/
@Data
public class RedisLettuceConfig {
    
    private RedisPoolModel redisPoolModel;
    
}

4)redis

package com.zlc.distributedlocka.model.redis;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author : 追到烏云的盡頭找太陽-(Jacob)
 * @date : 2020/1/20 11:21
 **/
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class RedisModel {

    private int database;
    /**
     * 等待節(jié)點(diǎn)回復(fù)命令的時間。該時間從命令發(fā)送成功時開始計(jì)時
     **/
    private int timeout;

    private String password;

    /**
     * 池配置
     */
    private RedisLettuceModel lettuce;

    /**
     * 哨兵配置
     */
    private RedisSentinelModel sentinel;
}

5)redisson

package com.zlc.distributedlocka.config;

import com.zlc.distributedlocka.model.redis.RedisModel;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SentinelServersConfig;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author : 追到烏云的盡頭找太陽-(Jacob)
 * @date : 2020/1/20 11:27
 **/
@Configuration
@EnableConfigurationProperties(RedisModel.class)
public class RedissonConfig {

    private final RedisModel redisModel;
    
    public RedissonConfig(RedisModel redisModel) {
        this.redisModel = redisModel;
    }

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        String [] nodes = redisModel.getSentinel().getNodes().split(",");
        List<String> newNodes = new ArrayList<>(nodes.length);
        newNodes.addAll(Arrays.asList(nodes));

        SentinelServersConfig serverConfig = config.useSentinelServers()
                .addSentinelAddress(newNodes.toArray(new String[0]))
                .setMasterName(redisModel.getSentinel().getMaster())
                .setReadMode(ReadMode.SLAVE)
                .setTimeout(redisModel.getTimeout());
        // 設(shè)置密碼
        if(StringUtils.isNotBlank(redisModel.getPassword())){
            serverConfig.setPassword(redisModel.getPassword());
        }
        // 設(shè)置database
        if (redisModel.getDatabase()!=0){
            serverConfig.setDatabase(redisModel.getDatabase());
        }
        return Redisson.create(config);
    }
}

四、使用

一個簡單的使用方法示例

package com.zlc.distributedlocka;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.concurrent.TimeUnit;

@SpringBootApplication
public class DistributedlockAApplication {
    
    @Autowired
    private RedissonClient redissonClient;

    public static void main(String[] args) {
        SpringApplication.run(DistributedlockAApplication.class, args);
    }
    
    // 這里的鎖是對哨兵模式下的database生效的,
    // 需要分布式鎖的兩個系統(tǒng)一定要使用同一哨兵模式的database
    // 如果一個使用默認(rèn)0,一個使用1或者其他,是鎖不住的
    private void TestLock(){
        boolean lockFlag = false;
        RLock rLock = null;
        try {
            // 使用redis中的某個key值作為獲取分布式鎖
            rLock = redissonClient.getLock("redisKey");
            //  第一個參數(shù)為等待時間,第二個參數(shù)為占有時間(單位都為毫秒)
            // 等待時間為如果沒有通過redisKey獲取到鎖,則等待1s,1s后還沒獲取到鎖,則tryLock返回false,表明有人正在使用
            // 如果直接獲取到鎖了,則表明沒有人使用,設(shè)置了你占有他的時間為5s
            lockFlag = rLock.tryLock(1000, 5000, TimeUnit.MILLISECONDS);
            if (lockFlag){
                // 獲取到鎖,進(jìn)行數(shù)據(jù)處理或者其他操作
            }else {
                // 沒有獲取到鎖,進(jìn)行一些操作
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 如果鎖沒有釋放,手動釋放鎖
            // 注意是使用isHeldByCurrentThread
            if (lockFlag && rLock.isHeldByCurrentThread()){
                rLock.unlock();
            }
        }
    }
}

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • CentOS7.5使用mysql_multi方式安裝MySQL5.7.28多實(shí)例(詳解)

    CentOS7.5使用mysql_multi方式安裝MySQL5.7.28多實(shí)例(詳解)

    這篇文章主要介紹了CentOS7.5使用mysql_multi方式安裝MySQL5.7.28多實(shí)例,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • Redis集群的三種部署方式及三種應(yīng)用問題的處理

    Redis集群的三種部署方式及三種應(yīng)用問題的處理

    這篇文章主要介紹了Redis集群的三種部署方式及三種應(yīng)用問題的處理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 基于Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄項(xiàng)目示例(附源碼)

    基于Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄項(xiàng)目示例(附源碼)

    手機(jī)登錄驗(yàn)證在很多網(wǎng)頁上都得到使用,本文主要介紹了基于Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄項(xiàng)目示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Redis6.2.6生產(chǎn)環(huán)境redis.conf單機(jī)配置

    Redis6.2.6生產(chǎn)環(huán)境redis.conf單機(jī)配置

    在實(shí)際生產(chǎn)環(huán)境中,為了保障 Redis 的穩(wěn)定性和高性能,我們往往需要對默認(rèn)配置進(jìn)行一系列優(yōu)化,本文主要介紹了Redis6.2.6生產(chǎn)環(huán)境redis.conf單機(jī)配置,感興趣的可以了解一下
    2025-04-04
  • Redis緩存鍵清理問題解決

    Redis緩存鍵清理問題解決

    對于使用redis作為緩存服務(wù)器的開發(fā)者而言,定期清除redis中的緩存數(shù)據(jù)是非常必要的,本文主要介紹了Redis緩存鍵清理問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • redis單線程快的原因和原理

    redis單線程快的原因和原理

    在本篇文章中小編給大家整理了關(guān)于redis單線程為什么快的原因和具體實(shí)例,有興趣的朋友們可以參考下。
    2019-06-06
  • Redis源碼閱讀:Redis字符串SDS詳解

    Redis源碼閱讀:Redis字符串SDS詳解

    這篇文章主要介紹了Redis源碼閱讀:Redis字符串SDS,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • redis如何清理緩存

    redis如何清理緩存

    本文主要介紹了redis如何清理緩存,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Redis源碼環(huán)境構(gòu)建過程詳解

    Redis源碼環(huán)境構(gòu)建過程詳解

    這篇文章主要介紹了Redis源碼環(huán)境構(gòu)建過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • redis集群搭建過程(非常詳細(xì),適合新手)

    redis集群搭建過程(非常詳細(xì),適合新手)

    這篇文章主要介紹了redis集群搭建過程,Redis集群至少需要3個節(jié)點(diǎn),因?yàn)橥镀比蒎e機(jī)制要求超過半數(shù)節(jié)點(diǎn)認(rèn)為某個節(jié)點(diǎn)掛了該節(jié)點(diǎn)才是掛了,所以2個節(jié)點(diǎn)無法構(gòu)成集群,具體搭建過程跟隨小編一起看看吧
    2021-11-11

最新評論