redis思路

数据一致性

查询:先查redis,有则返回查询结果,无则查数据库,并把返回结果set进redis
删改:先把redis中的数据删除。再操作数据库
新增不操作

缓存击穿

当一个热点key过期,但受到大量访问,此时请求同时到达数据库。

解决

访问缓存key失败,加分布式锁redis,访问数据库吧返回数据添加缓存。成功后释放锁。
如果有另一个线程同时访问此失效数据,也会上锁如果上锁失败(redis分布式锁),那么休眠20mm再查缓存
在这里插入图片描述

public User getUser(int id){
    String s = stringRedisTemplate.opsForValue().get(id+"");
    if(StringUtils.hasText(s)){
        return JSONObject.parseObject(s, User.class);
    }
    //1. 未命中,加分布式锁
    Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent(id + "_lock", "lock", 60, TimeUnit.SECONDS);
    if(lock){
        //2. 加锁成功,查询数据库,并写入缓存
        List<User> users = jdbcTemplate.query("select * from user where id= ?",
                new Object[]{id}, new BeanPropertyRowMapper<>(User.class));
        stringRedisTemplate.opsForValue().set(id + "", JSONObject.toJSONString(users.get(0)), 30, TimeUnit.SECONDS);
        //3. 释放锁,解锁的代码要写到finally中
        stringRedisTemplate.delete(id + "_lock");
        return users.get(0);
    }else{
        //4. 加锁失败,休眠20毫秒,继续查询缓存
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {}

        return getUser(id);
    }
}

延时双删

springboot配置redis

不再用原生的数据库连接池。启动器提供了两个封装好的类。可以用来操纵redis中五种数据类型,分别是 redisTemplate StringRedistemplate
1.redisTemplate 支持对象的自动序列化(实现serializable接口),但可读性较差
2.StringRedisTemplate 所有参数要求字符串类型,有对象类型的话需要手动转换
重新指定序列化方式,key序列化和hash序列化都用string value和hashValue都用json
需要在自定义配置类中,重写redistemplate方法,并且重新指一下bean的名字。这样就可以使用自己的配置方法

方法1

@Bean(name = {"redisTemplate"})
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(RedisSerializer.json());
        template.setHashKeySerializer(RedisSerializer.string());
        template.setHashValueSerializer(RedisSerializer.json());
        //把链接工厂设置到template中(为了获得连接)
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

方法2

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //创建 RedisTemplate 对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        //设置 连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //设置key的序列化
        redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);
        redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);

        //设置 value 的序列化
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);

        return redisTemplate;
    }
}

全量同步

slave-redis第一次连接主机时,向master请求数据同步。master通过判断请求中是否包含runid来确定是否是第一次连接。如果是第一次连接。那么把runid和offset(游标:确定同步数据到哪个位置)交给slave保存
master在运行中执行bgsave语句生成rdb文件(新线程),用来发送给slave同步数据。在master生成rdb的过程中,依然可以执行读写操作,这期间产生的数据变化无法写入rdb中,为了避免造成数据的丢失。这期间使用的指令被记录进replication-buffer中,与此同时,slave清空数据加载rdb文件,开始数据同步
最后master把replication-buffer中的命令发送给slave,slave执行命令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值