亚马逊产品备案网站建设要求,东营做网站优化多少钱,银行内部网站建设建议,计算机网页设计专业学什么事务
一个成熟的数据库系统一般都会有事务的支持#xff0c;Redis作为一个缓存数据库也不例外#xff0c;Redis的事务比之关系型数据库mysql#xff0c;oracle等算比较简单的#xff0c;Redis中无需理解那么多事务模型#xff0c;可以直接使用。不过也正是因为简单#…事务
一个成熟的数据库系统一般都会有事务的支持Redis作为一个缓存数据库也不例外Redis的事务比之关系型数据库mysqloracle等算比较简单的Redis中无需理解那么多事务模型可以直接使用。不过也正是因为简单redis的事务模型是不严谨的不能像关系型数据库那么用Redis的事务。
Redis事务的基本用法
每个事务操作的基本过程都有如下begin commit和rollback如下 begin指令标识事务的开始commit指令标识事务的提交rollback指令标识事务的回滚
begin();
try{command1();command2();....commit();
}cache(Exception e){rollback();
}Redis事务形式上基本相同指令分别是multi execdiscard multi事务开始exec事务执行discard事务丢弃
新docker-redis:0multi
OK新docker-redis:0incr books
QUEUED新docker-redis:0incr books
QUEUED新docker-redis:0exec1) 22) 3以上过程如下图所示所有指令在exec之前都不执行二手缓存在服务器的一个服务队列中服务器一旦收到exec指令才开始执行整个事务队列执行完后一次性返回所有指令结果因为Redis 是单线程不用担心自己在执行队列的时候被其他指令打搅保证原子性。
原子性
事务的原子性指要么全部成功要么都失败Redis的事务是非原子性的。如下案例。
新docker-redis:0multi
OK新docker-redis:0set books iamastring
QUEUED新docker-redis:0incr books
QUEUED新docker-redis:0set poorman iamdesperate
QUEUED新docker-redis:0exec1) OK2) ERR value is not an integer or out of range3) OK如上案例是事务执行到中间有一条指令是执行失败的提示不能对字符串进行累加。但是后面的指令还是可以成功执行所有poorman 的值是正常设置此处说明Redis事务不具备原子性而仅仅是满足了事务的“隔离性”中的串行化-----当前执行的事务有不被其他事务打断的权利。
discard丢弃
Redis为事务提供discard指令用于丢弃事务缓存队列中所有指令在exec执行之前。
新docker-redis:0get books
null新docker-redis:0multi
OK新docker-redis:0incr books
QUEUED新docker-redis:0incr books
QUEUED新docker-redis:0 discard
OK新docker-redis:0exec
ERR EXEC without MULTI新docker-redis:0get books
null执行discard后队列中所有指令都没有执行我们执行exec后提示无法执行空的队列
Redis事务的优化
Redis事务在发送每个指令到事务队列缓存时候需要经一次网络读写当一个事务内部指令较多需要的IOShi就也会线性增加所以同城Redis客户端在执行事务时候回结合pipeline一起使用这样可以将多次IO操作压缩为单次。例如java中Redis的使用
public class MultiTest {public static void main(String[] args) throws IOException {Jedis jedis JedisPoolTools.getJedis();Pipeline pipe jedis.pipelined();pipe.multi();pipe.incr(books);pipe.incr(books);ResponseListObject value pipe.exec();pipe.close();System.out.println(value.get());}
}watch
当有一个业务场景Redis存储账户余额是一个整数多个客户端并发修改余额这个修改不是简单的incrby而是需要通过一个逻辑计算但是Redis单指令无法完成我们需要先取出计算在存储。这样就是去原子性有并发问题 方案一我们用Redis分布式锁来避免冲突分布式锁是悲观锁只允许一方持有锁其他等待方案二Redis提供watch机制是乐观锁有watch我们又多了一种可以解决并发修改的方法。watch使用方法如下。
public static void main(String[] args) {Jedis jedis JedisPoolTools.getJedis();jedis.watch(books);jedis.set(books , 100); //此处已经修改最终返回nullPipeline pipe jedis.pipelined();pipe.multi();pipe.incr(books);pipe.incr(books);try {ResponseListObject value pipe.exec();pipe.close();System.out.println(value.get());}catch (Exception e){System.out.println(e.getMessage());}}watch会在事务开始之前叮嘱一个或者多个关键变量流程如下 当事务执行之后执行exec命令后要顺序执行缓存的指令队列Redis检查关键变量watch之后是否被修改如果被变量被修改过exec指令将返回null通知客户端执行失败此时我们可以重试或者其他逻辑
注意
Redis禁止在multi 和exec之间执行watch必须在multi之前执行watch否则抛出异常。
上一篇Redis持久化-深入理解AOFRDB 下一篇Redis存储优化–小对象压缩