zoukankan      html  css  js  c++  java
  • 分布式锁和Redis事务

    分布式锁

    一、高并发产生的问题?

      1、购票: 多个用户抢到同一张票?
      2、购物: 库存只剩1个,被多个用户成功买到?
      ... ...

    二、怎么办

      在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段

    三、原理

      1、多个客户端先到redis数据库中获取一把锁,得到锁的用户才可以操作数据库
      2、此用户操作完成后释放锁,下一个成功获取锁的用户再继续操作数据库

    四、实现

      set key value nx ex 3

    Redis事务

    一特点

    1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
    2. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

    二事务命令

    1、MULTI # 开启事务
    2、命令1 # 执行命令
    3、命令2 ... ...
    4、EXEC # 提交到数据库执行
    4、DISCARD # 取消事务

    三使用步骤

    # 开启事务
    127.0.0.1:6379> MULTI
    OK
    # 命令1入队列
    127.0.0.1:6379> INCR n1
    QUEUED
    # 命令2入队列
    127.0.0.1:6379> INCR n2
    QUEUED
    # 提交到数据库执行
    127.0.0.1:6379> EXEC
    1) (integer) 1
    2) (integer) 1

    四事务中命令错误处理

    # 1、命令语法错误,命令入队失败,直接自动discard退出这个事务
      这个在命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名)
      处理方案:客户端发生了第一个错误情况,在exec执行之前发生的。通过检查队列命令返回值:如果这个命令回答这个队列的命令是正确的,否则redis会返回一个错误。如果那里发生了一个队列命令错误,大部分客户端将会退出并丢弃这个事务
    
    # 2、命令语法没错,但类型操作有误,则事务执行调用之后失败,无法进行事务回滚
       从我们施行了一个由于错误的value的key操作(例如对着String类型的value施行了List命令操作)
       处理方案:发生在EXEC之后的是没有特殊方式去处理的:即使某些命令在事务中失败,所有的其他命令都将会被执行。
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set num 10
    QUEUED
    127.0.0.1:6379> LPOP num
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    127.0.0.1:6379> get num
    "10"
    127.0.0.1:6379> 

    五为什么redis不支持事务回滚

    1、Redis的内部极其简单和快速,来源于它不需要回滚功能

    2、在生产环境中,通常回滚并不能解决来自编程的错误。举个例子,你本来想+1,却+2了,又或者+在错误的类型上,回滚并不能解决。由于无法提供一个避免程序员自己的错误,而这种错误在产品中并不会出现,所以选择一个简单和快速的方法去支持事务

    pipeline补充

    python使用pipeline()与execute()批量进行批量操

    import redis
    
    # 创建连接池并连接到redis
    pool = redis.ConnectionPool(host = '192.168.153.130',db=0,port=6379)
    r = redis.Redis(connection_pool=pool)
    
    # 第一组
    pipe = r.pipeline()
    pipe.set('fans',50)
    pipe.incr('fans')
    pipe.incrby('fans',100)
    pipe.execute()
    
    # 第二组
    pipe.get('fans')
    pipe.get('pwd')
    # [b'151', b'123']
    result = pipe.execute()
    print(result)
  • 相关阅读:
    Smarty数据、模版创建指引
    做了个google工具栏的饭否按钮
    php程序调试(远程调试,firephp)
    Linux shell编程与Makefile的一些记录(等待更新)
    My MSSQL Tips
    Castle.ActiveRecord中Save与SaveAndFlush的性能差别
    Linux Basic Approach (My Notes)
    去青城后山玩了一天
    Infopath 2007 使用实践(占位)
    Delphi 6
  • 原文地址:https://www.cnblogs.com/maplethefox/p/11316219.html
Copyright © 2011-2022 走看看