什么时候需要进行需要原子操作?

很常见的例子,就是利用Redis实现分布式锁。

实现锁需要哪些条件?

我们知道要实现锁,就需要一个改变锁状态的方法。这个方法能原子地对锁的状态进行检查并修改。如果修改成功,则意味着获得了锁。对于硬件,它提供的就是test-and-set,compare-and-swap等原语。

Redis有没有提供类似的原语呢?

有的。Redis有提供setnx(),它会提供这样的原子操作:如果key没有值,则将值设置进去,如果已有值就不做处理,提示失败。

这样就可以基于这个原语来实现锁,简单原理就是:key就是对应的锁,如果key有值就说明锁被占用。删除值代表释放锁。如果插入值成功,则代表获得锁。再加上过期时间,基本就可以满足分布式锁的需求了。

除了锁,还有哪些地方需要原子操作?

假如我们在操作Redis数据的时候,需要判断Redis中某个值是否满足条件,只有满足条件才做这个操作

我随便举个例子,例如:如果key-xxx的值不为0,则加1,如果为0,则删除。

这种情况Redis可以处理吗?

可以,Lua脚本。Redis支持Lua脚本。针对上面的问题,我们只要写这样的Lua脚本就可以了。

local a = redis.call('get', 'xxx') //调用redis的get方法,key为'xxx'
if(tonumber(a) > ) then //redis都是以String进行存储的,需要转型
redis.call('incr', 'xxx') //调用redis的incr方法,key为'xxx'
return 'OK'
else
return 'FAIL'

为什么Lua脚本可以实现原子操作, 看不出来它有用锁啊?

这与Redis的请求处理有关。Redis只用一个线程来处理客户端的请求。所以在执行lua脚本的时候,没有其他客户端的请求在处理。所以在lua脚本中的对redis数据的修改操作就是原子的。

只用一个线程处理的过来吗?

Redis的请求处理线程,利用Select和事件循环进行处理,大概就是下面这样:

while() {
events = getEvents(); //先利用SELECT拿到最近的请求
for(e in events) //然后逐个处理
processEvent(e);
}

由于使用的是select()来处理网络I/O,所以线程不会在一个socket连接上阻塞。另一方面因为redis的操作的数据都在内存中。处理起来也很快,所以也不会出现响应时间太长的情况。

万一这个线程阻塞了怎么办?

一般情况下,阻塞不了。前面也说了,客户端上来的请求都是操作内存的,不会有其他调用(例如文件I/O这样的调用)。但是,这是一般情况。别忘了lua,lua脚本里面是可以写阻塞操作的(比如文件I/O,或者最简单的死循环)。实测发现,如果往Redis中提交一个死循环的lua脚本,Redis就挂了。所以写lua脚本的时候要小心。

【杂谈】如何对Redis进行原子操作的更多相关文章

  1. 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法

    "为什么这个功能用不了?" 程序员:"清一下缓存" 上篇洞悉系列文章给大家详细介绍了MySQL的存储内幕:洞悉MySQL底层架构:游走在缓冲与磁盘之间.既然聊过 ...

  2. Redis的介绍及使用实例.

    本文就来讲一下Redis安装的方法和Redis生成主键的优点以及和其他几种方式生成主键的对比. 1,Redis安装首先将Redis的tar包拷贝到Linux下的根目录 然后解压到redis文件夹下:( ...

  3. redis学习(一)

    一.redis简介 Redis是基于内存.可持久化的日志型.key-value高性能存储系统.关键字(Keys)是用来标识数据块.值(Values)是关联于关键字的实际值,可以是任何东西.有时候你会存 ...

  4. Redis缓存你必须了解的!

    不管你是从事Python.Java.Go.PHP.Ruby等等… Redis都应该是一个比较熟悉的中间件.而大部分经常写业务代码的程序员,实际工作中或许只用到了set value.get value两 ...

  5. redis实现高并发下的抢购/秒杀功能

    之前写过一篇文章,高并发的解决思路(点此进入查看),今天再次抽空整理下实际场景中的具体代码逻辑实现吧:抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢 ...

  6. 使用Redis实现抢购的一种思路(list队列实现)

    原文:https://my.oschina.net/chinaxy/blog/1829233 抢购是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如 ...

  7. Redis 真得那么好用吗?

    不管你是从事Python.Java.Go.PHP.Ruby等等......Redis都应该是一个比较熟悉的中间件.而大部分经常写业务代码的程序员,实际工作中或许只用到了set value.GetVal ...

  8. Redis真的那么好用吗

    Redis是什么 Redis是一个开源的底层使用C语言编写的key-value存储数据库.可用于缓存.事件发布订阅.高速队列等场景.而且支持丰富的数据类型:string(字符串).hash(哈希).l ...

  9. Redis分布式之前篇

    第一篇:初识Redis 一.Redis是什么? Redis 是一个开源(BSD许可)的,使用ANSI C语言编写的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据 ...

随机推荐

  1. 解释一下,知乎上关于C语言奇技淫巧最火的回答。

    前几天逛知乎,碰巧发现一个很火的问题. “C 语言有什么奇技淫巧?”虽然问题本身没有什么特殊的地方,但是网友的回答却是非常幽默. 下面就让我们一起来分析一下,被赞最多的答案“C 语言运算符 趋向于‘- ...

  2. IIS7上传4M文件以上文件出现“Post大小超出允许的限制”错误解决方法

    在web.config文件中的system.web节点中添加如下这句,即40M <system.web> <httpRuntime maxRequestLength = " ...

  3. Java---使用EWS读取exchange邮件

    第一步: 下载EWS API相关包: 从如下路径下载EWS API包:http://code.msdn.microsoft.com/Exchange-EWS-Java-API-12-1a5a1143 ...

  4. Mac下安装redis5.0 与命令

    参考链接:https://blog.csdn.net/zyp1376308302/article/details/84257606 参开链接2:https://www.cnblogs.com/guan ...

  5. Mac 简单切换jdk版本

    https://www.cnblogs.com/c-xiaohai/p/6985018.html dmg安装包安装 vim ~/.bash_profile_jdk export JAVA_8_HOME ...

  6. 【Mac】Mac快捷键与Mac下的Idea快捷键

             本人之前一直在windows平台下进行开发,刚接触Mac的时候有些许的不适应,无论是无鼠标操作,还是文件系统的变更,以及键盘格式以及系统快捷键的变更,都曾对自己造成过一定程度的困扰. ...

  7. php __autoload 在有命名空间的时候失效(使用的局限性)

    如果要使用__autoload方法,则不能再之前使用namespace,    使用命名空间,则至少php5.3不再调用__autoload方法    因此如果需要使用__autoload和命名空间, ...

  8. Salesforce LWC学习(二) helloWorld程序在VSCode中的实现

    上一篇我们简单的描述了一下Salesforce DX的配置以及CLI的简单功能使用,此篇主要简单描述一下LWC如何实现helloWorld以及LWC开发时应该注意的一些规范. 做国内项目的同学直观的感 ...

  9. CRISP-DM--数据挖掘标准流程

    CRISP-DM--数据挖掘标准流程 在1996年的时候,SPSS,戴姆勒-克莱斯勒和NCR公司发起共同成立了一个兴趣小组,目的是为了建立数据挖掘方法和过程的标准.并在1999年正式提炼出了CRISP ...

  10. 抽丝剥茧分析asyncio事件调度的核心原理

    先来看一下一个简单的例子 例1: async def foo(): print('enter foo ...') await bar() print('exit foo ...') async def ...