zoukankan      html  css  js  c++  java
  • python学习笔记4-redis multi watch实现锁库存

      python 关于redis的基本操作网上已经很多了,这里主要介绍点个人觉得有意思的内容1.redis的事务操作以及watch 乐观锁;后面描述2.tornado下异步使用redis的方式
         
      redis是单进程单线程模型,本身应对外部请求的是单任务的,也是多线程安全的,这个大家都应该知道的, 所以才会经常有人用redis做计数服务。
         
      首先redis 的事务处理只能使用pipeline:In redis-py MULTI and EXEC can only be used through a Pipeline object.
       
      很多人喜欢在处理电商库存,例如秒杀活动的时候用redis做计数器,不过下面这段代码采用了事务来控制库存,是不是有点问题呢?
    if __name__ == "__main__":
        with sms_redis.pipeline() as pipe:
            while 1:
                try:
                    # 事务开始
                    pipe.multi()
                    count = int(sms_redis.get('stock_count'))
                    if count > 0:  # 有库存
                        pipe.set('stock_count', count - 1)
                    # 事务结束
                    pipe.execute()
                    # 把命令推送过去
                    break
                except Exception:
                    traceback.print_exc()
                    continue
      问题在于误以为pipe.multi() 事务处理执行后,就可以锁住该库存,这里强调下:
    redis 本身没有悲观锁的概念,也就是说对于客户的是无法锁住redis中的值的,当然你可以通过其它曲径实现,比如SETNX, 这里先不谈;
    redis 的事务可以认为是一段命令的批量执行和执行结果一次性返还,事务操作本身没有问题,执行过程不会中断,但是在pipe.execute() 的时候事务才真正向redis_server 提交,但是很遗憾在redis_server 执行之前库存都有机会被其它客户端修改,完全起不到锁库存概念
     
      那么如何才能实现锁库存呢?watch是一个很好的解决方案:
      watch 字面就是监视的意思,这里可以看做为数据库中乐观锁的概念,谁都可以读,谁都可以修改,但是修改的人必须保证自己watch的数据没有被别人修改过,否则就修改失败了;
     
    if __name__ == "__main__":
        with sms_redis.pipeline() as pipe:
            while 1:
                try:
                    #关注一个key
                    pipe.watch('stock_count’)
                    count = int(pipe.get('stock_count'))
                    if count > 0:  # 有库存
                        # 事务开始
                        pipe.multi()
                        pipe.set('stock_count', count - 1)
                        # 事务结束
                        pipe.execute()
                        # 把命令推送过去
                    break
                except Exception:
                    traceback.print_exc()
                    continue
      如果在watch后值被修改,在执行pipe.execute()的时候会报异常WatchError: Watched variable changed.
    这里可以简单的实现基于redis中的锁库存的逻辑。
     
     
     
     
  • 相关阅读:
    delphi实现FTP下载
    delphi中ClientDataSet的隐含功能
    删除注册的ODBC
    ZOJ 1041 Transmitters
    POJ 3232 Accelerator
    POJ 3460 Booksort
    UVa 11552 Fewest Flops
    SOJ 8064 Whack the Groundhog
    BNU OJ 29355 手速为王
    POJ 3322 Bloxorz I
  • 原文地址:https://www.cnblogs.com/suyuan1573/p/6037066.html
Copyright © 2011-2022 走看看