redis使用场景 ;SpringBoot 整合Redis; 基于RedisTemplate操作Redis 5种数据结构;

Redis 简介

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。------ 来自百度百科。

Redis 常见的应用场景

1. 热点数据的存贮和展示
“热点数据”有两个较明显的特点,其一:这些数据被用户高频率的访问,其二:这些数据的内容不常发生改变。比如说一个购物网站中的商品分类、一个新闻资讯网站的导航栏目等。

2. 最近访问的数据
用户最近访问的数据在数据库中一般用时间类型的字段作为标识,常见的实现方式是通过一段时间差去数据库查询然后把符合条件的记录返回,这种解决方法的缺点是较消性能和耗时。基于Redis 中的List 数据结构来实现这功能避免了这个缺点。下文会详细介绍如何使用。

3. 并发访问
并发访问可以粗糙理解为在某一个时间段有大量的请求访问。比如在某一个时刻秒杀一个商品会并发访问“商品库存”,这会对数据库造成巨大的压力。此时引用Redis 似乎是一个好的解决方案。

4. 排行榜
在关系型数据可以基于Order by 来实现,但是Redis 有更改的解决方案—— Sorted Set 。可以解决关系型数据库的性能瓶颈。

SpringBoot 整合Redis

1. 去官网下载redis 安装到本地。
至于如何安装和启动redis比较简单此处暂省略,之前没接触过redis 的同学可以先去了解redis 的基础命令。
2. 在项目中添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.3.3.RELEASE</version>
        </dependency>

3. 在application文件配置好redis 的基本信息

spring.redis.host=127.0.0.1
spring.redis.port=6379
# redis密码默认为空,我本地redis 密码为123456
spring.redis.password=123456

4. 注入bean 组件


import org.springframework.beans.factory.annotation.Autowired;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @description: redis 配置类
 * @author: Edison
 * @create: 2020-10-18 00:01
 **/
@Configuration
public class RedisConfig {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 缓存redis-redisTemplate
     *
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //TODO:指定大key序列化策略为为String序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        //TODO:指定hashKey序列化策略为String序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
    /**
     * 缓存redis-stringRedisTemplate
     *
     * @return
     */
    @Bean
    public StringRedisTemplate stringRedisTemplate() {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
        return stringRedisTemplate;
    }
}

redis 5种数据结构

数据类型常存储的值常用操作
String字符串、整数或者浮点数对整个字符串或者字符串的其中一部分执行操作对整数和浮点数执行自增或者自减操作
List列表从两端压入或者弹出元素对单个或者多个元素进行修剪,只保留一个范围内的元素
Set无序集合添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素
ZSet有序集合添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名
Hash包含键值对的无序散列表添加、获取、移除单个键值对获取所有键值对检查某个键是否存在

基于RedisTemplate 操作Redis 五种数据结构

1. string(字符串)
String 数据结构应用场景很丰富,可用于计数,存贮字符串 和实体信息等。
存贮字符串 和实体信息例子如下

    private static final Logger log= LoggerFactory.getLogger(RedisTest.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    public User initUser(int id,String name){
        User user = new User();
        user.setId(id);
        user.setName(name);

        return user;
    }
    /**
     * redisTemplate 操作简单的String 数据结构,存储简单的String 类型数据
     */
    @Test
    public  void StringTest(){
        final String value = "this is a String";
        final String key = "redis:redisTemplate:string";
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // set value
        valueOperations.set(key,value);
        //get value
        Object getValue = valueOperations.get(key);
        log.info("redis 读取出的内容:{}",getValue);
        //redis 读取出的内容:this is a String
    }

    /**
     * redisTemplate 操作String 数据结构,存储实体类信息
     * @throws Exception
     */
    @Test
    public void entityTest() throws Exception{
       ValueOperations valueOperations = redisTemplate.opsForValue();
       String key = "redis:test:entity";
       User user = initUser(1,"edison");
       // objectMapper 用于String 与 user 实体类映射
       String value = objectMapper.writeValueAsString(user);
        valueOperations.set(key,value);
        User v =  objectMapper.readValue(valueOperations.get(key).toString(),User.class);
        log.info("redis 读取出的内容:{}",v);
        // redis 读取出的内容:User(id=1, name=edison)
    }

User 实体类

import lombok.Data;
import lombok.ToString;

import java.io.Serializable;

/**
 * @description:
 * @author: Edison
 * @create: 2020-10-18 14:04
 **/
@Data
@ToString
public class User implements Serializable {
    private  int id;
    private String name;

}

2. list(列表)

有序列表,可存list 做为消息队列等;

存贮list集合以及简易消息队列的例子如下:

 
     /**
     * redisTemplate 操作 list 数据结构
     */
    @Test
    public void list(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1,"jack"));
        listUser.add(initUser(2,"lee"));
        listUser.add(initUser(3,"edison"));
        listUser.add(initUser(4,"andy"));
        listUser.add(initUser(5,"lucy"));
        log.info("listUser 中的的信息 {}",listUser);


        String key = "redis:list";
        ListOperations listOperations = redisTemplate.opsForList();

        // 为了每次单元测试运行的结果是一样的,在给这个list 添加元素之前先从缓存中删除这个list
        redisTemplate.delete(key);

        // list 是有序的 尝试从list的左边开始存贮元素
        listOperations.leftPushAll(key, listUser);
        List listUserFromRedis = redisTemplate.opsForList().range(key, 0, -1);
        log.info(" 从redis中读取list信息: {}",listUserFromRedis );
        //[User(id=5, name=lucy), User(id=4, name=andy), User(id=3, name=edison), User(id=2, name=lee), User(id=1, name=jack)]
        //一个很简易的消息队列 ,假设从头到尾去消费队列中的消息;被消费掉的消息将用list 在移除掉
        User consume =  (User) listOperations.rightPop(key);
        log.info(" 被消费掉的消息:" + consume);
        //被消费掉的消息:User(id=1, name=jack)
        log.info(" 此时队列中还存在的消息" + redisTemplate.opsForList().range(key, 0, -1));
        //[User(id=5, name=lucy), User(id=4, name=andy), User(id=3, name=edison), User(id=2, name=lee)]
    }

3. set(集合)
set 特点 无序,不重复
简单来一个存贮读取自然去重的例子

        /**
     *  redisTemplate 操作Set  数据结构,Set 特点无序不重复
     */
    @Test
    public void setTest(){
        List<String> listName = new ArrayList<>();
        listName.add( "Jack");
        listName.add("Mike");
        listName.add("Lee");
        listName.add("Blue");
        listName.add("Edison");
        listName.add("Lee");

        String key = "redis:test:set";
        SetOperations setOperations = redisTemplate.opsForSet();
        for (String name:listName) {
            setOperations.add(key, name);
        }

        Set<String> set = setOperations.members(key);
        log.info("读取到的set:{}",set);
        //读取到的set:[Mike, Jack, Blue, Edison, Lee]
    }

4. zset(sorted set:有序集合)
举一个存贮集合排序输出的例子

    /**
     *  redisTemplate 操作ZSet  数据结构,Set 特点有序不重复
     */
    @Test
    public void zSet(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1, "jack"));
        listUser.add(initUser(4, "mick"));
        listUser.add(initUser(3, "xue"));
        listUser.add(initUser(2, "edison"));

        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        String key = "redis:zSet:test";
        for (User user: listUser
             ) {
            zSetOperations.add(key, user, user.getId());
        }
        long size = zSetOperations.size(key);

        Set<User> setUser = zSetOperations.range(key,0L,size);
        Set<User> setReverseUser =  zSetOperations.reverseRange(key,0L,size);
        log.info("从低到高排行榜:{}",setUser);
        //[User(id=1, name=jack), User(id=2, name=edison), User(id=3, name=xue), User(id=4, name=mick)]
        log.info("从高到低排行榜:{}",setReverseUser);
        //[User(id=4, name=mick), User(id=3, name=xue), User(id=2, name=edison), User(id=1, name=jack)]
    }

5. hash(哈希)
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。

    /**
     *  redisTemplate 操作Map  数据结构
     */
    @Test
       /**
     *  redisTemplate 操作Map  数据结构
     */
    @Test
    public void mapTest(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1, "jack"));
        listUser.add(initUser(4, "mick"));
        listUser.add(initUser(3, "xue"));
        listUser.add(initUser(4, "xue"));
        listUser.add(initUser(2, "edison"));

        String key = "redis:test:map";
        HashOperations hashOperations = redisTemplate.opsForHash();
        for (User user: listUser
        ) {
            hashOperations.put(key, user.getName(), user);
        }
        // 获取全部信息
       Map<String,User> map = hashOperations.entries(key);
        log.info("获取全部信息:{}",map);
        //{jack=User(id=1, name=jack), xue=User(id=4, name=xue), mick=User(id=4, name=mick), edison=User(id=2, name=edison)}
        // 获取指定的实体信息
       User user = (User)hashOperations.get(key,"xue");
        log.info(" 获取指定的实体信息:{}",user);
        //获取指定的实体信息:User(id=4, name=xue)

    }

最后上测试类中完整的代码

package redis;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @description: redis 测试类
 * @author: Edison
 * @create: 2020-10-18 13:46
 **/

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class RedisTest {
    private static final Logger log= LoggerFactory.getLogger(RedisTest.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    public User initUser(int id,String name){
        User user = new User();
        user.setId(id);
        user.setName(name);

        return user;
    }

    /**
     * redisTemplate 操作简单的String 数据结构,存储简单的String 类型数据
     */
    @Test
    public  void StringTest(){
        final String value = "this is a String";
        final String key = "redis:redisTemplate:string";
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // set value
        valueOperations.set(key,value);
        //get value
        Object getValue = valueOperations.get(key);
        log.info("redis 读取出的内容:{}",getValue);
    }

    /**
     * redisTemplate 操作String 数据结构,存储实体类信息
     * @throws Exception
     */
    @Test
    public void entityTest() throws Exception{
       ValueOperations valueOperations = redisTemplate.opsForValue();
       String key = "redis:test:entity";
       User user = initUser(1,"edison");
       // objectMapper 用于String 与 user 实体类映射
       String value = objectMapper.writeValueAsString(user);
        valueOperations.set(key,value);
        User v =  objectMapper.readValue(valueOperations.get(key).toString(),User.class);
        log.info("redis 读取出的内容:{}",v);
    }



    /**
     * redisTemplate 操作 list 数据结构
     */
    @Test
    public void list(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1,"jack"));
        listUser.add(initUser(2,"lee"));
        listUser.add(initUser(3,"edison"));
        listUser.add(initUser(4,"andy"));
        listUser.add(initUser(5,"lucy"));
        log.info("listUser 中的的信息 {}",listUser);


        String key = "redis:list";
        ListOperations listOperations = redisTemplate.opsForList();

        // 为了每次单元测试运行的结果是一样的,在给这个list 添加元素之前先从缓存中删除这个list
        redisTemplate.delete(key);

        // list 是有序的 尝试从list的左边开始存贮元素
        listOperations.leftPushAll(key, listUser);
        List listUserFromRedis = redisTemplate.opsForList().range(key, 0, -1);
        log.info(" 从redis中读取list信息: {}",listUserFromRedis );
        //[User(id=5, name=lucy), User(id=4, name=andy), User(id=3, name=edison), User(id=2, name=lee), User(id=1, name=jack)]
        //一个很简易的消息队列 ,假设从头到尾去消费队列中的消息;被消费掉的消息将用list 在移除掉
        User consume =  (User) listOperations.rightPop(key);
        log.info(" 被消费掉的消息:" + consume);
        //被消费掉的消息:User(id=1, name=jack)
        log.info(" 此时队列中还存在的消息" + redisTemplate.opsForList().range(key, 0, -1));
        //[User(id=5, name=lucy), User(id=4, name=andy), User(id=3, name=edison), User(id=2, name=lee)]
    }

    /**
     *  redisTemplate 操作Set  数据结构,Set 特点无序不重复
     */
    @Test
    public void setTest(){
        List<String> listName = new ArrayList<>();
        listName.add( "Jack");
        listName.add("Mike");
        listName.add("Lee");
        listName.add("Blue");
        listName.add("Edison");
        listName.add("Lee");

        String key = "redis:test:set";
        SetOperations setOperations = redisTemplate.opsForSet();
        for (String name:listName) {
            setOperations.add(key, name);
        }

        Set<String> set = setOperations.members(key);
        log.info("读取到的set:{}",set);
        //读取到的set:[Mike, Jack, Blue, Edison, Lee]
    }

    /**
     *  redisTemplate 操作ZSet  数据结构,Set 特点有序不重复
     */
    @Test
    public void zSet(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1, "jack"));
        listUser.add(initUser(4, "mick"));
        listUser.add(initUser(3, "xue"));
        listUser.add(initUser(2, "edison"));

        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        String key = "redis:zSet:test";
        for (User user: listUser
             ) {
            zSetOperations.add(key, user, user.getId());
        }
        long size = zSetOperations.size(key);

        Set<User> setUser = zSetOperations.range(key,0L,size);
        Set<User> setReverseUser =  zSetOperations.reverseRange(key,0L,size);
        log.info("从低到高排行榜:{}",setUser);
        log.info("从高到低排行榜:{}",setReverseUser);
    }

    /**
     *  redisTemplate 操作Map  数据结构
     */
    @Test
    public void mapTest(){
        List<User> listUser = new ArrayList<>();
        listUser.add(initUser(1, "jack"));
        listUser.add(initUser(4, "mick"));
        listUser.add(initUser(3, "xue"));
        listUser.add(initUser(4, "xue"));
        listUser.add(initUser(2, "edison"));

        String key = "redis:test:map";
        HashOperations hashOperations = redisTemplate.opsForHash();
        for (User user: listUser
        ) {
            hashOperations.put(key, user.getName(), user);
        }
        // 获取全部信息
       Map<String,User> map = hashOperations.entries(key);
        log.info("获取全部信息:{}",map);
        //{jack=User(id=1, name=jack), xue=User(id=4, name=xue), mick=User(id=4, name=mick), edison=User(id=2, name=edison)}
        // 获取指定的实体信息
       User user = (User)hashOperations.get(key,"xue");
        log.info(" 获取指定的实体信息:{}",user);
        //获取指定的实体信息:User(id=4, name=xue)

    }
}



暂时写这么多了,RedisTemplate 有很多API ,有空可以去看看源码。合理使用工具会使工作效率大幅度提升。That is all ,祝各位老板早点下班Many thanks !

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Redis Hash 结构是一数据结构,它允许你将键值对存储为哈希表的形式,其中每个键都是唯一的,并且可以关联任意类型的数据(包括字符串、列表、集合或有序集合)。在 Spring Boot 中整合 Redis,你可以使用 Spring Data Redis 库,它简化了与 Redis 的交互。 Spring Boot 整合 Redis 的步骤如下: 1. 添加依赖:在你的 `pom.xml` 或 `build.gradle` 文件中添加 Spring Data Redis 和相关 Redis客户端库的依赖,如 lettuce 或 Jedis。 ```xml <!-- Maven --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Gradle (Lettuce) --> implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.5.x' implementation 'io.lettuce:lettuce-core:6.0.x' ``` 2. 配置 Redis:在 `application.properties` 或 `application.yml` 中配置 Redis 的连接信息,如主机名、端口和密码(如果有)。 ```yaml spring.redis.host=your-redis-host spring.redis.port=your-redis-port spring.redis.password=your-password ``` 3. 使用 `HashOperations`:Spring Data Redis 提供了 `HashOperations` 接口,你可以通过注入 `RedisTemplate` 或 `HashOperations` 对象来操作 RedisHash 结构。 ```java @Autowired private RedisTemplate<String, Object> redisTemplate; // 使用方法 HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash("your-hash-key"); hashOps.put("field1", "value1"); hashOps.get("field1"); // 获取 value1 ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Edison-XX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值