Redis 中的事务
在我们平常的程序中,不是多个客户端同时处理数据时,程序都会稳定的执行,但是我们都会遇到多个客户端访问的情况,这样就会容易出现数据错误的情况。为了防止这个情况我们才有了事务这一说。那么什么是事务呢?
使用事务
为了方便我们在程序中使用Redis的事务,在Redis中有一个EXEC命令来帮忙除服并执行事务中的所有执行。在客户端开启事务之后如果因为网络的原因断线导致没有成功的执行exec,那事务中的所有命令都不会被执行。另一方面客户端成功执行exec命令后,事务中的所有命令都会执行。
Redis有可能会出现一种事务错误的情况。当我们采用AOF做数据的持久化,在redis中是采用单个的write命令将事务写入到磁盘中。如果redis服务挂掉导致部分事务命令写入到磁盘中 在启动的时候会汇报错误。
怎么使用事务请参考以下命令:
>mutl
>set key value
>set key1 value
>exec
我们使用这个事务,在exec命令中的回复其实是一个数组,数据中的每个元素 都是执行十五中命令产生的回复。并且顺序也是一致的。当客户端处于事务状态时,所有命令都会返回一个QUEUED的状态回复,这些入队命令将在exec中调用时执行。
出现的错误
在事务执行的时候,我们可能会遇到下面两种错误:
那么我们在出现这些异常的时候Redis是怎么解决这个问题的呢。在我们前面说过,Redis在mutl中执行会返回一组数组,并且每个命令都会返回QUEUED的回复,这个代表的是成功,相反 入队失败,大部分客户端就会取消这个事务了。但是Redis的版本不同,情况也不同,在2.6.5以后失败会进行记录,在以前的版本会直接忽略入队失败的命令。
在我们使用redis之前,使用mysql关系型数据库,同样也会使用事务,但是mysql中的事务是会支持数据回滚的,而mysql中却不支持,这是为什么呢?那是因为在Redis中命令只会因为错误的语法失败或者错误的类型键上失败,这就意味错误是在编程阶段造成的,并且不支持回滚,Redis的内部可以保持简单且快速的方式访问。
使用check-and-set命令实现乐观锁和watch命令观察
watch命令用来帮助我们为Redis事务提供check-and-set 行为。watch是通过观察整个事务中这些被操作的键是否被改动来达到监视的行为的。如果至少一个键在执行exec之前被改动过,那么整个事务会被取消,并且返回nil-reply 表示事务失败。watch可以监视多个键 比如这样的watch key key key .
Redis的复制
在我们使用数据的库的时候,经常会用到主从同步的功能,一般都是主库用来插入数据,从库用来读取数据,减少数据库的读取和插入的压力。并且我们在Redis中也看到了这种技术的应用主从复制。主master 与从slave
Redis在复制中主要是依靠了三个主要的机制:
在Redis中,默认使用的是异步复制的方式,特点是高延迟和高性能。 这是绝大多数Redis用例的自然复制模式,但是Redis服务器会一步的确认其从主Redis服务器周期接收到的数据量。但是我们在使用Redis的时候也可以用使用WAIT的命令来请求同步复制某些特定的数据。
复制的安全性
我们在使用复制的功能的时候,应该在两者都开启持久化,如果不能启动,那么也应该配置实例来避免重置后自动重启。如果我们没有持久化当master出现问题的时候,那么其他从节点从master复制就会把自身的数据清空,造成从节点数据也丢失。
复制如何工作的
在redis的master中都有一个replication ID ,这是一个较大的伪随机字符串,标记了一个给定的数据集。每个master都有一个偏移量,master将自己产生的复制刘发送给slave时,发送多少个自己的数据,自身的偏移量就会增加多少。目的是为了有新的操作时,修改自己的数据集并且以这个来更新slave的状态。在Redis的复制过程中全量的重同步要求在磁盘上创建一个RDB文件,然后将它从磁盘加载到内存中,然后slave以此进行数据同步。如果磁盘性能很低的情况下这对于master就是一个压力很大的操作。Redis在2.8.18版本后支持无磁盘的复制版本。子进程直接发送RDB文件给slave.无需使用磁盘作为中间存储介质。
配置Redis的复制
在Redis中配置复制功能还是很方便的,在slave的配置文件加上 slaveof master port 内容。但是我们也说了我们可以使用无磁盘复制,那么我们就需要配置 repl-diskless-sync的相关参数 。详细信息可以看redis.conf
只读性质的slave
在Redis2.6以后 slvve支持 只读模式且默认开启。redis.conf的slave-read-only变量控制这个行为,且可以在运行时使用CONFIG SET来随时开启或者关闭。在只读的模式下拒绝所有写入的命令,我们在redis.conf中的使用rename-command 指令可以禁用上述管理员命令以提高只读的安全性。在Redis的2.8版本以后我们可以拥有N个slave链接到master 时,配置的master才有可能接收写查询。在复制的过程中,无法确保slave是否实际接收到给定的写命令。因此总会有一个数据丢失窗口。原理如下:
然而在这些情况下 redis还有可能出现写入错误的情况,那么当错误时 master会回复一个error并且写入将不被接收。这个特性有两个参数
Redis复制处理key的过期
平常程序中,我们会有一些需求就是需要设置key的过期时间,让key在规定的时间内自然的消失,不需要程序再去执行删除操作。那么我们就可以使用Redis的过期机制来限制key的生存时间。Redis中为了实现这样的功能,没有采用同步时钟的功能,而是使用了另外的三中方式: