Redis

什么是Redis

Redis(Remote Dictionary Server )远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存也可持久化的日志型、Key-Value(NoSQL)数据库。

Redis的特点

1.性能极高,读写速度快,基于内存

2.支持多种数据类型,列如string,hash,list,set,zset

3.原子性的,支持事务

4.丰富的特性,支持发布订阅和通知

5.支持持久化,将内存的数据保存在磁盘,重启后再次加载

6.支持分布式,理论上可以无限扩展

7.单线程,没有并发问题,但在5.0版本后支持多线程

应用场景

1. 缓存
2. 分布式锁
3. 分布式Session
4. 消息队列等

Redis数据类型

string(字符串类型)

键值对格式,常用命令有set,get

应用场景:

  1. 缓存

  2. 分布式ID

  3. 分布式锁

  4. 全局Session

  5. 全局计数器

Hash(一个键,多个值)

应用场景:保存对象的多个属性

和string的对比,优势是:可以灵活读写对象的部分属性

常用命令:hmget(读取对象属性),hgetall(读取对象所有属性),hdel(删除对象属性)

List(链表结构)

有序可重复

应用场景:

  1. 模拟数组、栈、队列等数据结构

  2. 线型结构,如:粉丝、点赞列表

  3. 消息队列

常用命令:lpush左入,lpop左出,rpush右入,rpop右出

Set

set是无序的、不可重复的集合。

应用场景:

  1. 点赞数(避免重复)

  2. 社交关系(共同关注、可能认识)

常用命令sadd添加,sismember判断是否有这个元素,sinter取交集,sdiff取差集,sunion取并集

zset

zset是有序的、不可重复的集合。

应用场景:

  1. 排行榜

常用命令:zadd添加, zrangebyscore读取数据

Redis在开发中的使用

编程式缓存

首先想要用Redis必须导入相关依赖

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

再添加配置文件

# 服务器地址
spring.redis.host=localhost
# 端口
spring.redis.port=6379
# 数据库名
spring.redis.database=0
# 最大连接数
spring.redis.jedis.pool.max-active=100
# 最大闲置时间
spring.redis.jedis.pool.max-wait=100ms
# 最大闲置连接数
spring.redis.jedis.pool.max-idle=100
# 最小闲置连接数
spring.redis.jedis.pool.min-idle=10

接下来就需要在config包下创建RedisTemplate配置类

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        // 配置序列化器
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson序列化器
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

然后还需要引入

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

用来解决缺少的依赖

在使用方法上加入注解

@Cacheable(cacheNames = "Student",key = "T(String).valueOf(#id)")

声明式缓存

推荐使用声明式,编程式缓存使用复杂,代码侵入性高,推荐使用声明式缓存,通过注解来实现热点数据缓存。

声明式在编程式的基础上,需要在配置类中额外加入以下代码

@Configuration
public class RedisConfig {

    @Bean
    public RedisCacheConfiguration provideRedisCacheConfiguration(){
        //加载默认配置
        RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig();
        //返回Jackson序列化器
        return conf.serializeValuesWith(
                RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }

然后还需要添加一个

//启动缓存
@EnableCaching注解

最终如下

@Configuration
//启动缓存
@EnableCaching
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        // 配置序列化器
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson序列化器
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;


    @Bean
    public RedisCacheConfiguration provideRedisCacheConfiguration(){
        //加载默认配置
        RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig();
        //返回Jackson序列化器
        return conf.serializeValuesWith(
                RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
}

注意事项,如果我们进行增删改查导致mysql数据与redis数据不一样,mysql数据如果删除了,redis将读到mysql里没有数据,所有我们在做操作的时候,需要使用组合注@Cacing

列如一下代码

public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired
    private StudentMapper studentMapper;
    
    public static final String PREFIX = "Student-";

    @Autowired
    private RedisTemplate<String,Object>redisTemplate;

    @Cacheable(cacheNames = "Student-Page",key = "T(String).valueOf(#current)")
    @Override
    public Page<Student> getStudentPage(Long current, Long size) {
        return studentMapper.selectStudentPage(new Page<>(current,size));
    }
    @Cacheable(cacheNames = "Student",key = "T(String).valueOf(#id)")
    @Override
    public Student getStudentById(Long id){
        return  studentMapper.selectById(id);
    }

    //    @CacheEvict(cacheNames = "Student",key = "T(String).valueOf(#id)")
    //使用组合注解,删除一个学生时,将所有分页缓存删掉
    @Caching(
            evict = {@CacheEvict(cacheNames = "Student", key = "T(String).valueOf(#id)"),
                    @CacheEvict(cacheNames = "Student-Page", allEntries = true)
            }
    )
    @Override
    public void removeStudentById(Long id) {
        studentMapper.deleteById(id);
    }

    //    @CachePut(cacheNames = "Student",key = "T(String).valueOf(#student.stuId)")
    @Caching(
            put = @CachePut(cacheNames = "Student",key = "T(String).valueOf(#student.stuId)"),
            evict = @CacheEvict(cacheNames = "Student-Page", allEntries = true)
    )
    @Override
    public Student updateStudentById(Student student) {
        studentMapper.updateById(student);
        return student;
    }

    //    @CachePut(cacheNames = "Student",key = "T(String).valueOf(#student.stuId)")
    @Caching(
            put = @CachePut(cacheNames = "Student",key = "T(String).valueOf(#student.stuId)"),
            evict = @CacheEvict(cacheNames = "Student-Page", allEntries = true)
    )
    @Override
    public Student addStudent(Student student) {
        studentMapper.insert(student);
        return student;
    }

该代码就是在进行添加,修改,删除的时候,对redis缓存同步进行了删除操作,所有就不出现读到脏数据的情况。

总结

Redis作为一个高性能的键值存储数据库,具有出色的性能和灵活的数据结构。它在诸多场景中展现出独特的优势,如缓存层、会话存储、实时应用程序和统计数据等。通过充分了解Redis的特性和应用,我们可以更好地利用它来构建高效、可扩展的应用程序。希望通过本文的介绍,读者能对Redis有更深入的理解,并能正确使用它来满足不同的需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值