Redis学习(五):事务、持久化及使用Java操作Redis

事务

Redis事务本质:一组命令的集合。一个事务中的所有命令都会被序列化,在事务执行过程中,会按顺序执行。
一次性、顺序性、排他性!执行一系列的命令。
Redis单条命令保证原子性,但是事务不保证原子性!
Redis事务没有隔离级别的概念,所有的命令在事务中并没有直接被执行,只有发起执行命令的时候才会执行。

Redis的事务:

  • 开启事务
  • 命令入队
  • 执行事务

正常执行事务

  • 开启事务 multi
  • 执行事务 exec

image-20230306163000377

放弃事务

discard命令,执行后事务队列中命令再不会被执行。

image-20230306163215900

错误

错误有两种

  • 编译型异常(代码有问题),事务中所有的命令都不会背执行

    image-20230306163724370

  • 运行时异常,会跳过有错误的部分,其他命令可以正常执行,错误命令抛出异常。

    image-20230306164027727

监控

悲观锁:

  • 认为什么时候都会出问题,无论做什么都会加锁

    上厕所的时候认为一定会有人推你的门,所以要锁上厕所门

  • 可能会影响效率

乐观锁:

  • 认为什么时候都不会出现问题,所以不会上锁,在更新数据的时候去判断一下在此期间是否有人改动过数据。
  • 获取version
  • 更新的时候比较version

image-20230306165504142

乐观锁并不真正加锁,而是在提交操作的时候对比一下version。

Redis监视测试

watch监视money,正常执行情况:

image-20230306165649271

注意一旦事务结束,watch会自动失效。

如果在事务执行过程中事务被中断并且被watch的变量发生了改变,则事务会执行失败。

模拟一下这种情况,先写好这些代码

image-20230306170244631

先不提交事务,然后开另外一个客户端修改一下money的值

image-20230306170502627

再在这里提交事务

image-20230306170519942

可以发现事务没有被执行。

执行失败之后,先解锁watch的变量,再重新watch。
相当于先放弃之前的version变量,然后保存最新的version变量。
使用unwatch解锁变量。

整个流程相当于,先使用watch给指定变量加上乐观锁,然后在执行事务的时候,会对比监视变量的version和加锁的时候变量的version,如果相同就执行,不同就不执行。

Jedis

使用Java来操作redis

什么是 Jedis

是redis官方推荐的Java连接开发工具,使用Java操作redis中间件。

测试
  1. 导入依赖

    <dependencies>
        <!--导入Jedis包-->
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>
        <!--faseJson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.16</version>
        </dependency>
    </dependencies>
    
  2. 编码测试

    • 连接数据库

      public class TestPing {
          public static void main(String[] args) {
              Jedis jedis = new Jedis("localhost", 6379);
              String ping = jedis.ping();
              System.out.println(ping);
          }
      }
      

      image-20230306175525920
      jedis的所有方法就是redis数据库中的各种指令。

    • 操作命令

    • 断开连接

SpringBoot整合

SpringBoot操作数据:spring-data
在SpringBoot2.x之后,原来的jedis被替换为了lettuce
jedis: 采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全,使用Jedis pool连接池。更像BIO模式。
lettuce: 采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况,可以减少线程数量。更像NIO模式。

  1. 导入依赖
    在创建项目的时候勾上对应的包

  2. 配置测试

    # 配置redis
    spring.redis.host=localhost
    spring.redis.port=6379
    
  3. 测试

    @SpringBootTest
    class Redis02SpringbootApplicationTests {
    
    	@Autowired
    	RedisTemplate redisTemplate;
    	@Test
    	void contextLoads() {
    		// redisTemplate, 操作不同的数据类型
    		// opsForValue 操作字符串 类似string
    		// opsForList 操作list
    		// opsForSet
    		// opsForHash
    		// opsForZSet
    		// opsForGep
    		// opsForHyperLogLog
    
    		// 出了基本的操作,常用方法可以直接通过redisTemplate操作, 事务和基本的CRUD
    
    //		// 获取redis连接对象
    //		RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
    //		connection.flushDb();
    //		connection.flushAll();
    		redisTemplate.opsForValue().set("mykey", "test");
    		System.out.println(redisTemplate.opsForValue().get("mykey"));
    	}
    }
    

Redis配置

启动的时候,需要指定的配置文件

单位

image-20230306213448134

对单位的大小写不敏感

包含

一个配置文件可以包含其他的配置文件
image-20230306213618510

网络

image-20230306213709456

通用

daemonize yes # 以守护进程方式运行,默认是no

pidfile /var/run/redis_6379.pid # 如果以后台的方式运行,我们就需要指定一个pid文件

# 指定日志的级别
# Specify the server verbosity level.
# 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 # 数据库的数量,默认为16

always-show-logo yes # 是否显示logo

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件 .rdb .aof

redis 是内存数据库,如果没有持久化,那么断电后数据就丢失了。

# Unless specified otherwise, by default Redis will save the DB:
#   * After 3600 seconds (an hour) if at least 1 key changed
#   * After 300 seconds (5 minutes) if at least 100 keys changed
#   * After 60 seconds if at least 10000 keys changed
#
# You can set these explicitly by uncommenting the three following lines.
#
# 如果3600秒内,如果至少有1个key进行了修改,我们就进行持久化操作
# save 3600 1
# save 300 100
# save 60 10000


stop-writes-on-bgsave-error yes  # 持久化如果出错,是否还需要继续工作

rdbcompression yes # 是否压缩rdb文件(持久化文件)需要消耗一些CPU资源

rdbchecksum yes # 保存消息到rdb文件时计算出校验码

dir /usr/local/var/db/redis/ # rdb文件保存的目录

安全

requirepass foobared # 可以在配置文件里面加密码

也可以在客户端给服务端加密码。

image-20230306215243851

限制

maxclients 10000 # 设置最大客户端数量

maxmemory <bytes> # 设置内存上限

# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key having an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
maxmemory-policy noeviction # 内存达到上限的处理策略

APPEND ONLY模式配置( AOF配置)

appendonly no # 默认不开启aof模式,默认使用rdb方式持久化,大部分情况下,rdb方式够用了

appendfilename "appendonly.aof" # aof持久化文件的名字

# appendfsync always  # 每次修改会同步,消耗性能
appendfsync everysec  # 每秒同步一次,可能会丢失1s的数据
# appendfsync no      # 不执行同步,这个时候操作系统自己同步数据,速度最快

Redis持久化

RDB(Redis DataBase)

在指定的时间间隔内将内存中的数据集体写入磁盘,也就是形成了一个快照,恢复时将快照文件直接读到内存里面。Redis会单独创建一个子进程来进行持久化,会现将数据写入到一个临时文件中,待持久化过程结束了,再用临时文件替换上次持久化的文件。整个过程中主线程不进行任何IO操作,保证了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加高效。RDB的缺点是最后一次持久化之后的数据可能丢失(最后的数据没来得及持久化)。

rdb保存的文件默认是dump.rdb。

手动执行save命令或者满足自动存储条件的时候,会进行持久化。

  • 优点
    • 适合大规模的数据恢复,把快照直接还原到内存中
  • 缺点
    • 需要一定的时间间隔进行保存,如果redis以外宕机了,最后一次修改数据就没有了
    • fork进程的时候,会占用一定的内存空间

AOF (Append Only File)

将我们所有的命令都记录下来,history,回复的时候就把这个文件全部再执行一遍。

以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(不包括读操作),只允许追加文件但不允许改写文件,redis启动之初会读取该文件重新构建数据。

AOF保存的是appendonly.aof

image-20230307095424203

默认不开启,需要手动开启,重启服务器之后生效。

进行几次操作后可以看到出现了appendonly.aof文件,并且里面记录了刚刚使用的赋值命令。

image-20230307095848426

如果appendonly.aof文件被破坏之后,可以发现服务器无法启动。

image-20230307100406104

这时候我们需要使用redis提供的 redis-check-aof 工具来对这个文件进行检测并修复

image-20230307100607179

这个工具会把被破坏的部分数据直接删除。

  • 优点

    • 同步配置,可以提高效率
    • 丢失数据更少
  • 缺点

    • 相对于rdb文件来说,aof文件更大,载入速度也更慢

拓展

  1. RDB持久化方式能够在指定时间间隔内对数据进行快照存储

  2. AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以Redis协议追加保存每次写的操作到文件末尾,Redis还能对AOF文件进行后台重写(合并指令),使得AOF文件体积不会过大。

  3. 只做为缓存时,可以不使用任何持久化

  4. 同时开启两种持久化方式

    • redis重启时会有效载入AOF文件来恢复原始数据,因为在通常情况下AOF文件保存的数据更加完整
    • RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。但是相对于AOF来说,RDB文件变化慢,更容易备份,而且恢复速度快,不会有AOF潜在的BUG

    image-20230307102323448

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值