原子性

原子性是数据库的事务中的特性。在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。

Redis操作原子性的原因

Redis的操作之所以是原子性的,是因为Redis是单线程的。

由于对操作系统相关的知识不是很熟悉,从上面这句话并不能真正理解Redis操作是原子性的原因,进一步查阅进程与线程的概念及其区别。

进程与线程

  • 进程

    计算机中已执行程序的实体。比如,一个启动了的php-fpm,就是一个进程。
  • 线程

    操作系统能够进行运算调度的最小单元。它被包含在进程之中,是进程的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。比如,mysql运行时,mysql启动后,该mysql服务就是一个进程,而mysql的连接、查询的操作,就是线程。

进程与线程的区别

  • 资源(如打开文件):进程间的资源相互独立,同一进程的各线程间共享资源。某进程的线程在其他进程不可见。
  • 通信:进程间通信:消息传递、同步、共享内存、远程过程调用、管道。线程间通信:直接读写进程数据段(需要进程同步和互斥手段的辅助,以保证数据的一致性)。
  • 调度和切换:线程上下文切换比进程上下文切换要快得多。

    线程,是操作系统最小的执行单元,在单线程程序中,任务一个一个地做,必须做完一个任务后,才会去做另一个任务。

Redis在并发中的表现

Redis的API是原子性的操作,那么多个命令在并发中也是原子性的吗?

看看下面这段代码:

$redis= newRedis();
$redis->connect('127.0.0.1',6379);
for($i= 0;$iget('val');
$num++;
$redis->set('val',$num);
usleep(10000);
}

用两个终端执行上面的程序,发现val的结果是小于2000的值,那么可以知道,在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的。

如果想在上面的程序中实现原子性,可以将get和set改成单命令操作,比如incr,或者使用Redis的事务,或者使用Redis+Lua的方式实现。

原子性总结

综上所述,对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。

Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。

事务

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

事务的关键字

  • EXEC 命令负责触发并执行事务中的所有命令:

    如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。
  • 另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。

    当使用 AOF 方式做持久化的时候, Redis 会使用单个 write(2) 命令将事务写入到磁盘中。

    然而,如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。

    如果 Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。

    使用redis-check-aof程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。

    从 2.2 版本开始,Redis 还可以通过乐观锁(optimistic lock)实现 CAS (check-and-set)操作,具体信息请参考文档的后半部分。

事务的语句

> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

为什么 Redis 不支持回滚(roll back)

如果你有使用关系式数据库的经验, 那么 “Redis 在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。

以下是这种做法的优点:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

    有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。 举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

知其所以然~redis的原子性的更多相关文章

  1. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

  2. InnoDB,5项最佳实践,知其所以然?

    InnoDB,5项最佳实践,知其所以然? 原创: 58沈剑 架构师之路 昨天 缓存讲了一个月<缓存架构,一篇足够>.今天,开始写数据库. 第一篇,说说MySQL两个最常用的存储引擎,MyI ...

  3. redis的原子性

    什么是原子性操作 在多进程(线程)访问共享资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源,(要么完全执行,要么完全不执行) 简单描述 有个变量X=0,要进行+1操作,步骤如下: ...

  4. 感想篇:7)知其然与知其所以然,KnowHow与KnowWhy

    本章目的:探究--知其然与知其所以然,KnowHow与KnowWhy. 1.Know-How体系与代价: 100多年的汽车研发历史表明,企业只有开发过两代车以上才能逐步建立和完善Know-How体系. ...

  5. 一看便知_linux安装redis和调试

          rpm包下载地址:     http://vault.centos.org/6.3/os/x86_64/Packages/1.进入目录,解压文件 # tar  -zxvf  redis-3 ...

  6. 知其所以然~分布式事务cap

    背景 一致性是一个抽象的.具有多重含义的计算机术语,在不同应用场景下,有不同的定义和含义.在传统的IT时代,一致性通常指强一致性,强一致性通常体现在你中有我.我中有你.浑然一体:而在互联网时代,一致性 ...

  7. 初见TensorFlow :知其所以然

    2.1 TensorFlow的主要依赖包 TensorFlow依赖的两个最主要的工具包——Protocol Buffer和Bazel. 2.1.1 Protocol Buffer Protocol B ...

  8. 读FCL源码系列之List<T>---让你知其所以然---内含疑问求大神指点

    序言 在.NET开发中,List<T>是我们经常用到的类型.前段时间看到其他部门小伙伴讨论“两个List(10W个元素)集合求并集,list1.Where(p=>list2.Cont ...

  9. 知其所以然~mongodb副本集

    MongoDB 复制(副本集) MongoDB复制是将数据同步在多个服务器的过程. 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. 复制还允许您 ...

随机推荐

  1. [OC] UIcollectionView 与 UIcollectionViewCell 的使用

    UICollectionView    @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSou ...

  2. css 控制横向布局,超出隐藏,滚动

    <!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta cha ...

  3. 安装使用eclipse

    安装使用eclipse 目标 java学习需要,老师说要安装eclipse,,其实已经下了IDEA了,不过还是听老师的比较好( 准备 jre 也就是java运行环境,因为之前就下了jdk(里面包含jr ...

  4. redis + cookies 实现持久登入

    通过登入把用户信息和token加载到redis中去, 将token和部分用户信息存储在cookie中, 下次登入时 判断cookie的token在redis中是否存在, 存在就把用户信息加载出来自动登 ...

  5. 关于A2C算法

    https://github.com/sweetice/Deep-reinforcement-learning-with-pytorch/blob/master/Char4%20A2C/A2C.py ...

  6. 【PHP版】火星坐标系 (GCJ-02) 与百度坐标系 (BD-09ll)转换算法

    首先感谢java版作者@宋宋宋伟,java版我是看http://blog.csdn.net/coolypf/article/details/8569813 然后根据java代码修改成了php代码. & ...

  7. Centos7 编译测试工具 wrk bombardier iftop

    1.wrk 安装及使用----------------------------------------------------------------------------------------- ...

  8. Spring Cloud 组件 —— feign

    feign 作为一个声明式的 Http Client 开源项目.在微服务领域,相比于传统的 apache httpclient 与在 spring 中较为活跃的 RestTemplate 更面向服务化 ...

  9. Servlet 上传下载文件

    上传文件 1)在表单中使用表单元素 <input type=“file” />,浏览器在解析表单时,会自动生成一个输入框和一个按钮 2)表单需要上传文件时,需指定表单 enctype 的值 ...

  10. webpack配置非CMD规范的模块

    一.前言 webpack在配置多页面开发的时候 ,发现用 import 导入 Zepto 时,会报 Uncaught TypeError: Cannot read property 'createEl ...