Redis之持久化与一致性

Redis之持久化与一致性

一、 对象序列化

1.1. 将对象转成JSON字符串

创建一个实体类:

@Data
public class UserEntity {
    private String name;
    private String pass;
    private Integer age;
}

对象转字符串

@RestController
public class RedisController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/addData")
    public String add() {
        UserEntity userEntity = new UserEntity();
        userEntity.setAge(12);
        userEntity.setName("张三");
        userEntity.setPass("123456");
        stringRedisTemplate.opsForValue().set("user", JSONObject.toJSONString(userEntity));
        return "success";
    }

}

结果:

1.2. 将对象序列化后存储(二进制)

需要实现序列换接口:

@Data
class UserEntity implements Serializable {
    private static final long serialVersionUID = -2700793157456551921L;
    private String name;
    private String pass;
    private Integer age;
}

设置和获取:

@RestController
public class RedisController {
	/** 使用@Autowired会报错,使用@Resource通过名字获取注入的类 */
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /** 设置 */
    @GetMapping("/addData")
    public String add() {
        UserEntity userEntity = new UserEntity();
        userEntity.setAge(12);
        userEntity.setName("张三");
        userEntity.setPass("123456");
        redisTemplate.opsForValue().set("user", userEntity);
        return "success";
    }

    /** 获取 */
    @GetMapping("/getDate")
    public UserEntity get() {
        UserEntity user = (UserEntity) redisTemplate.opsForValue().get("user");
        return user;
    }

}

结果:

获取:

二、 持久化机制

2.1. 全量同步和增量同步的区别

全量同步: 就是每天定时(避开高峰期)或者采用一个周期实现将数据拷贝到一个地方也就是RDB存储。

增量同步: 比如采用对行为的操作实现对数据的同步,也就是AOF

全量与增量的比较: 增量同步比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。

2.2. RDBAOF实现持久化的区别

Redis提供了两种持久化的机制,分别为RDBAOF实现,RDB采用定时(全量)持久化机制,但是服务器因为某种原因宕机后可能数据会丢失,AOF是基于数据日志操作实现的持久化,所以AOF采用增量同步的方案。

Redis已经帮助我默认开启了RDB存储。

2.3. RedisRDB同步配置

开启RDB同步配置:

# Redis默认采用rdb方式实现数据的持久化,以快照的形式将数据持久化到磁盘的是一个二进制的文件dump.rdb

RDB相关配置

# Redis会将数据集的快照dump到dump.rdb文件中,可以通过配置文件来修改Redis服务器dump快照的频率.
save 900 1    # 在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10   # 在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 # 在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

RDB同步流程:

2.4. RedisAOF同步配置

AOF是以执行命令的形式实现同步

开启AOF同步:

# redis.conf文件中将 appendonly从no改为yes
appendonly yes

AOF相关配置:

appendfsync always    # 每次有数据修改发生时都会写入AOF文件,能够保证数据不丢失,但是效率非常低。
appendfsync everysec  # 每秒钟同步一次,可能会丢失1s内的数据,但是效率非常高。
appendfsync no        # 从不同步。高效但是数据不会被持久化。

同步流程:

三、Springboot整合注解版Redis

开启缓冲注解:

@SpringBootApplication
@EnableCaching
public class RedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class, args);
    }

}

控制器上使用:

@RestController
public class RedisController {

    @GetMapping("/getDate")
    @Cacheable(cacheNames = "user", key = "'getDate'")
    public UserEntity get() {
        UserEntity userEntity = new UserEntity();
        userEntity.setAge(12);
        userEntity.setName("张三");
        userEntity.setPass("123456");
        return userEntity;
    }

}

这里需要注意,实体类UserEntity需要实现序列化的接口,因为Redis注解缓冲使用的二进制对象缓冲,否则会报一下SerializationFailedException异常:

{
    "timestamp":"2019-12-02T15:33:34.162+0000",
    "status":500,
    "error":"Internal Server Error",
    "message":"Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.mly.redis.UserEntity]",
    "path":"/getDate"
}

所以实体类需要和上一个例子一样:

class UserEntity implements Serializable {
    private static final long serialVersionUID = -2700793157456551921L;
    private String name;
    private String pass;
    private Integer age;
}

四、 一致性解决同步问题

MySQLRedis一致性问题的解决

  • 直接清除Redis的缓冲,重新读取数据库
  • 使用mq异步订阅MySQLbinlog实现增量同步
    • 使用alibabacancal github地址:https://github.com/alibaba/canal/wiki

五、所有例子的依赖文件

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章