服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - 浅谈Redis如何应对并发访问

浅谈Redis如何应对并发访问

2022-08-01 14:14剑圣无痕 Redis

本文主要介绍了Redis如何应对并发访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

项目中经常会遇到这种场景,我们需要先将Redis数据读取到本地,然后进行修改,修改完成后在将数据写回Redis,这种读取-修改-写回操作,我们称之为RMW操作。当有多个客户端对同一份数据执行RMW操作的话,Redis如何保证RMW操作涉及的代码以原子性方式执行?

浅谈Redis如何应对并发访问

原子性操作

Redis的原子性操作是一种无锁操作,即可以保证并发控制,还能减少系统对并发性能的影响,

单命令模式

把Redis多个操作实现成一个操作,即为单命令模式。

Redis提供了INCR/DECR命令,可以对数据进行增值/减值操作,而且它们本身就是单个命令操作,Redis单线程模式,执行命令时具有互斥性。

示例说明

?
1
2
3
4
5
6
7
8
9
10
11
public Long getIncrNumber(String key,long alive)
   {
       RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
       Long incrNum = entityIdCounter.getAndIncrement();
       if (null == incrNum || incrNum.longValue()==0)
       {
           entityIdCounter.expire(alive,TimeUnit.MILLISECONDS);
           incrNum = entityIdCounter.getAndIncrement();
       }
       return incrNum;
   }

说明:采用Reids的INCR命令,如果不存在的key则设置过期时间,如果key存在则进行递增操作返回。所以如果我们执行RMW操作进行相关的递增或者递减操作时,Redis提供的INCR和DECY命令可以保证并发控制。

多命令模式

当我们不是执行简单的加加减减操作,而是更加复杂的逻辑判断或者其他操作时,Redis是无法保证原子性,所以需要将多个操作写到一个Lua脚本中,Redis会把Lua脚本作为一个整体执行,在执行过程中不会被其他命令打断,从而保证了操作的原子性。

lua简介

Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

示例说明

接口进行限流操作,同一用户3秒内不能重复访问,我们可以通过lua脚本来实现。

?
1
2
3
4
5
6
7
8
9
10
11
12
local key = KEYS[1]
local count = tonumber(ARGV[1])
local time = tonumber(ARGV[2])
local current = redis.call('get', key)
if current and tonumber(current) > count then
    return tonumber(current)
end
current = redis.call('incr', key)
if tonumber(current) == 1 then
    redis.call('expire', key, time)
end
return tonumber(current)

说明:key、count、time为三个传入参数,分别代表Redis的key、次数和过期时间。通过get获取key对应的值,获取的值为时间内访问接口的次数,如果为第一次访问则返回的为null,此时需要对当前key进行自增1操作,如果返回为数字,则需要判断返回的数字是否已经超过了cout值,如果超过说明已经超过限流了,直接返回。

建议

  • 1.编写lua脚本不要进行复杂耗时的计算逻辑,否则执行lua时间过长,会导致Redis主线程阻塞。
  • 2.lua脚本尽量简单,不要把所有的操作都放入到lua脚本中执行,这样会导致Redis执行脚本的时间增加,同时也会降低Redis的并发性能。

事务

关于事务保证原子性,采用的watch命令其原理和乐观锁的实现原理类似,详情可以参考juejin.cn/post/712582… 文章,本文就不在具体阐述。

加锁

关于Redis的分布式锁的实现,后续的章节进行详情说明。高并发环境下加锁虽然能够保证正确性,但是也会带来其他的问题:

  • 加锁操作过多会降低系统的并发访问性能
  • Redis客户端要加锁,需要使用分布式锁,而分布式锁实现复杂,增加复杂度。

总结

本文讲解了针对并发访问Redis如何保证原子性操作,针对不同的业务场景,选择合适的方案,更多相关Redis 并发访问内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7126430659173679134

延伸 · 阅读

精彩推荐
  • Redis利用yum安装Redis的方法详解

    利用yum安装Redis的方法详解

    Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工...

    daisy4712019-10-31
  • Redis为什么断电后Redis数据不会丢失

    为什么断电后Redis数据不会丢失

    Redis 作为一款内存数据库,被广泛使用于缓存,分布式锁等场景,那么假如断电或者因其他因素导致 Reids 服务宕机,在重启之后数据会丢失吗?本文就来介...

    双子孤狼5602021-09-16
  • Redis12 个问题搞懂 Redis

    12 个问题搞懂 Redis

    随着硬件性能的提升,Redis 的性能瓶颈有时会出现在网络 IO 的处理上,也就是说,单个主线程处理网络请求的速度跟不上底层网络硬件的速度,而读写的操...

    不止dotNET7942021-09-14
  • RedisWindows下Redis的安装使用图解

    Windows下Redis的安装使用图解

    Redis是一个key-value存储系统。Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。这篇文章小编...

    lijiao3712019-10-26
  • Redis关于Redis网络模型的源码详析

    关于Redis网络模型的源码详析

    这篇文章主要给大家介绍了关于Redis网络模型的源码,文中通过示例代码介绍的非常详细,对大家的学习或者使用Redis具有一定的参考学习价值,需要的朋友...

    数小钱钱的种花兔4762020-07-27
  • RedisRedis缓存穿透/击穿工具类的封装

    Redis缓存穿透/击穿工具类的封装

    在实际生产环境中,缓存的使用规范也是一直备受重视的,如果使用的不好,很容易就遇到缓存击穿、雪崩等严重异常情景。本文为大家准备了Redis缓存穿...

    知识的搬运工旺仔11602022-07-27
  • Redis深入理解redis分布式锁和消息队列

    深入理解redis分布式锁和消息队列

    本篇文章主要介绍了深入理解redis分布式锁和消息队列,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    叶下梧桐4492019-11-06
  • RedisCentOS系统中Redis数据库的安装配置指南

    CentOS系统中Redis数据库的安装配置指南

    Redis是一个基于主存存储的数据库,性能很强,这里我们就来看一下CentOS系统中Redis数据库的安装配置指南,包括将Redis作为系统服务运行的技巧等,需要的朋友可...

    zhoutk5232019-10-29