0
点赞
收藏
分享

微信扫一扫

SpringBoot+Redis整合

乌龙茶3297 2023-11-13 阅读 48

SpringBoot+Redis整合

一.操作Json

1.1 pom文件

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.7.17</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.2.2</version>
        </dependency>
        <!--redis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
    
    
    <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
    </dependency>
    
    </dependencies>

2.创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String pwd;
}

3.通用类

​ JedisPoolUtil

4.测试类

@Test
    public void test01(){
        Jedis jedis= JedisPoolUtils.getJedis();
        User user=new User(1,"张三","666");
        String jsonString = JSONObject.toJSONString(user);
        //存数据擦操作
        //设置数据到redis服务器
        jedis.set("user:1",jsonString);
        System.out.println(jedis.get("user:1"));
        
        //从redis服务器取数据操作
        //将字符串的格式转回Object类型;
        //parseObject(json字符串,User.class);
        User user2= JSONObject.parseObject(jedis.get("user:1"), User.class);
        System.out.println(user2);
        jedis.close();
        jedis.close();
    }

image-20231111192450978

5.集合测试类

@Test
    public void test02(){
        Jedis jedis= JedisPoolUtils.getJedis();
        List<User> userList = Arrays.asList(new User(2,"万凯","888"),new User(3,"tom","989"));
        String jsonString = JSONArray.toJSONString(userList);
        //存数据到redis服务器
        jedis.set("userList",jsonString);
        System.out.println(jedis.get("userList"));
        //将字符串转回来;
        String str=jedis.get("userList");
		
        //从redis服务器取数据操作;
         List<User>list= JSONArray.parseArray(str, User.class);
        //lambda方式;
         list.forEach(System.out::println);
        
        //之前的操作方式
         for (User user : userList2) {
            System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getPwd());
        }
         jedis.close();
    }

image-20231111192603750

二.整合RedisTemplate

SpringData

JDBCTemplate

jedis客户端,存在如下不足:

  1. connection管理缺乏自动化,connection-pool的设计缺少必要的容器支持。
  2. 数据操作需要关注“序列化”/“反序列化”,因为jedis的客户端API接受的数据类型为string和byte,对结构化数据(json,xml,pojo等)操作需要额外的支持。
  3. 事务操作纯粹为硬编码。
  4. pub/sub功能,缺乏必要的设计模式支持,对于开发者而言需要关注的太多。

spring-data-redis针对jedis提供了如下功能:

  • 1.连接池自动管理,提供了一个高度封装的“**RedisTemplate”**类

  • 2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口

    ValueOperations:String简单K-V操作
    SetOperations:set类型数据操作
    ZSetOperations:zset类型数据操作
    HashOperations:针对map类型的数据操作
    ListOperations:针对list类型的数据操作
    
  • 3.提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即

    BoundKeyOperations
    BoundValueOperations
    BoundSetOperations
    BoundListOperations
    BoundSetOperations
    BoundHashOperations
    
  • 4.将事务操作封装,有容器控制。

  • 5.针对数据的“序列化/反序列化”,提供了多种可选择策略.

    RedisTemplate中API使用

2.1增加jar包依赖

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.17</version>
    </parent>

		<!--  data-redis依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.5</version>
        </dependency>
 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

2.2 测试代码

编写启动类

@SpringBootApplication
public class RedisApp {
    public static void main(String[] args) {
        SpringApplication.run(RedisApp.class);
    }
}

编写配置类

package com.yh.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        //使用jackson进行序列化
        Jackson2JsonRedisSerializer jsonRedisSerializer =
                new Jackson2JsonRedisSerializer(Object.class);
        //规定序列化规则
        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 第一个参数指的是序列化的域,ALL指的是字段、get和set方法、构造方法
         * 第二个参数指的是序列化哪些访问修饰符,默认是public,ANY指任何访问修饰符
         */
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //指定序列化输入的类型,类必须是非final修饰的类
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jsonRedisSerializer.setObjectMapper(objectMapper);
        //序列化key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = RedisApp.class)
public class Demo03 {
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    /**
     * 对redisTemplate的依赖
     */

    @Test
    public void test03(){
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set("name","chenguang");
        System.out.println(opsForValue.get("name"));
    }
    @Test
    public void test04(){
        User user=new User(5,"tomhs","tttt");
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set("user"+user.getId(),user);

        User u = (User) opsForValue.get("user" + user.getId());
        System.out.println(u);
    }
    @Test
    public void test05(){
        List<User> userList = Arrays.asList(new User(2,"smith","99999"),new User(3,"king","kkkk"));
        ValueOperations opsForValue = redisTemplate.opsForValue();
    }
}

单对象格式:

image-20231113122235039

列表格式:

image-20231113122409213

三.布隆过滤器测试

​ 布隆过滤器本质上是一种数据结构,是一种巧妙的概率型数据结构,用来高效的插入和查询.作用是用来告诉使用者某样东西一定不存在或者可能存在。使用多个哈希函数,将一个数据映射到位图结构中。

查询某个变量的时候,只要这些对应的点是否是都是1:

  • 如果这些点有一个0,则被查询的变量一定不存在.
  • 如果都是1,则被查询的变量可能存在
  • image-20231112223815792
		<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>

JAVA代码测试

	private static int size = 1000000;//预计要插入多少数据
    private static double fpp = 0.01;//期望的误判率
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);

    public static void main(String[] args) {
        //插入数据
        for (int i = 0; i < 1000000; i++) {
            bloomFilter.put(i);
        }
        int count = 0;
        for (int i = 1000000; i < 2000000; i++) {
            if (bloomFilter.mightContain(i)) {
                count++;
                System.out.println(i + "误判了");
            }
        }
        System.out.println("总共的误判数:" + count);
    }

使用場景

布隆过滤器适用场景

1.网页爬虫中对URL的去重,避免爬取相同的URL地址
2.垃圾邮件过滤,从数十亿个垃圾邮件列表中判断邮箱是否是垃圾邮箱
3.秒杀系统,查看用户是否重复购买
4.数据库防止穿库。 Google Bigtable,HBase 和 Cassandra 以及 Postgresql 使用BloomFilter来减少不存在的行或列的磁盘查找。避免代价高昂的磁盘查找会大大提高数据库查询操作的性能。
业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。
5.缓存宕机、缓存击穿场景,一般判断用户是否在缓存中,如果在则直接返回结果,不在则查询db,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应,这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则穿透到db。如果不在布隆器中,则直接返回。
举报

相关推荐

0 条评论