springboot+redis+mybatis体会布隆过滤器

2024-08-31 06:28

本文主要是介绍springboot+redis+mybatis体会布隆过滤器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.建立数据库表和对应实体类

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`uname` varchar(50) DEFAULT NULL,`usex` varchar(20) DEFAULT NULL,`uage` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1319 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
public class User {private String id;private String uname;private String usex;private String uage;public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}public String getUsex() {return usex;}public void setUsex(String usex) {this.usex = usex;}public String getUage() {return uage;}public void setUage(String uage) {this.uage = uage;}public String getId() {return id;}public void setId(String id) {this.id = id;}
}

2.编写Controller,新增用户和获取用户

@Controller
public class BloomController {@Autowiredprivate BloomService bloomService;@RequestMapping(value = "/addUser")@ResponseBodypublic void addUser(){for(int i=0;i<100;i++){User user = new User();user.setUsex(i + "");user.setUname("user:" + i);user.setUage("26");bloomService.addUser(user);}}@RequestMapping(value = "/getUser")@ResponseBodypublic User getUser(HttpServletRequest request){String userId = request.getParameter("userId");User user = bloomService.getUser(userId);return  user;}}

3.编写servie,实现具体的业务逻辑

public interface BloomService {void addUser(User user);User getUser(String userId);List<String> getUserIds();
}
@Service
public class BloomServiceImpl implements BloomService {public static final String redisKey = "USER:";@Resourceprivate BloomDao bloomDao;@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate BloomCheckUtil bloomCheckUtil;@Overridepublic void addUser(User user) {int i = bloomDao.addUser(user);if(i>0){//mysql插入成功,将数据存入redisUser currentUser = bloomDao.getUser(user.getId());redisTemplate.opsForValue().set(redisKey+user.getId(), JSONObject.toJSONString(currentUser));}}@Overridepublic User getUser(String userId) {User user = null;//1.先从布隆过滤器中获取数据,若没有则直接返回if(!bloomCheckUtil.check(userId)){System.out.println("该用户id:" + userId +"不在合法用户内!!!!");return user;}//2.从redis中查找String rediskey = redisKey + userId;String jsonObj = Optional.ofNullable(redisTemplate.opsForValue().get(rediskey)).map(Object::toString).orElse(null);if(jsonObj == null){//3.redis中没有,查询数据库user = bloomDao.getUser(userId);if(user != null){//4.redis无mysql有,把查询出的数据写入到redis缓存redisTemplate.opsForValue().set(rediskey,JSONObject.toJSONString(user));}return user;}user =JSONObject.parseObject(jsonObj, User.class) ;return user;}@Overridepublic List<String> getUserIds() {return bloomDao.getUserIds();}
}

4.编写dao和mapper,实现数据库操作

public interface BloomDao {int addUser(@Param("user") User user);User getUser(@Param("id")String id);List<String> getUserIds();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cn.study.redis.dao.BloomDao"><insert id="addUser"  parameterType="com.cn.study.redis.pojo.User" useGeneratedKeys="true" keyProperty="id">insert into user(uname,usex,uage) values (#{user.uname},#{user.usex},#{user.uage})</insert><select id="getUser" resultType="com.cn.study.redis.pojo.User">select u.id ,u.uname ,u.usex ,u.uage  from user u where u.id = #{id}</select><select id="getUserIds" resultType="String">select id from user</select>
</mapper>

5.编写布隆过滤器和工具类

@Component
public class BloomFilter {public static final String key = "LEGITIMATE_USER";@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate BloomService bloomService;@PostConstructpublic void init(){//初始化布隆过滤器//1.从数据库查出user表中的所有id,计算hash值List<String> userIdList = bloomService.getUserIds();for(int i=0;i<userIdList.size();i++){//对每个userId计算hash值并取绝对值int hashValue = Math.abs(("USER:" + userIdList.get(i)).hashCode());//使用hash值对2的32次方取余,得到下标long index = (long)(hashValue % Math.pow(2,32));System.out.println("id为:" + userIdList.get(i)+"的用户产生的hash值为:" + hashValue +",下标为:" + index);//将redis中对应下标的bitmap的值更新成1redisTemplate.opsForValue().setBit(key,index,true);}}
}
@Component
public class BloomCheckUtil {private static final String key = "LEGITIMATE_USER";@Autowiredprivate RedisTemplate redisTemplate;public boolean check(String userId){boolean flag = false;int hashValue = Math.abs(("USER:" + userId).hashCode());long index = (long)(hashValue % Math.pow(2,32));flag = redisTemplate.opsForValue().getBit(key,index);return flag;}}

7.验证

由于第一次启动项目的时候,BloomFilter 类中的init方法会在一开始执行,此时我还并没有调用addUser方法添加用户,数据库中没有任何用户信息,所以第一次启动项目的时候,布隆过滤器中不会有任何的数据。
我们启动项目后,手动调用下addUser方法,新增100条用户数据。
然后重启项目,将用户信息加载到布隆过滤器中。
我们调用getUser方法尝试获取用户信息,当我们传了一个数据库不存在的用户id时,当请求到布隆过滤器,布隆过滤器发现没有此数据,则直接返回,不会再往下查redis和mysql
在这里插入图片描述

这篇关于springboot+redis+mybatis体会布隆过滤器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123137

相关文章

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows