29 | 无锁的原子操作:Redis如何应对并发访问?

318 阅读2分钟

基本概念

  • redis某些操作是需要原子性,临界区的读写操作保证串行\

  • redis保证并发访问的正确性\

    • 加锁 获得锁可以执行相关操作,否则允许执行操作

      • 缺点

        • 加锁过多会降低系统的并发访问性能
        • 需要使用分布式锁,成本高
    • 原子操作

      • 执行过程中保证原子性操作(类似操作系统的原语)

并发访问中需要对什么进行控制?

  • 并发访问原理:是指对多个客户端访问操作同一份数据的过程进行控制,以保证任何一个客户端发送的操作在 Redis 实例上执行时具有互斥性

    • 例如执行A,阻塞B
  • 客户端修改数据时的步骤 Read-Modify-Write RMW

    • 客户端读取数据到本地,在本地进行修改
    • 客户端修改完数据后,写会redis
  • 临界区:访问同一份数据的 RMW 操作代码

  • 加锁(利用分布式锁):导致系统并发性能降低\

//临界区操作
current = GET(id) 
current-- 
SET(id, current) 
//加锁
LOCK() 
current = GET(id) 
current-- 
SET(id, current) 
UNLOCK() 

1

\

Redis 的两种原子操作方法

  • redis想要使用原子操作的两种办法

    • 把多个操作在 Redis 中实现成一个操作,也就是单命令操作\

      • 针对string INCR/DECR 命令进行数据的增值 / 减值操作(很难符合业务需求)
    • 把多个操作写到一个 Lua 脚本中,以原子性方式执行单个 Lua 脚本(避免别的指令插队)\

      • 使用 Redis 的 EVAL 命令来执行脚本\
  • \

总结

  • 在并发访问时,并发的 RMW 操作会导致数据错误,所以需要进行并发控制\

  • 原子操作的办法

    • 使用incr/decr

    • 使用lua脚本

      • 在编写 Lua 脚本时,你要避免把不需要做并发控制的操作写入脚本中\
    • 使用分布式锁