1.redis事务

事务实际上指的是一组命令的集合,执行时会按顺序串行的执行,中途不能加入其它命令。它用来解决批处理需求。

在redis中的基本使用如下:

>multi

ok

>incr books

QUEUED

>exec

(integer) 1

(integer) 2

multiexec就是事务开始和结束的标志,中间就是事务的具体内容。事务的丢弃可用discard命令,所有的事务在exec之前都不会执行。

redis的事务有以下特点:

1.全体连坐

            >set books python
ok
>multi
ok
>set a1 b1
QUEUED
>cbaafasfaf books linux
(error) ERR unknown command 'cbaafasfaf'
>set a2 b2
QUEUED
>exec
(error) EXECABORT Transaction discarded because of previous errors.
>get a1
(nil)
>get a2
(nil)

可见multi语句中,每输入一次指令都会被检测一次,当出现错误语法时会直接返回一个error,之后exec提交后会发现事务中的语句都不会被执行。

2.冤有头债有主

        >set books redis
ok
>multi
ok
>set k1 v1
QUEUED
>incr books
QUEUED
>set k2 v2
QUEUED
>exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
>get k1
"v1"
>get k2
"v2"
>get books
"redis"

可见,redis事务将正确的指令都执行了,只卡住了错误的命令。这是为什么呢?

实际上redis事务并不是一种严格的事务,只要是中间没有明显的特别明显的错误,就会将正确的指令都执行,只抛弃错误的指令。而且redis的事务也不支持回滚这种操作。

2.悲观锁和乐观锁

悲观锁即认为客户端的操作一定会引起数据混乱,为了防止数据的错误操作,在对数据操作之前会对要操纵数据所在的数据库表进行不同范围的上锁,防止误操作。

而乐观锁认为,客户端操作基本不会对数据造成影响,只对一些认为可能出问题的数据上锁。

具体操作如下:

悲观锁:利用数据库的表锁和行锁或其他锁机制实现

乐观锁:redis利用watch方法实现,其本质上也是加了把锁,当其他请求修改了被watch数据之后,事务就会执行失败,这就需要重新发起请求。需要注意的是在redis中,watch只能用在事务开始之前,否则会出错。

基本使用如下:

import redis

def key_for(user_id):
return 'account_{}'.format(user_id) def bussiness(client,user_id):
key = key_for(user_id)
while True:
client.watch(key)
# 数值加倍
value = int(client.get(key))
value *= 2
#用管道提交事务
pipe = client.pipeline(translation=True)
pipe.multi()
pipe.set(key,value)
#尝试提交事务,成功时跳出循环;失败时重新尝试。
try: pipe.exec()
break
except WatchError:
continue
return int(client.get(key)) client = redis.StructRedis()
user_id = 'abc'
client.setnx(key_for(user_id),5) #初始化
print(bussiness(client,user_id))

借用管道可以将事务中的多次I/O操作压缩成单次I/O,提高效率。在python的redis客户端中提交事务是要强制使用pipeline的。

悲观锁尽管很安全,但是在在执行时要有拿锁,操作数据,释放锁的流程,且其他的请求在这个过程只能等待。并发情况下,尤其在高并发请求时,速度是真的慢。所以它一般只适用于要对数据库做大改动或其他重要的情况下进行。

乐观锁适用于读操作为主要请求,对数据安全性要求不苛刻的情况下,可以显著提升高并发情况下的请求处理速度。

最新文章

  1. ubuntu安装libxml2--PC端
  2. Windows Server 2016 预览版下载
  3. android和httpClient
  4. 使用Soapui测试webservice接口
  5. OpenCV GPU CUDA OpenCL 配置
  6. TCP/IP 之大明王朝邮差
  7. UIImageView 的contentMode属性
  8. COM组件(MFC篇)
  9. CSS3 background-size图片自适应
  10. jquery 实现层级下拉框联动效果 代码
  11. Java NIO 学习笔记
  12. vue + vuex 表单处理
  13. Java随机数生成原理--转稿
  14. Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition
  15. Jmeter自带录制功能
  16. js中布尔值为false的六种情况
  17. GO语言的进阶之路-初探GO语言
  18. 3.3 idea中使用git遇到的一些问题
  19. c#数组去重
  20. 搭建ssm环境

热门文章

  1. DELPHI指针的使用
  2. day23_4_hashlib
  3. Spring 事务传播行为(12)
  4. 使用CEfSharp之旅(1) 加载网络页面
  5. Hibernate的多对多映射
  6. C++函数或者命名空间前面加::
  7. DataTime 和 时间转化
  8. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService
  9. csp-s模拟测试54x,y,z题解
  10. LUOGU P1438 无聊的数列 (差分+线段树)