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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章