Redis(四):事务及复制

事务

乐观锁: 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,

乐观锁策略:提交版本必须大于记录当前版本才能执行更新(加版本号,发现版本号不同重新操作)。

悲观锁:悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁(每次操作锁表,其他操作只能等待,并发性极激下降)。

redis事务命令

序号命令描述
1MULTI标记一个事务块的开始
2EXEC执行所有事务块内的命令
3DISCARD取消事务,放弃执行事务块内的命令
4WATCH key [key …]监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断
5UNWATCH取消WATCH命令对所有key的监视

redis执行事务的阶段:

  • 开启:以MULTI命令开启一个事务
  • 入队:将多个命令入队到事务中,接收这些命令并不会立即执行,而是放到等待执行的事务队列中
  • 执行:由EXEC命令触发执行事务,执行事务队列里命令

例子:

1.事务正常执行

redis 127.0.0.1:6379> set balance 1000
OK
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> incrby balance 100
QUEUED
redis 127.0.0.1:6379> incr balance
QUEUED
redis 127.0.0.1:6379> decrby balance 50
QUEUED
redis 127.0.0.1:6379> incrby balance 100
QUEUED
redis 127.0.0.1:6379> EXEC
1) (integer) 1100
2) (integer) 1101
3) (integer) 1051
4) (integer) 1151
redis 127.0.0.1:6379> get balance
"1151"

2.放弃事务

redis 127.0.0.1:6379> get balance
"1151"
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> decrby balance 20
QUEUED
redis 127.0.0.1:6379> DISCARD
OK
redis 127.0.0.1:6379> get balance
"1151"

3.全体连坐(当命令进入队列过程中,有一个命令报错(抛出异常,可以是命令不符合规范,也可以是程序对这个事务抛出异常)的话,在执行事务过程中,redis会报错,将事务队列中所有事务回滚,一个都不执行)

redis 127.0.0.1:6379> get balance
"1151"
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> getset balance
(error) ERR wrong number of arguments for 'getset' command
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
redis 127.0.0.1:6379> get balance
"1151"

可以看出,balance没有改变

4.冤有头债有主(当执行事务过程中执行失败报错(注意,不是进入队列过程中报错),redis将执行其他命令)

redis 127.0.0.1:6379> get balance
"1151"
redis 127.0.0.1:6379> set k1 v1
OK
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> incr k1
QUEUED
redis 127.0.0.1:6379> get balance
QUEUED
redis 127.0.0.1:6379> EXEC
1) (integer) 1181
2) (error) ERR value is not an integer or out of range
3) "1181"

5.WATCH监视,但开启WATCH监视key时,如果在操作过程中有其他人对key进行过修改,那么本次事务失败。(一旦执行了exec之前加的监控锁都会被取消掉了。)

WATCH监视balance并开启事务

redis 127.0.0.1:6379> get balance
"1181"
redis 127.0.0.1:6379> WATCH balance
OK
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> incrby balance 30
QUEUED
redis 127.0.0.1:6379> incrby balance 100
QUEUED

这时候再开启一个客户端对balance操作

redis 127.0.0.1:6379> incrby balance 10
(integer) 1191

回到原客户端进行操作,可以看出,执行事务失败了。

redis 127.0.0.1:6379> incrby balance 10
QUEUED
redis 127.0.0.1:6379> EXEC
(nil)

对于Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行。

通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。

redis事务特性:

  • 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
  • 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。

所以,redis对事务的支持是部分的。

复制

也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。主要用来读写分离、容灾恢复。

redis主从复制配从(库)不配主(库)

怎么使用:

修改配置文件细节

1.开启daemonize yes

daemonize yes

2.修改pid管道

pidfile /var/run/redis6380.pid

3.修改端口

# Accept connections on the specified port, default is 6379.
# If port 0 is specified Redis will not listen on a TCP socket.
port 6380

4.修改log文件名字

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile "6380.log"

5.修改dump文件名字

# The filename where to dump the DB
dbfilename dump6380.rdb

6、修改从机的redis.conf,配置slaveof 为主机的ip地址和端口号,如果这里不修改的话,也可以在从机客户端通过命令slaveof 192.168.25.1 6379,但这种启动方式只要从机重新启动就要重新配置。

# slaveof <masterip> <masterport>
slaveof 192.168.25.1 6379

7、通过配置文件启动从机(一定要使用配置文件启动,否则还是使用默认的端口)

如果配置成功的话,在从机客户端输入命令info replication,得到如下

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:192.168.25.1
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:jd
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

###主从复制常用方式

一、一主二仆

配置一台主机两台从机,如上面方式配完后,从机将完整地主机里的内容复制过来(在从机启动之前主机的数据也会被复制过来)。在主机挂掉后从机会原地待命,直到与主机重新连接上。并且,从机不可用写,如何写的话,将会报错,如下:

127.0.0.1:6380> set k1 v1
(error) READONLY You can't write against a read only slave.

二、薪火传承

在有多台从机的情况下,可以让从机即当从机又当主机,如6380作为6379的从机,又作为6381的主机。这样可以减轻主机压力。这样,上一个从机可以是下一个从机的主机,从机同样可以接收其他从机的连接和同步请求,那么该从机作为了链条中下一个的主机,可以有效减轻master的写压力

三、反客为主

在主机挂掉的情况下,通过SLAVEOF no one命令,使当前从机停止与其他数据库的同步,转成主机。然后设置其他从机跟随新的主机。

四、哨兵模式

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。

步骤:

1、创建sentinel.conf文件

2、在文件里添加

 sentinel monitor 被监控数据库名字(自己起名字) 127.0.0.1 6379 1

上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机

也可以通过一组sentinel能同时监控多个Master

3、启动哨兵

哨兵模式下如果主机挂了,则哨兵会监控到,并让其他从机投票选举出新的主机。如果原来的主机回来,则会变成从机。

复制原理:

  • slave启动成功连接到master后会发送一个sync命令

  • Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步

  • 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。

  • 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步

  • 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

复制的缺点:

由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值