1.6 Redis事务
事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
1.6.1 基本的事务操作
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,事务执行中,按照顺序执行
Redis单条命令保证原子性,但是事务不保证原子性!
- 一次性
- 顺序性
- 排他性
- 没有隔离级别的概念,没有幻读、脏读…
---入队---
command1
command2
command2
---执行---
三个阶段:
- 开启事务(MULTI)
- 命令入队(commands)
- 执行事务(EXEC)
### 正常执行
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> set key1 1 # 命令入队
QUEUED
127.0.0.1:6379> set key2 2
QUEUED
127.0.0.1:6379> set key3 3
QUEUED
127.0.0.1:6379> get key1
QUEUED
127.0.0.1:6379> get key2
QUEUED
127.0.0.1:6379> exec # 事务执行,按照顺序执行
1) OK
2) OK
3) OK
4) "1"
5) "2"
### 放弃事务
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> set key1 1
QUEUED
127.0.0.1:6379> set key2 2
QUEUED
127.0.0.1:6379> set key3 3
QUEUED
127.0.0.1:6379> DISCARD # 取消事务
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
127.0.0.1:6379> get key1 # 放弃事务取不到相关的值
(nil)
### 事务错误一:命令有错,事务中所有的命令都不会被执行!
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key1 1
QUEUED
127.0.0.1:6379> set key2 2
QUEUED
127.0.0.1:6379> getset key3 # 错误的命令,直接报错
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set key3 3
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors. # 执行事务报错
127.0.0.1:6379> get key1 # 结果是所有的命令都不会执行
(nil)
### 事务错误二:运行异常,如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key1 "yunmx"
QUEUED
127.0.0.1:6379> incr key1
QUEUED
127.0.0.1:6379> set key2 2
QUEUED
127.0.0.1:6379> set key3 3
QUEUED
127.0.0.1:6379> get key3
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range # 代码结构没问题,抛出异常
3) OK
4) OK
5) "3"
127.0.0.1:6379> get key2
"2"
1.6.2 乐观锁
监控:watch
悲观锁:很悲观;认为任何时候都会出现问题,无论做什么都加锁,影响性能
乐观锁:很乐观,任务任何时候都不会出现问题,所以不会上锁,更新数据的时候去判断一下,在此期间,是否有人修改过这个数据,mysql用的version字段!
### Redis的测试监视
127.0.0.1:6379> set mymoney 1000
OK
127.0.0.1:6379> set myout 0
OK
127.0.0.1:6379> WATCH mymoney # 监视
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRby mymoney 20
QUEUED
127.0.0.1:6379> INCRBY myout 20
QUEUED
127.0.0.1:6379> exec # 事务正常结束,数据期间没有发生变动,正常执行了
1) (integer) 980
2) (integer) 20
127.0.0.1:6379>
### 使用watch当乐观锁,测试多线程修改值后事务提交失败
# 第一个进程开启事务
127.0.0.1:6379> watch mymoney
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY mymoney 10
QUEUED
127.0.0.1:6379> INCRBY myout 10
QUEUED
127.0.0.1:6379> exec # 未提交前执行第二个事务进行数据的修改
(nil) # 事务提交后返回修改失败,
127.0.0.1:6379>
# 第二个进程修改我们的值
127.0.0.1:6379> get mymoney
"980"
127.0.0.1:6379> set mymoney 20
OK
127.0.0.1:6379> get mymoney
"20"
127.0.0.1:6379> set mymoney 1000
OK
127.0.0.1:6379> get mymoney
"1000"
### 可以使用unwatch解锁,再次使用watch获取最新的值,再去执行事务
1.7 Redis配置文件详解
1.7.1 redis.conf
启动时候就是通过配置文件来启动的
配置文件对大小写不敏感
包含其他配置文件
网络
bind 127.0.0.1 # 绑定的ip
protected-mode yes # 保护模式
port 6379 # 端口设置
GENERAL通用配置
daemonize yes # 已守护进程方式运行,默认是no,我们需要自己开启
pidfile /var/run/redis_6379.pid # 如果以后台的方式运行,我们就需要指定一个pid文件
# 日志(4个级别)
# 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 可以不显示,默认显示
快照SNAPSHOTTING
# 规则
save 900 1 # 如果900秒内,至少有一个key进行修改,我们就进行持久化操作
save 300 10
save 60 10000
# 我们可以设置自己的一个规则
stop-writes-on-bgsave-error yes # 持久化出现错误的时候,是否继续进行工作,默认是yes
rdbcompression yes # 是否压缩rdb文件,压缩就会消耗CPU资源
rdbchecksum yes # 是否校验rdb文件,出错会进行修复
dir ./ # rdb文件保存的目录
快照
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件,.rdb .aof,如果没有持久化,那么数据就会断电及失
主从复制 REPLICATION
安全SECURITY
# requirepass foobared 默认没有密码
# 可以通过修改配置文件来设置密码
# 比如:
requirepass 123456
# 验证
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
# 也可以通过命令进行密码设置
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"
127.0.0.1:6379> config set requirepass "110"
OK
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 110
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
客户端CLIENTS
# 客户端的一些限制
maxclients 10000 # 设置能连接上redis的客户端数量限制
maxmemory <bytes> # redis配置的最大内存容量
maxmemory-policy noeviction # 内存到达上限后的处理策略
# 移除一些过期的key
# 报错
# ...
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
APPEND ONLY MODE模式 aof配置
appendonly no # 默认不开启aof模式,默认使用的是rdb方式持久化的
appendfilename "appendonly.aof" # 持久化的文件的名字
# appendfsync always # 每次修改值都会写入,速度比较慢
appendfsync everysec # 每秒执行一次sync,可能会丢失1s的数据!
# appendfsync no # 不同步,这个时候操作系统自己同步数据,速度最快!