当前位置: 首页 > article >正文

Redis 附加功能(三)— 持久化、发布与订阅及模块

Redis 把所有数据都存储在内存中,而传统数据库将实际的数据存储在硬盘中。Redis的持久化功能把内存中存储的数据以文件形式存储到硬盘上,服务器也可以根据这些文件在系统停机之后实施数据恢复。

发布与订阅功能可以让客户端通过广播方式,将消息同时发送给可能存在的多个客户端。

模块功能允许开发者通过Redis开放的API,通过C语言在Redis之上构建任意复杂的、全新的数据结构、功能和应用。

1 持久化

Redis提供了RDB持久化、AOF持久化和RDB-AOF混合持久化等多种持久化方式。也可以完全关闭持久化功能。

1.1 RDB持久化

RDB、Redis DataBase(Redis 数据库),构建出一个经过压缩的二进制文件(包含了服务器在各个数据库中存储的键值对数据等信息),文件名一般为dump.rdb。

全量式持久化。

1.1.1 创建方式

SAVE

阻塞服务器,并创建PDB文件。

在命令执行期间,Redis服务器将阻塞,直到RDB文件创建完毕为止。

BGSAVE

以非阻塞方式创建PDB文件。

命令以异步方式执行,会将命令执行之前的数据保存到RDB中,创建中及之后的数据不会被保存。

自动创建

通过save选项配置。

save <seconds> <changes>

如果服务在seconds秒内至少进行changes次修改,服务器将自动执行一次BGSAVE命令。

可以同时使用多个save选项。

默认配置:

save 60 10000

save 300 100

save 3600 1

注意:每次成功创建RDB文件之后,时间计数器及修改次数计数器都会被清零。

表 创建RDB的方式

1.1.2 优缺点

优点

RDB文件体积小,恢复数据的速度快。

缺点

  1. 容易丢失的数据比较多(RDB文件创建间隔时间越长,丢失数据越多)。
  2. 需要全量保存,耗时及耗性能。

表 RDB方式的优缺点

1.2 AOF持久化

增量式持久化。服务器每次执行完命令后,都会以协议文本的方式将被执行的命令(非只读命令)追加到AOF文件的结尾。

在配置文件中打开AOF持久化功能:appendonly yes

1.2.1 AOF文件的冲洗频率

为了提供程序的写入性能,操作系统通常会把针对硬盘的多次写操作优化为一次写操作。当程序调用操作系统接口对文件进行写入时,系统不会直接把数据写入硬盘,而是会将数据写入位于内存的缓冲区中,等到指定的时限到达或满足某些条件时,才将缓冲区的数据冲洗至硬盘。

这种机制虽提高了程序性能,但给写入操作带来了不确定性(当系统突然停机时,内存缓冲区中的数据可能会丢失)。Redis提供了appendfsync <value>选项,控制系统冲洗AOF文件的频率。

always

每执行一个写命令,就对AOF文件执行一次冲洗

everysec

默认值,每隔1s,就对AOF文件执行一次冲洗

no

不主动对AOF文件执行冲洗,由操作系统决定。

表 appendfsync 的选项

1.2.2 AOF重写

如果服务器对相同的键执行过多次修改操作,那么AOF文件会出现多个冗余命令。减少冗余,取最后一次对这个键的写操作来存储。 这时,需要对AOF文件进行重写。

BGREWRITEAOF

显式触发AOF重写操作,是一个异步命令。

注意:1)发送BGREWRITEAOF命令时,如果服务器正在持久RDB文件,那么AOF重写操作会等RDB文件创建完毕之后再执行。2)如果再执行重写操作过程中,又接收到BGREWRITEAOF,那服务器会返回错误。

AOF重写配置选项

auto-aof-rewrite-min-size <value>

设置触发自动重写需要的最小AOF文件体积。

auto-aof-rewrite-percentage <value>

触发自动重写所需的文件增大的百分比。与上次AOF文件重写之后的体积相比(如果没执行过重写,那么使用启动服务器时使用的AOF文件体积)。

表 触发AOF 重写的方式

1.2.3 优缺点

优点

丢失数据更少

缺点

  1. 文件体积比RDB要大得多,生成AOF文件所需的时间也会比RDB更长。
  2. 数据恢复速度比RDB慢得多。因为RDB可以直接恢复,而AOF通过执行保存的命令来间接恢复。
  3. 重写时耗时长,及耗性能。

表 AOF的优缺点

1.3 RDB-AOF混合

配置打开RDB-AOF混合持久方式:aof-use_rdb-preamble yes

原理:在执行AOF重写时,根据数据库当前的状态生成出相应的RDB数据,并将这些数据写入新建的AOF文件中,那些在AOF重写之后执行的命令,继续以协议文本的方式追加到新AOF文件的末尾(即已有的RDB数据后面)。

1.4 其他

1.4.1 单纯的内存缓存服务器

启动服务时,配置 save “”

1.4.2 SHUTDOWN:关闭服务器

默认情况下,在执行这个命令时,会根据服务器的持久化配置选项,决定是否执行数据保存操作。

2 发布与订阅

图 Redis 的频道和它的订阅者

客户端与频道的对应关系是多对多。客户端可以订阅频道模式,模式匹配到的频道都会发送消息给该客户端。

客户端可以将消息发布到多个频道。

2.1 相关命令

发布消息

PUBLISH channel message

订阅

SUBSCRIBE channel [channel ...]

在redis-cli 执行订阅命令之后,就会进入阻塞状态,无法再执行其他任何命令,在阻塞过程中,监听频道发送的消息。 只能强制退出redis-cli程序。

PSUBSCRIBE pattern [pattern ...]

订阅模式

退订

UNSUBSCRIBE [channel ...]

当不指定频道时,会退订所有频道。

PUNSUBSCRIBE [pattern ...]

退订模式

查看发布与订阅

PUBSUB

PUBSUB CHANNELS [pattern] 查看频道

PUBSUB NUMSUB [channel ...] 查看任意多个给定频道的订阅者数量。

PUBSUB NUMPAT 被订阅模式的总数量。

表 发布与订阅相关命令

2.2 示例

广播系统:公司A 及 公司B会不定时发布消息,证券公司、股民能接收到这些消息。

public class SecuritiesMarket {

    private static class CompanyThread extends Thread {

        private final String name;
        private final String channel;

        private CompanyThread(String name, String channel) {
            this.name = name;
            this.channel = channel;
        }

        @Override
        public void run() {
            Jedis redis = RedisPool.getRedis();
            Random random = new Random();
            int count = 0;
            while (true) {
                redis.publish(channel,name + "利好:" + (count++));
                try {
                    Thread.sleep((random.nextInt(5) + 1) * 1000L);
                } catch (InterruptedException e) {
                    System.err.println(name + "利好释放完毕");
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        CompanyThread threadA = new CompanyThread("A","company_a");
        CompanyThread threadB = new CompanyThread("B","company_b");
        threadA.start();
        threadB.start();

        JedisPubSub personnel = new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
                System.err.println("股民接收到消息," + channel + ":" + message);
            }
        };

        JedisPubSub securityCompany = new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
                System.out.println("证券公司接收到消息," + channel + ":" + message);
            }
        };

        Runnable run1 = () -> {
            RedisPool.getRedis().subscribe(personnel,"company_b");
        };

        Runnable run2 = () -> {
            RedisPool.getRedis().subscribe(securityCompany,"company_a","company_b");
        };

        new Thread(run1).start();
        new Thread(run2).start();

    }
}

3 模块

Redis为用户提供了流水线、事务及Lua脚本用于扩展功能,但是它们有几个明显的缺陷:

  1. 必须基于Redis现有的数据结构或功能来实现。
  2. 在编程方面过于复杂。
  3. 性能上有损耗。

模块功能允许开发者基于Redis提供的API,通过C语言在Redis之上构建复杂的、全新的数据结构及功能,让使用者用“原生”方式在Redis调用及使用扩展的功能及数据结构,而且在性能上带来了更大的提升。

3.1 管理模块

图 模块的生命周期

编译模块:使用make命令

载入模块:配置项 loadmodule <module_path> 或使用命令 MODULE LOAD module_path

列出已载入的模块:MODULE LIST

卸载模块: MODULE UNLOAD module_name

3.2 热门模块

ReJSON

实现了Redis对JSON数据的原生支持。用户可以直接在Redis中存储、更新和获取JSON数据。

RediSQL

嵌入了一个完整的SQLite实现,用户可以在Redis中使用SQLite的全部功能,可以使用SQL语句。

RediSearch

全文搜索引擎,为多种语言的文档建立索引。

表 Redis 热门模块


http://www.kler.cn/a/443549.html

相关文章:

  • c# WaitSleepJoin状态的线程如何自动恢复
  • vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)
  • TOGAF之架构标准规范-业务架构
  • 什么是网络安全(Cybersecurity)?
  • HIVE数据仓库分层
  • 【Java项目】基于SpringBoot的【外卖点餐系统】
  • 计算机基础知识——数据结构与算法(二)(山东省大数据职称考试)
  • Linux服务器上安装JDK1.8
  • ilqr算法原理推导及代码实践
  • 音视频入门基础:MPEG2-TS专题(19)——FFmpeg源码中,解析TS流中的PES流的实现
  • [网络]tcp通信协议接口函数及一些简易项目
  • 【后端面试总结】深入解析进程和线程的区别
  • 《C++ 赋能强化学习:Q - learning 算法的实现之路》
  • 【Java 数据结构】如何写一副扑克牌 (附:全部码源) !!!
  • 量子通信学习路径(一)
  • JS使用random随机数实现简单的四则算数验证
  • transformer学习笔记-位置编码
  • 使用 NVIDIA DALI 计算视频的光流
  • 【设计模式】单例模式的应用场景
  • 计算机的错误计算(一百八十五)
  • AI-PR曲线
  • C++中如何实现单例模式?
  • 【Maven】基础(一)
  • 深度神经网络(DNN)在时序预测中的应用与缺陷
  • 前端 计算发布时间(如“1小时前”、“3天前”等)
  • Mybatis plus查询开用了Redis缓存,一开始挺快,用户多/时间拉长就变慢了