当前位置: 首页 > news >正文

Redission分布式锁、WatchDog续约、布隆过滤器

参考资料:

参考视频

参考博客

学习笔记及参考demo


概述:

        首先需要搭建SpringBoot框架,具体参照本人前面的博客。


Redission分布式锁:

依赖

        <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.21.3</version></dependency>

添加配置


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.redisson.config.Config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient(){// 配置Config config = new Config();config.useSingleServer().setAddress("redis://192.168.154.150:6379").setDatabase(0)//setAddress("redis://127.0.0.1:6379");//.setPassword("password");// 创建RedissonClient对象return Redisson.create(config);}
}

控制层


import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.TimeUnit;@RestController
@Slf4j
public class ServerController {@Autowiredprivate RedissonClient redissonClient;/*** 模拟一个服务获取分布式锁  并且更新数据* @param leaseTime 锁施放时间 -1 表示开启watchdog  自动续约  其他的时间为锁自动释放时间* @return*/@RequestMapping("firstRequset")public ResponseEntity<String> firstRequset(@RequestParam("leaseTime")Long leaseTime){try {//获取锁(可重入),指定锁的名称/*** 在 Redisson 中,锁的名称是唯一标识锁的依据,* 因此,只要你在 Redisson 中使用 getLock 方法并传入锁的名称,* Redisson 会在 Redis 中为该名称创建一个锁。你无需手动创建锁,只要使用时保证锁名称唯一且一致即可。** 锁的创建:** Redisson 使用的是 Redis 中的 SETNX(set if not exists)命令来实现分布式锁的原理,* 当你使用 getLock("anyLock") 时,它会在 Redis 中设置一个与名称对应的键(如 anyLock),* 该键的过期时间为你设定的自动释放时间。只要该键存在,其他客户端就无法获得锁。*/RLock lock = redissonClient.getLock("anyLock");/*** 尝试获取锁,参数分别是:* 获取锁的最大等待时间(期间会重试),* 锁自动释放时间,-1 会开启watchdog* 时间单位*/boolean isLock = lock.tryLock(1,leaseTime, TimeUnit.SECONDS);//判断获取锁成功if(isLock){log.info("服务器1-获取锁成功,{}",leaseTime==-1L?"开启自动续约状态":"锁自动释放时间:"+leaseTime);try{//  执行业务Thread.sleep(50_000);log.info("服务器1-执行业务-进行重要数据库字段计算更新");}finally{//释放锁try {lock.unlock();log.info("服务器1-释放锁成功");} catch (Exception e) {log.info("服务器1-释放锁异常,锁已经过期,并且未续约:{}",e);}return new ResponseEntity<String>("执行成功",HttpStatus.OK);}}else{log.info("服务器1-未获取到锁");return new ResponseEntity<String>("未获取到锁",HttpStatus.OK);}}catch (Exception e){e.printStackTrace();}return new ResponseEntity<String>("执行失败",HttpStatus.OK);}// 模拟一个服务获取分布式锁  并且更新数据@RequestMapping("secondRequset")public ResponseEntity<String> secondRequset(@RequestParam("leaseTime")Long leaseTime){try {//获取锁(可重入),指定锁的名称RLock lock = redissonClient.getLock("anyLock");//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位boolean isLock = lock.tryLock(1,10, TimeUnit.SECONDS);//判断获取锁成功if(isLock){try{log.info("服务器2-获取锁成功,{}",leaseTime==-1L?"开启自动续约状态":"锁自动释放时间:"+leaseTime);//执行业务Thread.sleep(1_000);log.info("服务器2-执行业务-进行重要数据库字段计算更新");}finally{//释放锁try {lock.unlock();log.info("服务器2-释放锁成功");} catch (Exception e) {log.info("服务器2-释放锁异常,锁已经过期,并且未续约:{}",e);}return new ResponseEntity<String>("执行成功",HttpStatus.OK);}}else{log.info("未获取到锁");return new ResponseEntity<String>("未获取到锁",HttpStatus.OK);}}catch (Exception e){e.printStackTrace();}return new ResponseEntity<String>("执行失败",HttpStatus.OK);}
}

WatchDog续约

        只需要将参数leaseTime设置为-1,系统就会默认开启,分布式锁无限续约,直到业务执行完成。


布隆过滤器:

依赖

<!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

YAML配置

server:port: 8080
spring:redis:host: 192.168.154.150port: 6379password: nulldatabase: 0timeout: 10000jedis:pool:max-active: 10max-idle: 5min-idle: 1cache:type: redis

配置


import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;@Service
@Slf4j
public class BloomFilterService {private static final String BLOOM_NAME = "my_bloom_filter";@Autowiredprivate RedissonClient redissonClient;@Autowiredprivate RedisTemplate<String, String> redisTemplate;@PostConstructpublic void initOnStartup() {initBloomFilter();}public void initBloomFilter() {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(BLOOM_NAME);// 假设你只有 100W 数据bloomFilter.tryInit(1_000_000L, 0.01); // 1百万,误判率 1%// 全量扫描 Redis keyScanOptions options = ScanOptions.scanOptions().count(100000).match("*").build();try (Cursor<byte[]> cursor = redisTemplate.getConnectionFactory().getConnection().scan(options)) {while (cursor.hasNext()) {String key = new String(cursor.next(), StandardCharsets.UTF_8);bloomFilter.add(key);}} catch (IOException e) {throw new RuntimeException("初始化布隆过滤器失败", e);}}/*** 增量更新:新增数据时加入布隆过滤器*/public void add(String key) {log.info("新增数据: " + key);RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(BLOOM_NAME);bloomFilter.add(key);}/*** 查询是否存在*/public boolean mightContain(String key) {log.info("查询数据: " + key);RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(BLOOM_NAME);return bloomFilter.contains(key);}
}

布隆过滤器的一些使用方式


import com.example.springbootredisdemo.config.bloom.BloomFilterService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/bloom")
@Slf4j
public class BloomController {@Autowiredprivate BloomFilterService bloomFilterService;// 新增数据@PostMapping("/add")public String add(@RequestParam String key) throws Exception{Thread.sleep(1000);log.info("新增数据完成: " + key);bloomFilterService.add(key);return "已添加: " + key;}// 查询@GetMapping("/check")public String check(@RequestParam String key) throws Exception{Thread.sleep(1000);log.info("查询数据: " + key);boolean exist = bloomFilterService.mightContain(key);return exist ? "可能存在: " + key : "不存在: " + key;}
}

布隆过滤器的其他方式

Guava过滤器(推荐)

依赖
        <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.2-jre</version></dependency>
代码
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;public class GuavaBloomFilterDemo {public static void main(String[] args) {// 预计插入数据量int expectedInsertions = 1000;// 误判率double fpp = 0.01; // 1%// 创建布隆过滤器BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(java.nio.charset.StandardCharsets.UTF_8), // 字符串的 FunnelexpectedInsertions,fpp);// 添加元素bloomFilter.put("123");bloomFilter.put("abc2113");bloomFilter.put("abc2413");// 判断元素是否存在(可能存在误判)System.out.println(bloomFilter.mightContain("123"));       // trueSystem.out.println(bloomFilter.mightContain("abc21313"));  // false (可能存在误判)}
}

Hutool过滤器

依赖
        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency>
代码

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.bloomfilter.BloomFilter;
import cn.hutool.bloomfilter.filter.DefaultFilter;
import cn.hutool.bloomfilter.filter.ELFFilter;
import cn.hutool.bloomfilter.filter.JSFilter;public class HutoolBloomExample {public static void main(String[] args) {BloomFilter[] filters = new BloomFilter[]{new DefaultFilter(10*32),new ELFFilter(10*32),new JSFilter(10*32)};BitMapBloomFilter bloomFilter = new BitMapBloomFilter(10, filters);// 添加数据bloomFilter.add("apple");bloomFilter.add("banana");bloomFilter.add("orange");// 查询System.out.println(bloomFilter.contains("apple"));   // trueSystem.out.println(bloomFilter.contains("grape"));   // false (极少可能 true)}
}

http://www.dtcms.com/a/457403.html

相关文章:

  • 《jQuery 捕获》
  • 【开题答辩全过程】以 阿歹果园养鸡场管理系统为例,包含答辩的问题和答案
  • 【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
  • 河北做网站哪家公司好广州市网站建设公
  • AI学习日记——卷积神经网络(CNN):卷积层与池化层的概念
  • JavaScript中的axios
  • 我们提供的网站建设响应式网站 尺寸
  • Robotframework 并发执行
  • 兰州拼团网站建设网站建设知识点的总结
  • 做门窗的建网站怎么赚钱网页设计图片怎么变小
  • 第十六篇: 算法复杂度分析:大O表示法实战指南
  • 网站倍攻击wordpress 换行符
  • 【PyTorch】神经风格迁移
  • LabVIEW运行时快捷菜单创建
  • 用rp怎么做网站原型网站开发包括后台 前台
  • asp.net网站运行助手wordpress哪个php版本好
  • Python网络编程——TCP编程
  • 手机网站建站费用网站的死链
  • docker容器技术
  • 线程与进程理论知识入门
  • 从零搭建 RAG 智能问答系统2:实现chainlit个性化设计以及文件上传预览
  • AI智能体(Agent)大模型入门【11】--基于llamaindex框架和fastapi框架完善页面和大语言模型对话的一些扩展接口
  • Linux进程第六讲——深入理解fork系统调用(下)
  • 织梦网站模板免费网站ico制作
  • 邹城网站建设多少钱做的比较好看的网站
  • Python 运算符与列表(list)
  • 鸿蒙NEXT Basic Services Kit:打造更稳固的应用基石
  • 使用 OpenAPI 构建 API 文档
  • 【C语言基础】03. 函数详解:从概念到高级应用
  • 精通C语言(2.结构体)(内含彩虹)