Redis-02

事物

基础

Redis 事物本质 : 一组命令的集合! 一个事物中的所有命令都会被序列化,在事物执行过程中,会安照顺序执行
一次性 顺序性 排他性
------- 队列 set set set 执行 ---------


1. Redis 事物没有隔离级别的概念
2. 所有的命令在事物中,并不执行! 当发起执行(exec)命令时才执行
3. Redis 单条命令保证原子性(要么完整的被执行,要么完全不执行),但是事物不保证

过程

# 开启事物
multi
# 命令入队 .....

# 执行事物
exec

# 取消事物 队列中的所有命令都不会执行
discard

命令出错

# 编译时异常 命令有语法错误 执行事物会报错
队列中的所有命令都不会执行
# 运行时异常 逻辑错误 出错的命令报异常
队列中的其他命令都会执行

悲观锁

无论什么时候都会出问题, 都上锁

乐观锁

无论什么时候都不会出问题, 都不上锁

实现

# 监听 在事物中添加 当监听的 key 的值改变时,事物会失败
watch key

# 放弃监视
UNwatch key

Jedis

maven

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.54</version>
    </dependency>
</dependencies>

Java

// 获取Redis对象
Jedis jedis = new Jedis("192.168.182.132",6379);
//所有方法和命令一样
jedis.XXX

//事物
Transaction multi = jedis.multi;
multi.set("name","fang");
multi.exec;

//关闭连接
jedis.close;

SpringBoot集成

配置

maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

源码

RedisAutoConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

    // redisTemplate  -->  Redis 操作模板, 放<Object, Object>
	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

    // StringRedisTemplate  --> Redis 操作模板, 专用于 String 存放
	@Bean
	@ConditionalOnMissingBean
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

}

RedisProperties.class

/*
 * 配置类
 */

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

	// 默认 0 号数据库
	private int database = 0;

	//
	private String url;

	//
	private String host = "localhost";

	//
	private String password;

	// 默认 6379 端口
	private int port = 6379;

	//
	private boolean ssl;

	//
	private Duration timeout;

使用

@Test
void test1(){
    // 操作字符串
    redisTemplate.opsForValue().set("fang","男");
    String fang = (String) redisTemplate.opsForValue().get("fang");
    // redisTemplate.opsForXXX --  找到对应数据类型即可
    redisTemplate.opsForList();
    redisTemplate.opsForHash();
    redisTemplate.opsForSet();
    // .........
}

常用

@Test
void test(){
    // 删除
    redisTemplate.delete("fang");
    // 事物
    redisTemplate.discard();
    redisTemplate.exec();
    redisTemplate.multi();
    // 过期时间
    redisTemplate.expireAt("fang",new Date(new Date().getTime() + 100));
    // 移动 
    redisTemplate.move("fang",5);
}

Redis.conf

# units are case insensitive so 1GB 1Gb 1gB are all the same.
# 大小写不敏感

# 可以包涵其他配置文件
include /path/to/local.conf

# 绑定 ip , 默认为 127.0.0.1 只允许本机访问
bind 127.0.0.1
# 是否受保护 
protected-mode yes
# 端口
port 6379

# 是否为守护进程 默认是No 一般改为 yes
daemonize no

# 配置文件 如果以后台方式运行 需指定一个 pid 文件
pidfile /var/run/redis_6379.pid

# 日志
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
# 生成的文件名
logfile ""

# 默认的数据库数量
databases 16
# 是否总是显示 logo
always-show-logo yes

持久化

# 900s 内 如果有 1 个 key 进行修改 进行持久化操作
save 900 1
# 300 内 如果有 10 个 key 进行修改 进行持久化操作
save 300 10
# 60 内 如果有 10000 个 key 进行修改 进行持久化操作
save 60 10000

# 持久化失败 是否继续工作
stop-writes-on-bgsave-error yes
# 是否压缩 rdb 文件
rdbcompression yes
#是否校验 rdb 文件
rdbchecksum yes
# rdb 文件文件名
dbfilename dump.rdb
# 文件保存目录  ./ --> 当前目录
dir ./

安全

# 设置密码
requirepass ......(写密码)

主从

客户端

# 默认的客户端连接数
maxclients 10000

内存

# 内存容量
maxmemory <bytes>
# 内存超过策略
maxmemory-policy noeviction
    1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 
    2、allkeys-lru : 删除lru算法的key   
    3、volatile-random:随机删除即将过期key   
    4、allkeys-random:随机删除   
    5、volatile-ttl : 删除即将过期的   
    6、noeviction : 永不过期,返回错误

AOF(APPEND ONLY)

# 默认关闭
appendonly no
# 持久化文件名字
appendfilename "appendonly.aof"

# 同步
appendfsync always    # 每次修改都会 sync
appendfsync everysec  # 每 1 秒执行 sync
appendfsync no        # 不执行 sync 由操作系统进行 sync

持久化

RDB

RDB是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时是将快照文件直接读到内存里。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-POmQ1PkE-1604127485157)(…\img\Redis-RDB.jpg)]

触发

自动触发

# 配置文件中
save
    save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存
    save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存
    save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存
   
stop-writes-on-bgsave-error 
    默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。

rdbcompression
	默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。

rdbchecksum
	默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验

dbfilename
	设置快照的文件名,默认是 dump.rdb

dir
	设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。

手动触发

save
	该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。

bgsave
	执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作
	创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。

恢复

将 dump.rdb 放到目录下

优缺点

优势
  1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常
  适合用于进行备份和灾难恢复。

  2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任
  何磁盘IO操作。

  3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

劣势
  1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子
  进程,属于重量级操作,如果不采用压缩算法(内存中的数据被克隆了一份,大致2倍的膨胀性需要考
  虑),频繁执行成本过高(影响性能)

  2、RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本
  Redis服务无法兼容新版RDB格式的问题(版本不兼容)

  3、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修
  改(数据有丢失)

AOF

 AOF 则是通过保存Redis服务器所执行的写命令来记录数据库状态。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxKA9t4s-1604127485160)(…\img\Redis-AOF.png)]

触发

# 配置文件中
appendonly
	默认值为no,也就是说redis 默认使用的是rdb方式持久化,如果想要开启 AOF 持久化方式,需要
	将 appendonly 修改为 yes。

appendfilename 
	aof文件名,默认是"appendonly.aof"

appendfsync
	aof持久化策略的配置
	appendfsync always    # 每次修改都会 sync 速度最慢
	appendfsync everysec  # 每 1 秒执行 sync
	appendfsync no        # 不执行 sync 由操作系统进行 sync 速度最快  
     
no-appendfsync-on-rewrite
	
auto-aof-rewrite-percentage
	默认100 当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写

auto-aof-rewrite-min-size
	默认64mb 设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况

aof-load-truncated

优缺点

优点:
	AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而
	已。

  AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-
  check-aof 工具也很容易修正 AOF 文件。

  AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,
  在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。

  缺点:
  对于具有相同数据的的 Redis,AOF 文件通常会比 RDF 文件体积更大。

  虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时,
  RDB 比 AOF 具好更好的性能保证。

  RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,
  RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有存在。

选择

如果可以忍受一小段时间内数据的丢失,毫无疑问使用 RDB 是最好的,定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,而且使用 RDB 还可以避免 AOF 一些隐藏的 bug;否则就使用 AOF 重写。

但是一般情况下建议不要单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。Redis后期官方可能都有将两种持久化方式整合为一种持久化模型。

RDB-AOF混合持久化

# 配置文件
aof-use-rdb-preamble
	设置为yes表示开启,设置为no表示禁用。

  当开启混合持久化时,主进程先fork出子进程将现有内存副本全量以RDB方式写入aof文件中,然后将缓冲区中的增量命令
  以AOF方式写入aof文件中,写入完成后通知主进程更新相关信息,并将新的含有 RDB和AOF两种格式的aof文件替换旧的
  aof文件。

  简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。

使用 RDB 是最好的,定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,而且使用 RDB 还可以避免 AOF 一些隐藏的 bug;否则就使用 AOF 重写。

但是一般情况下建议不要单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。Redis后期官方可能都有将两种持久化方式整合为一种持久化模型。


## RDB-AOF混合持久化

```shell
# 配置文件
aof-use-rdb-preamble
	设置为yes表示开启,设置为no表示禁用。

  当开启混合持久化时,主进程先fork出子进程将现有内存副本全量以RDB方式写入aof文件中,然后将缓冲区中的增量命令
  以AOF方式写入aof文件中,写入完成后通知主进程更新相关信息,并将新的含有 RDB和AOF两种格式的aof文件替换旧的
  aof文件。

  简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页