4

全面了解 Redis 高级特性,实现高性能、高可靠的数据存储和处理 - 无回实验室

 1 year ago
source link: https://www.cnblogs.com/chuan2/p/17254110.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

99c660fe-2fe4-457c-a5f1-0b3ec6f3f68b.png

Redis 是一种高性能、高可靠的内存数据存储和处理系统,它支持多种数据结构和协议,可以用于各种不同的应用场景。本文将介绍 Redis 的高级特性,包括持久化、事务、Lua 脚本等方面,以及如何使用这些特性实现高性能、高可靠的数据存储和处理。

高性能、高可用、高可扩展性的原理

  1. 基于内存的数据结构:Redis将数据存储在内存中,而不是硬盘中,因此可以实现非常高速的读写操作。
  2. 单线程的模型:Redis采用单线程的模型,避免了多线程之间的竞争问题,也减少了线程切换的开销。
  3. 高效的网络通信:Redis采用自己设计的简单协议进行通信,协议本身非常轻量级,减少了网络传输的开销。
  4. 异步非阻塞式IO:Redis采用异步非阻塞的IO模型,当IO操作完成后才会通知应用程序,避免了IO阻塞对性能的影响。
  5. 高效的持久化机制:Redis支持多种持久化机制,包括快照和AOF,可以满足不同的业务需求,同时也可以提高数据的安全性。
学会与人相处,建立良好的人际关系,
这是在职场中获得成功的关键。

Redis是一种内存数据库,它将数据存储在内存中,因此它非常快速。但是,如果Redis进程意外终止,所有数据将丢失。为了解决这个问题,Redis提供了持久化功能,它可以将内存中的数据异步写入磁盘,以便在Redis重启后可以恢复数据。

RDB持久化

RDB持久化是将Redis在某个时间点上的数据保存到硬盘上,可以看作是对Redis内存中的数据做一个快照。RDB持久化可以通过配置Redis服务器的时间间隔来自动触发,也可以手动执行。

AOF持久化

AOF持久化是将Redis的写操作以文本形式追加到文件中。AOF文件中的每个写操作都是一个Redis命令,当Redis服务器重启时,可以通过执行AOF文件中的所有命令来恢复数据。

持久化的配置

RDB配置

RDB持久化的配置文件为redis.conf。在配置文件中,可以通过以下配置项来控制RDB持久化的行为:

  • save:指定Redis自动触发RDB持久化的条件,格式为 save ,其中seconds表示时间间隔,changes表示数据变化的次数。例如,save 900 1 表示如果900秒内有至少1个键被修改,则触发RDB持久化。
  • stop-writes-on-bgsave-error:如果设置为yes,则如果RDB持久化失败,Redis服务器将停止接受写请求,直到RDB持久化成功为止。
    Redis还提供了以下与RDB持久化相关的命令:
  • save:手动触发RDB持久化。
  • bgsave:在后台异步执行RDB持久化。

AOF配置

AOF持久化的配置文件为redis.conf。在配置文件中,可以通过以下配置项来控制AOF持久化的行为:

  • appendonly:如果设置为yes,则开启AOF持久化。
  • appendfsync:指定AOF缓冲区何时将数据同步到硬盘,有以下三个选项:
    • always:每个Redis命令都会立即同步到硬盘。
    • everysec:每秒将AOF缓冲区中的数据同步到硬盘。
    • no:完全依赖操作系统将数据同步到硬盘。
  • no-appendfsync-on-rewrite:如果设置为yes,则当Redis执行AOF重写时,不将数据同步到硬盘。
    Redis还提供了以下与AOF持久化相关的命令:
  • bgrewriteaof:在后台异步执行AOF重写。
  • bgappendonly:在后台异步执行AOF缓冲区的数据同步到硬盘。

持久化的恢复

RDB的恢复

RDB持久化的恢复比较简单,只需将RDB文件复制到Redis服务器的工作目录,并在redis.conf文件中指定RDB文件的路径即可。Redis服务器启动时会自动加载RDB文件,并恢复数据。

人生如一场旅程,不要只看到目的地,
更要享受旅途中的美好。

AOF的恢复

AOF持久化的恢复相对复杂。首先,需要将AOF文件加载到Redis服务器中:

plaintextCopy code
redis-cli
CONFIG SET appendonly yes
BGREWRITEAOF

然后,需要清空Redis服务器中的数据:

plaintextCopy code
redis-cli
FLUSHALL

最后,执行AOF文件中的所有命令,恢复数据:

plaintextCopy code
redis-cli
CONFIG SET appendonly yes
BGREWRITEAOF

RDB和AOF的选择

在选择持久化方式时,需要根据实际的业务场景和需求来选择RDB或AOF持久化。如果对数据完整性要求较高,可以选择AOF持久化;如果对数据完整性要求不高,可以选择RDB持久化。

持久化对性能的影响

持久化会对Redis服务器的性能产生一定的影响,特别是在执行RDB持久化时,由于需要fork出子进程,会占用一定的CPU和内存资源。因此,在配置持久化时,需要根据实际情况来平衡数据安全和性能的需求。

数据的丢失问题

由于Redis的持久化是异步的,因此在Redis意外终止时,可能会丢失部分数据。为了最小化数据丢失的风险,可以使用AOF持久化,并将appendfsync设置为always。这将确保每个写操作都同步到磁盘上的AOF文件中。

Redis事务是指在一次操作中执行多个命令,并且这些命令要么全部被执行,要么全部不执行。Redis事务可以保证一系列命令的原子性执行。

职场中最重要的能力并不是技术或知识,
而是沟通和协作的能力。

事务的优点

  • 原子性:Redis事务可以保证多个命令的原子性执行,即要么全部执行,要么全部不执行。
  • 性能:Redis事务可以将多个命令打包成一个批量操作,从而减少网络通信的开销,提高性能。
  • 一致性:Redis事务可以保证多个命令的一致性,即在执行事务期间,其他客户端不会对这些命令进行修改。
  • MULTI:开始一个事务。
  • EXEC:执行事务中的所有命令。
  • DISCARD:取消事务。
  • WATCH:监视一个或多个键,如果在事务执行期间这些键被修改,事务将被取消。
/**
     * 事务操作
     * @param isOpenError 是否开启异常
     */
    public void transactionalMethod(boolean isOpenError) {
        redisTemplate.execute(new SessionCallback<List<Object>>() {
            @Override
            public List<Object> execute(RedisOperations operations) {
                operations.multi(); // 开启事务
                ValueOperations<String, String> valueOps = operations.opsForValue();
                valueOps.set("key1", "value1");
                if(isOpenError){
                    int i = 1 / 0;
                }
                valueOps.set("key2", "value2");
                List exec = operations.exec();//提交事务
                return exec;
            }
        });
    }
  • Redis事务不支持回滚操作。
  • 如果在执行事务期间,键被其他客户端修改,那么事务将被取消。
  • Redis事务不支持嵌套事务。
  • Redis事务中的命令不能使用事务外的数据。
  • Redis事务中的命令不支持乐观锁。
  • 批量操作:将多个命令打包成一个事务,从而减少网络通信的开销,提高性能。
  • 保证数据一致性:在需要保证数据一致性的场景中使用Redis事务可以避免因为并发操作导致数据不一致的问题。

发布和订阅是 Redis 的一种消息传递机制,它可以实现多个客户端之间的消息通信。下面是一个简单的 Redis 发布和订阅的示例

实现消息订阅者

public class RedisMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] bytes) {
        System.out.println("收到消息: " + message.toString());
    }
}

注册消息订阅者

@Bean
    public RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisTemplate().getConnectionFactory());
        container.addMessageListener(new RedisMessageListener(), new ChannelTopic("pubsub:example"));
        return container;
    }
public void publish(String message) {
        redisTemplate.convertAndSend("pubsub:example", message);
    }

lua脚本

永远保持谦虚和学习的心态,
才能不断提升自己,赢得更多的机会和尊重。

Redis 支持 Lua 脚本,可以通过编写 Lua 脚本来实现复杂的数据操作和处理。Redis 的 Lua 脚本可以访问 Redis 数据库,Redis 提供的各种命令和函数。

下面是一个使用lua脚本实现redis自增计数器的示例

public Long increment(String key) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/increment.lua")));
        script.setResultType(Long.class);
        List<String> keys = Collections.singletonList(key);
        return redisTemplate.execute(script, keys);
    }

lua脚本

local key = KEYS[1]
local value = redis.call('INCR', key)
return value

使用 Lua 脚本可以将多个 Redis 命令封装在一个脚本中,减少网络开销和服务器负载。此外,Lua 脚本还可以实现 Redis 不支持的数据结构和算法,可以扩展 Redis 的功能和应用范围。

管道(pipeline)是一种高效的Redis命令执行方式,它可以在一次通信中发送多个Redis命令,并一次性获取所有命令的响应结果。这种方式可以有效地降低Redis服务器的网络延迟和通信开销,提高Redis的性能。

下面是一个使用管道操作的示例

/**
     * 管道操作
     * 注意管道操作不支持事务和watch命令,需要谨慎使用。
     * 管道操作会将多个命令打包成一个请求发送给Redis服务器,
     * 如果其中一个命令执行失败,那么整个管道操作都会失败
     */
    public void pipelineExample() {
        List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.stringCommands().set("key1".getBytes(), "value1".getBytes());
                connection.stringCommands().set("key2".getBytes(), "value2".getBytes());
                connection.stringCommands().set("key3".getBytes(), "value3".getBytes());
                return null;
            }
        });
        System.out.println(results); // 打印结果
    }

完整代码地址

https://gitee.com/youlaiorg/youlai-learning.git

本文介绍了Redis的高级特性,包括持久化、事务、发布订阅、lua脚本和管道操作。其中,持久化可以实现数据的持久化存储,事务可以保证一系列命令的原子性执行,发布订阅可以实现多个客户端之间的消息通信,lua脚本可以实现复杂的数据操作和处理,管道操作可以在一次通信中发送多个Redis命令。此外,本文还介绍了Redis高性能、高可用、高可扩展性的原理,包括基于内存的数据结构、单线程的模型、高效的网络通信、异步非阻塞式IO和高效的持久化机制。

做事要讲求团队合作,相互支持,共同进步。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK