Redis(3)---Redis事务|主从复制

Redis事务

Redis 通过 MULTI 、EXEC、 DISCARD  和 WATCH 四个命令来实现事务功能。

        MULTI :标记一个事务块的开始。

         EXEC: 执行所有事务块内的命令。

 DISCARD :取消事务,放弃执行事务块内的所有命令。

WATCH key [key ...] :监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

一、事务

   1、是什么?

     可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,不许加塞!

   2、能干什么?

     一个队列中,一次性的、顺序性的、排他性的执行一系列的命令。要么一起成功,要么一起失败。排好队,一次性的执行多个redis的命令!

   3、怎么玩?

   通过MULTI指令开启,之后输入多个命令!Redis将它们加入到队列当中,所有的命令通过EXEC来开启执行!通过DISCARD来放弃本次的批处理操作!

 (1)正常执行(好比购物先加入购物车,最后EXEC统一结账。)

复制代码
192.168.1.66:6379> MULTI    --开启事务
OK
192.168.1.66:6379> set k1 v1
QUEUED
192.168.1.66:6379> set k2 v2
QUEUED
192.168.1.66:6379> set k3 v3
QUEUED
192.168.1.66:6379> set k4 v4
QUEUED
192.168.1.66:6379> get k2
QUEUED
192.168.1.66:6379> EXEC  --结束事务
1) OK
2) OK
3) OK
4) OK
5) "v2"
复制代码

  (2)DISCARD 撤销所有操作!

复制代码
192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> set k1 11
QUEUED
192.168.1.66:6379> set k2 22
QUEUED
192.168.1.66:6379> set k3 33
QUEUED
192.168.1.66:6379> DISCARD
OK
192.168.1.66:6379> get k1  --这里的k1的value值还是上面的值,而不是新设置的value值
"v1"    
复制代码

  (3)加入队列时不出错,下面的都将正常运行,执行时出错不影响其他语句!

复制代码
192.168.1.66:6379> set k1 v1
OK
192.168.1.66:6379> set k2 v2
OK
192.168.1.66:6379> MULTI
OK
192.168.1.66:6379> incr k1
QUEUED
192.168.1.66:6379> set k2 22
QUEUED
192.168.1.66:6379> EXEC
1) (error) ERR value is not an integer or out of range --在运行是才发现k1不是数字,报错
2) OK     --执行成功
复制代码

注意:
   (1)当遇到执行错误时,redis放过这种错误,保证事务执行完成。(所以说redis的事务并不是保证原子性)
   (2)与mysql中事务不同,在redis事务遇到执行错误的时候,不会进行回滚,而是简单的放过了,并保证其他的命令正常执行。这个区别在实现业务的时候,需要自己保证逻辑符合预期。
   (3)当事务的执行过程中,如果redis意外的挂了。很遗憾只有部分命令执行了,后面的也就被丢弃了。当然如果我们使用的append-only file方式持久化,redis会用单个write操作写入整个事务内容。即是是这种方式还是有可能只部分写入了事务到磁盘。发生部分写入事务的情况 下,redis重启时会检测到这种情况,然后失败退出。可以使用redis-check-aof工具进行修复,修复会删除部分写入的事务内容。修复完后就 能够重新启动了。

 

Redis主从复制

一、环境搭建

     既然是主从复制,那肯定需要多个redis服务器,下面我先创建3个服务器,™的端口号分别是:6379、6380、6381。

  1、复制默认配置文件redis.conf,放到rediszhucong文件夹中,并重命名。

 

 根据每个端口号不同,重新配置conf文件

 (1)端口号

   

 (2)开启线程守护

  

 (3)Pid文件名字

 (4)Log文件名字

 (5)Dump.rdb名字

 

2、在redis-server目录下,读取配置启动这三个redis

    ./redis-server ../../rediszhucong/redis6379.conf
    ./redis-server ../../rediszhucong/redis6380.conf
    ./redis-server ../../rediszhucong/redis6381.conf

  查看进程

  3、打开多个界面进行操作

./redis-cli -p 6379
./redis-cli -p 6380
./redis-cli -p 6381

     成功打开三个服务器

 

二、主从复制

   1、是什么?

    行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。

  2、 能干嘛?

   读写分离,更加安全,性能提升。

  3、怎么玩?

   一主二仆、薪火相传、反客为主

 (1)一主二仆

  1. 配从不配主
  2. slaveof 主库ip 主库端口

    我这里把6379当成主库,所以只要在6380和6381端口输入:

   

   

   通过info replication 查看是否配置成功。

  可以看到6379端口服务器,role角色是master,同时下面有两个从服务器

 

  再看6380端口,role显示为slave。

 

总结:

    (1)如果master服务器挂了,那么6380,和6381角色依旧是slave

     (2)如果master又好了,那么一切正常,下面还是有两个从,自己还是主。

     (3)如果slave服务器挂了,那么重启后,需要重新slaveof 选择master,除非在配置文件中配置

 (2)薪火相传

  新火相传的意思其实就是去中心化,现在只有80和81两台slave连接master,假如,有100台slave的话,那么master就压力很大了,所以redis又推出了新火相传的解决方案,上一台slave,可以下一台slave的master.

  79和80不改变,在81上配置如下:

127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK

(3)反客为主

   上面提到了,当master死机的时候,重写启动还是master,现在时,我是想当master死机的时候,让某一台从机变成主机,这里是,让80变成主机,

   只要当master死机器的时候,手动在80执行如下命令:

127.0.0.1:6380> SLAVEOF no one

   同时,81也要重新配置,配置80为主机

127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK

三、哨兵模式

   虽然说,反客为主,已经不错了,但总不能一旦master挂掉,我在手动去重新配置主服务器,和slave服务器吧。

   简单的说,哨兵模式就是反客为主的自动版,通过监控主机,当主机挂掉的时候,就几台从机中透过投票选出新的主机

  1、在 /etc/redis/目录下新建一个sentinel.conf文件(这个目录随意,但名字一定叫sentinel.conf)

  里面的内容为:

sentinel monitor host6379 127.0.0.1 6379 1 

 意思是6379端口的服务器是现在的master,host6379是自己任意取的名字,上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机

 2、启动sentinel.conf 文件

./redis-sentinel ../sentinel.conf 

 

 表示成功!

这是注意:

     就是当原来的master回来后,不是做独立的mater,而是做新主机的slave

   当我输入:SHUIDOWN命令,代表kill端口的redis,当我重新启动6379端口后,发现他的角色变成了:slave

二、WATCH

       WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。

       被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回空多条批量回复(null multi-bulk reply)来表示事务已经失败。

1、首先我们不加WATCH进行事务处理

时间

客户端A

客户端 B

说明

T1

SET name aa

SET age  10

GET name

aa

GET age

10

数据库中两客户端登录,及键初始值。

它们是同步的。

T2

MULTI

SET name bb

Incr age

 

此时,客户端1开启事务,并提交队列命令:

1.想要将当前age自增+1运算;

2.将name值改为bb

T3

 

SET name cc

Incr age

此时,客户端2修改了age值

同时修改name值为cc

T4

EXEC

 

 

T5

GET name

bb

GET age

12

此时,客户端1执行队列命令,发现运算之后age不是理想中的11,而是12原因是被其它客户插足抢先给修改了。name值确实是没有被其它所改变。这样可能导致数据不一致性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、添加WARCH

客户端1-引入“乐观锁”机制 客户端2 说明
 SET age
"10"
 SET name
"zhangsan"

 GET age
"10"
 GET name
"zhangsan"
数据库中两客户端登录,及键初始值。
 WATCH    age name
OK
 MUTLI
OK
 incr age
QUEUED
 set name lisi
QUEUED
  此时,客户端1用watch命令监视age和name,然后开启事务,并提交队列命令
   incr age
(integer) 11
此时,客户端2修改了age值

 exec
(nil)
 get age
"11"
 get name
"zhangsan"
  此时,客户端1执行队列命令,由watch监控发现此期间age的值已经被修改过,则让事整个务回滚,不做任何动作。

watch可以同时监控多个键,在监控期间只要有一个键被其它客户端改变,则整个事务回滚。
posted @ 2022-02-20 21:03  hanease  阅读(63)  评论(0编辑  收藏  举报