02 jedis以及redis的持久化

1 Redis的连接工具之jedis的使用介绍

1-1 jedis的概述

定义:jedis是连Java应用程序连接redis服务端的工具

其他类似工具:SpringData Redis,Lettuce

可视化连接redis客户端
Redis Desktop Manager
Redis Client
Redis Studio

Lettuce相较于Jedis有哪些优缺点?

maven的依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

1-2 使用jedis进行数据库的连接

import org.junit.Test;
import redis.clients.jedis.Jedis;

public class test1 {
    @Test
    public static void main(String[] args) {
        // 01 连接redis
        Jedis jedis = new Jedis("127.0.0.1",6379);
        // 02 操作redis,注意jedis的操作指令与原生redis保持一致
        jedis.set("I","need_job");
        String res = jedis.get("I");
        System.out.println(res);
        // 03 关闭数据库连接
        jedis.close();
    }
}

执行结果

need_job

1-3 jedis操作基本数据类型

代码

import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.List;
import java.util.Map;

public class test2 {
    @Test
    public void testList() {
        Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.lpush("listI","need","a","job");
        jedis.rpush("listI","I");
        List<String>  list1 = jedis.lrange("listI",0,-1);
        for(String s:list1){
            System.out.print(s+" ");
        }
        System.out.println();
        System.out.println(jedis.llen("list1"));
        System.out.println();
        jedis.close();
    }

    @Test
    public void testHash() {
        Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.hset("hashI","key1","value1");
        jedis.hset("hashI","key2","value2");
        jedis.hset("hashI","key3","value3");
        Map<String,String> hash1 = jedis.hgetAll("hashI");
        System.out.println(hash1);
        System.out.println(jedis.hlen("hashI"));
        System.out.println();
        jedis.close();
    }
}

testList执行结果

{key1=value1, key2=value2, key3=value3}
3

job a need job a need I I 
7

1-4 使用jedis实现规定时间限制操作次数

业务场景解释

案例要求
① 设定A、 B三个用户
② A用户限制3次/10s调用, B用户限制6次/10s调用

基本思想:利用Redis中的string类型数据进行计数,并设置其生命周期。

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;
/*Redis的控制服务*/
@Slf4
public class Service {
    private String id;
    private int num;
    public Service(String id, int num) {
        this.id = id;
        this.num = num;
    }
    public void business(){
        Jedis jedis = new Jedis("127.0.0.1",6379);
        String v = jedis.get(id);
        try{
            if(v == null){
                jedis.setex(id,10, String.valueOf(Long.MAX_VALUE-num));  // 放入 id:初始数值,并设置生命周期为10s
            }else{
                long cur = jedis.incr(id);
                long tmp = num-(Long.MAX_VALUE-cur);           // 剩余次数
                log.warn("用户{} 10s内可调用次数为{},  已经调用{}次",id,num,tmp);
            }
        }catch (JedisDataException e){                                // 通过异常的发生去判断是否     
            log.warn("用户"+id+"调用次数用完, 需要升级账户");
        }finally {
            jedis.close();
        }

    }
}

class MyThread extends Thread{
    private String id;
    private int num;
    Service sc;

    public MyThread(String id, int num) {
        sc = new Service(id,num);
    }

    public void run(){
        while(true){
            sc.business();
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Main{
    public static void main(String[] args) {
        MyThread t1 = new MyThread("1",3);
        MyThread t2 = new MyThread("2",6);
        t1.start();
        t2.start();
    }
}

执行结果:通过对Redis的控制,实现了限定的时间的访问控制(不同用户的限制访问次数可以不同)。

22:46:37.633 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用1次
22:46:37.640 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用1次
22:46:38.649 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用2次
22:46:38.649 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用2次
22:46:39.654 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用3次
22:46:39.654 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用3次
22:46:40.660 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用4次
22:46:40.660 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:41.662 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用5次
22:46:41.662 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:42.669 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:42.669 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用6次
22:46:43.673 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:43.673 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:44.680 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:44.680 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:45.697 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:45.698 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户

22:46:47.705 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用1次
22:46:47.705 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用1次
22:46:48.710 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用2次
22:46:48.710 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用2次
22:46:49.715 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用3次
22:46:49.715 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用3次
22:46:50.719 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:50.719 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用4次
22:46:51.724 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用5次
22:46:51.724 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:52.728 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:52.728 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用6次
22:46:53.732 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:53.732 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:54.737 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:54.737 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户
22:46:55.741 [Thread-1] WARN Service - 用户2调用次数用完, 需要升级账户
22:46:55.741 [Thread-0] WARN Service - 用户1调用次数用完, 需要升级账户

22:46:57.750 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用1次
22:46:57.750 [Thread-1] WARN Service - 用户2 10s内可调用次数为6,  已经调用1次
22:46:58.755 [Thread-0] WARN Service - 用户1 10s内可调用次数为3,  已经调用2次

1-5 jedis对象的管理工具类实现

工具类作用:避免手动管理jedis对象,通过配置文件配置连接。

通过

Jedis jedis =  RedisUtil.getJedis();

取代

 Jedis jedis = new Jedis("127.0.0.1",6379);

代码实现(采用饱汉式单例实现)

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ResourceBundle;
/*这里通过静态成员对象实现redis连接池的单例用于提供Redis对象,不需要我们手动管理redis对象
* 通过配置文件更改参数。
* */
public class RedisUtil {
    private static final String host;
    private static final int port;
    private static final int maxTotal;
    private static final int maxIdle;
    private static final JedisPoolConfig poolConfig;
    private static final JedisPool jedisPool;
    //读取配置文件 获得参数值
    static{
        ResourceBundle rb = ResourceBundle.getBundle("jedis");
        host = rb.getString("jedis.host");
        port = Integer.parseInt(rb.getString("jedis.port"));
        maxTotal = Integer.parseInt(rb.getString("jedis.maxTotal"));
        maxIdle = Integer.parseInt(rb.getString("jedis.maxIdle"));
        poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setMaxIdle(maxIdle);
        jedisPool = new JedisPool(poolConfig,host,port);
    }
    public static Jedis getJedis(){
        Jedis jedis = jedisPool.getResource();   // 通过线程池提供redis的连接
        return jedis;
    }
    public static void main(String[] args) {
        RedisUtil.getJedis();
    }
}

配置文件内容

jedis.host=localhost
jedis.port=6379
jedis.maxTotal=30
jedis.maxIdle=10

1-6 Redis可视化工具的使用

Redis Desktop Manager

1-7 linux平台的redis的基本操纵命令

指定端口启动服务器/连接服务器
redis-server –-port 6379
redis-cli -p 6378
通过配置文件启动redis(实际开发中使用)
cat redis.conf | grep -v "#" | grep -v "^$" > redis-6378.conf

配置文件中的配置选项(加注释是常用的)

bind 127.0.0.1           // 绑定的IP
protected-mode yes
port 6379                // 端口号
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no            //守护线程方式启动
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""              // 日志文件名称
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb   
dir ./                  // 日志文件位置
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

设置配置文件redis-6378.conf

port 6378                
daemonize yes            
logfile "6378.log"    
dir ./redis-4.0.0/log_info      

配置文件进行启动实例

(base) god@god-MS-7C83:~/redis-4.0.0/conf$ redis-server redis-6378.conf
(base) god@god-MS-7C83:~/redis-4.0.0/conf$ ps -ef | grep redis
god       4197  3996  0 14:26 pts/2    00:00:00 grep --color=auto redis
god      29562     1  0 00:08 ?        00:00:42 redis-server *:6379

2 Redis持久化

2-1 数据持久化(Data Persistence )的概述

定义:利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化

2-1-1 redis中数据持久化的方式:

方式1:将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据

方式2:将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程

  • RDB (Redis Database): The RDB persistence performs point-in-time snapshots of your dataset at specified intervals.(存储数据的快照
  • AOF (Append Only File): The AOF persistence logs every write operation received by the server, that will be played again at server startup, reconstructing the original dataset. Commands are logged using the same format as the Redis protocol itself, in an append-only fashion. Redis is able to rewrite the log in the background when it gets too big.(数据的操作记录
  • No persistence: If you wish, you can disable persistence completely, if you want your data to just exist as long as the server is running.
  • RDB + AOF: It is possible to combine both AOF and RDB in the same instance. Notice that, in this case, when Redis restarts the AOF file will be used to reconstruct the original dataset since it is guaranteed to be the most complete.(2个一起使用)

Redis Persistence 官网参考资料

2-2 RDB进行数据持久化

操作命令

save

操作结果:会在配置文件中的dir目录产生rdb文件

配置文件中与RDB相关的配置选项:

dbfilename dump.rdb
说明:设置本地数据库文件名,默认值为 dump.rdb
经验:通常设置为dump-端口号.rdb
dir
说明:设置存储.rdb文件的路径
经验:通常设置成存储空间较大的目录中,目录名称data
rdbcompression yes
说明:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩
经验:通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨大)
rdbchecksum yes
说明:设置是否进行RDB文件格式校验,该校验过程在写文件和读文件过程均进行
经验:通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数据损坏风
2-2-1 save指令使用存在的问题与解决(bgsave)

缺点:save指令的执行会阻塞当前Redis服务器, 直到当前RDB过程完成为止, 有可能会造成长时间阻塞, 线上环境不建议使用

使用后台的save命令bgsave进行保存

bgsave的作用手动启动后台保存操作,但不是立即执行

  • bgsave命令是针对save阻塞问题做的优化。 Redis内部所有涉及到RDB操作都采用bgsave的方式, save命令可以放弃使用。

bgsave的相关配置选项

stop-writes-on-bgsave-error yes
说明:后台存储过程中如果出现错误现象,是否停止保存操作经验:通常默认为开启状态
2-2-2 数据持久化频率设置在配置文件中的设置
  • 满足限定时间范围内key的变化数量达到指定数量即进行持久化
    • second:监控时间范围
    • changes:监控key的变化量
save second changes    

配置文件中的相关选项

save 900 1           // 900s,key变化1次,则将key:value对应的数据进行持久化
save 300 10          // 300s,key变化10次
save 60 10000        // 60s,key变化10000次
  • 越小的时间间隔,key变化的次数越多才会进行记录。
  • 根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的
  • 对于second与changes设置通常具有互补对应关系,尽量不要设置成包含性关系
  • 配置启动后执行的是bgsave操作
2-2-3 启动RDB进行持久化的方式对比(重要)
方式 save指令 bgsave指令 save配置
读写 同步 异步(fork子进程返回结果)
阻塞客户端指令
额外内存消耗
启动新进程

其他使用RDB进行持久化的方式

全量复制
在主从复制中详细讲解
 服务器运行过程中重启
 关闭服务器时指定保存数据
rdb特殊启动形式
debug reload
shutdown save
  • 默认情况下执行shutdown命令时, 自动bgsave(如果没有开启AOF持久化功能)
2-2-4 RDB的优缺点以及实际应用

应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复

优点

  • RDB是一个紧凑压缩的二进制文件, 存储效率较高
  • RDB内部存储的是redis在某个时间点的数据快照, 非常适合用于数据备份,全量复制等场景
  • RDB恢复数据的速度要比AOF快很多

缺点

  • RDB方式无论是执行指令还是利用配置,无法做到实时持久化,宕机的时候可能会有部分数据丢失,具有较大的可能性丢失数据
  • bgsave指令每次运行要执行fork操作创建子进程, 要牺牲掉一些性能
  • Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象

2-3 AOF进行数据持久化

2-3-1 概述

AOF (Append Only File): The AOF persistence logs every write operation received by the server, that will be played again at server startup, reconstructing the original dataset. Commands are logged using the same format as the Redis protocol itself, in an append-only fashion. Redis is able to rewrite the log in the background when it gets too big.

优点:

  • 由于只记录操作过程,相比较RDB其实时性更加好,目前已经成为主流方式(数据持久化优先考虑AOF)

2-3-2 AOF写数据的时机

策略 说明 备注
always(每次) 每次写入操作均同步到AOF文件中, 数据零误差,性能较低 不推荐适用
everysec(每秒) 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高在系统突然宕机的情况下丢失1秒内的数据 默认使用
no(系统控制) 由操作系统控制每次同步到AOF文件的周期,整体过程不可控
AOF在文件中的配置选项
port 6378
daemonize yes
logfile "6378.log"
dir /home/god/redis-4.0.0/log_info      
appendonly yes                           // 开启AOF日志记录
appendfsync everysec                     // 设置AOF写入策略,always|everysec|no

AOF文件内容

(base) god@god-MS-7C83:~/redis-4.0.0/log_info$ redis-cli -p 6378
127.0.0.1:6378> set age 100
OK
127.0.0.1:6378> lpush dd sdf
(integer) 1
127.0.0.1:6378> set daughter 11
OK
127.0.0.1:6378> ls
(error) ERR unknown command 'ls'
127.0.0.1:6378>
(base) god@god-MS-7C83:~/redis-4.0.0/log_info$ ls
6378.log  appendonly.aof  dump.rdb
// 可以看到AOF文件中确实记录的是对命令的操作
(base) god@god-MS-7C83:~/redis-4.0.0/log_info$ vim appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
age
$3
100
*3
$5
lpush
$2
dd
$3
sdf
*3
$3
set
$8
daughter
$2
11

2-3-2 AOF重写(rebuild the AOF)的概念

Redis supports an interesting feature: it is able to rebuild the AOF in the background without interrupting service to clients. Whenever you issue a BGREWRITEAOF Redis will write the shortest sequence of commands needed to rebuild the current dataset in memory. I

重写的场景:对于冗余命令的处理,用于压缩文件体积

定义:将Redis进程内的数据转化为写命令同步到新AOF文件的过程。 将对同一个数据的若干个条命令执行结果转化成最终结果数据对应的指令进行记录。

AOF重写作用

节约空间,提高数据恢复效率:

  • 降低磁盘占用量,提高磁盘利用率
  • 提高持久化效率,降低持久化写时间,提高IO性能
  • 降低数据恢复用时,提高数据恢复效率
AOF重写规则
  • 进程内已超时的数据不再写入文件
  • 忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令如del key1、 hdel key2、 srem key3、 set key4 111、 set key4 222等
  • 对同一数据的多条写命令合并为一条命令
    • 如lpush list1 a、 lpush list1 b、 lpush list1 c 可以转化为: lpush list1 a b c。
      为防止数据量过大造成客户端缓冲区溢出,对list、 set、 hash、 zset等类型, 每条指令最多写入64个元素
AOF重写在配置文件中的配置项目
bgrewriteaof                            //  控制台输入命令手动重写
auto-aof-rewrite-min-size size          //  自动重写配置选项2
auto-aof-rewrite-percentage percentage  // 自动重写配置选项2

  • 上图是bgwriteaof的原理展示,可以看到也是通过子进程进行数据的重写,类似于bgsave命令

2-3-3 AOF自动重写2个参数的理解

auto-aof-rewrite-min-size size          //  自动重写配置选项2
auto-aof-rewrite-percentage percentage   // 自动重写配置选项2

自动重写前需获取以下参数进行对比

aof_current_size
aof_base_size
自动重写触发条件

info指令可以看到相关信息


127.0.0.1:6378> info
# Server
redis_version:4.0.0
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:d748290e16ddf3d8
redis_mode:standalone
os:Linux 5.4.0-70-generic x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:7.5.0
process_id:17510
run_id:ace405d287322bccdf4804e64f8357385b148e0e
tcp_port:6378
uptime_in_seconds:1449
uptime_in_days:0
hz:10
lru_clock:9913231
executable:/home/god/redis-4.0.0/redis-server
config_file:/home/god/redis-4.0.0/conf/redis-6378.conf

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:828968
used_memory_human:809.54K
used_memory_rss:4071424
used_memory_rss_human:3.88M
used_memory_peak:828968
used_memory_peak_human:809.54K
used_memory_peak_perc:100.12%
used_memory_overhead:815438
used_memory_startup:765544
used_memory_dataset:13530
used_memory_dataset_perc:21.33%
total_system_memory:67383435264
total_system_memory_human:62.76G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:4.91
mem_allocator:jemalloc-4.0.3
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:8
rdb_bgsave_in_progress:0
rdb_last_save_time:1620524518
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:0
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:217088 
aof_current_size:299                   // current size指令
aof_base_size:121                      // base size参数
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0

# Stats
total_connections_received:2
total_commands_processed:11
instantaneous_ops_per_sec:0
total_net_input_bytes:336
total_net_output_bytes:20437
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:287
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:cf0a4f48c944dfcf437de6d55c8edee2c02c3349
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:0.85
used_cpu_user:0.37
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=5,expires=0,avg_ttl=0
127.0.0.1:6378>

2-3-4 AOF重写的原理

rebuild机制的原理:另外设置一个重写的aof buffer,信息足够写入AOF文件(如下图所示)

2-4 RDB与AOF的总结(重要)

RDB存储数据快照:数据存储慢,文件大,恢复快,实时性差

AOF存储操作记录:存储快,文件小,实时性好,恢复慢

使用场景:

应用场景 使用要点
RDB 对数据非常敏感, 建议使用默认的AOF持久化方案 存储频率不要太频繁
AOF 数据呈现阶段有效性,建议使用RDB持久化方案

实际使用原则(考虑数据丢失的容忍度,资源占用以及恢复速度进行综合考虑)

 RDB与AOF的选择实际上是在做一种权衡,每种都有利有弊
 如不能承受数分钟以内的数据丢失,对业务数据非常敏感, 选用AOF
 如能承受数分钟以内的数据丢失, 且追求大数据集的恢复速度, 选用RDB
 灾难恢复选用RDB
 双保险策略, 同时开启 RDB 和 AOF, 重启后, Redis优先使用 AOF 来恢复数据,降低丢失数据的量

3 业务场景下哪些数据可以持久化

原则:持久化主要根据业务场景确定,特别重要的信息,通常需要持久化

业务场景 数据是否适合持久化 原因
redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性 否(主键id) 宕机后部分数据丢失,仅仅依赖持久化数据会造成主键id重复问题,持久化仍然必须扫描所有数据库获取最大id,因此这里持久化没有意义
redis应用于各种结构型和非结构型高热度数据访问加速 否(热度数据) 访问加速数据在关系型数据库中就已经有,没必要存储
redis 应用于购物车数据存储设计 慢速数据在关系型数据库中就已经有
redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计 是(快速数据) 快速数据需要持久化,因为底层数据库可能来不及同步这些快速数据
redis 应用于具有操作先后顺序的数据控制
redis 应用于最新消息展示
redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索 关系网络复杂,直接读库
redis 应用于基于黑名单与白名单设定的服务控制 长期策略存储在库中,短期策略可以考虑持久化
redis 应用于计数器组合排序功能对应的排名 推荐持久化
redis 应用于即时任务/消息队列执行管理 rabbitmq中间件解决
redis 应用于按次结算的服务控制 看服务的重要性,不重要也可以不持久化

参考资料

01 Nyima的博客之redis的学习

02 redis的基础课程

03 redis重点知识汇总

04 JavaGuide的Redis数据

05 Redis Persistence 官网参考资料

原文地址:https://www.cnblogs.com/kfcuj/p/14747403.html