Redis 连接&&慢查询&&监视器&&持久化&&缓存过期和淘汰策略&&缓存穿透

Redis 连接

  1. Redis 连接命令主要是用于连接 redis 服务。

  2. 通过密码验证连接到 redis 服务,并检测服务是否在运行:

    redis 127.0.0.1:6379> AUTH "password"
    OK
    redis 127.0.0.1:6379> PING
    PONG
    
  3. Redis Auth 命令用于检测给定的密码和配置文件中的密码是否相符。密码匹配时返回 OK ,否则返回一个错误。

    redis 127.0.0.1:6379> AUTH PASSWORD
    (error) ERR Client sent AUTH, but no password is set
    redis 127.0.0.1:6379> CONFIG SET requirepass "mypass"
    OK
    redis 127.0.0.1:6379> AUTH mypass
    Ok
    
  4. Redis Echo 命令用于打印给定的字符串。返回字符串本身。

    redis 127.0.0.1:6379> ECHO "Hello World"
    "Hello World"
    
  5. Redis Ping 命令使用客户端向 Redis 服务器发送一个 PING ,如果服务器运作正常的话,会返回一个 PONG 。通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值,如果连接正常就返回一个 PONG ,否则返回一个连接错误。

    # 客户端和服务器连接正常
    
    redis 127.0.0.1:6379> PING
    PONG
    
    # 客户端和服务器连接不正常(网络不正常或服务器未能正常运行)
    
    redis 127.0.0.1:6379> PING
    Could not connect to Redis at 127.0.0.1:6379: Connection refused
    
  6. Redis Quit 命令用于关闭与当前客户端与redis服务的连接。一旦所有等待中的回复(如果有的话)顺利写入到客户端,连接就会被关闭。总是返回 OK 。

    redis 127.0.0.1:6379> QUIT
    OK
    
  7. Redis Select 命令用于切换到指定的数据库,数据库索引号 index 用数字值指定,以 0 作为起始索引值。总是返回 OK

    redis 127.0.0.1:6379> SET db_number 0         # 默认使用 0 号数据库
    OK
    
    redis 127.0.0.1:6379> SELECT 1                # 使用 1 号数据库
    OK
    
    redis 127.0.0.1:6379[1]> GET db_number        # 已经切换到 1 号数据库,注意 Redis 现在的命令提示符多了个 [1]
    (nil)
    
    redis 127.0.0.1:6379[1]> SET db_number 1
    OK
    
    redis 127.0.0.1:6379[1]> GET db_number
    "1"
    
    redis 127.0.0.1:6379[1]> SELECT 3             # 再切换到 3 号数据库
    OK
    
    redis 127.0.0.1:6379[3]>                      # 提示符从 [1] 改变成了 [3]
    

Redis 慢查询

  1. Redis也有慢查询日志,可用于监视和优化查询

  2. 慢查询设置:在redis.conf中可以配置和慢查询日志相关的选项:

    #执行时间超过多少微秒的命令请求会被记录到日志上 0 :全记录 <0 不记录
    slowlog-log-slower-than 10000
    #slowlog-max-len 存储慢查询日志条数
    slowlog-max-len 128
    
  3. Redis使用列表存储慢查询日志,采用队列方式(FIFO)

    config set的方式可以临时设置,redis重启后就无效
    config set slowlog-log-slower-than 微秒
    config set slowlog-max-len 条数
    
  4. 查看日志:slowlog get [n]

    127.0.0.1:6379> config set slowlog-log-slower-than 0
    OK
    127.0.0.1:6379> config set slowlog-max-len 2
    OK
    127.0.0.1:6379> set name:001 zhaoyun
    OK
    127.0.0.1:6379> set name:002 zhangfei
    OK
    127.0.0.1:6379> get name:002
    "zhangfei"
    127.0.0.1:6379> slowlog get
    1) 1) (integer) 7 #日志的唯一标识符(uid)
    2) (integer) 1589774302 #命令执行时的UNIX时间戳
    3) (integer) 65 #命令执行的时长(微秒)
    4) 1) "get" #执行命令及参数
    2) "name:002"
    5) "127.0.0.1:37277"
    6) ""
    2) 1) (integer) 6
    2) (integer) 1589774281
    3) (integer) 7
    4) 1) "set"
    2) "name:002"
    3) "zhangfei"
    5) "127.0.0.1:37277"
    6) ""
    # setget都记录,第一条被移除了。
    
  5. 慢查询记录的保存:在redisServer中保存和慢查询日志相关的信息

    struct redisServer {
    	// ...
    	// 下一条慢查询日志的 ID
    	long long slowlog_entry_id;
    	// 保存了所有慢查询日志的链表 FIFO
    	list *slowlog;
    	// 服务器配置 slowlog-log-slower-than 选项的值
    	long long slowlog_log_slower_than;
    	// 服务器配置 slowlog-max-len 选项的值
    	unsigned long slowlog_max_len;
    	// ...
    };
    

Redis 监视器

  1. Redis客户端通过执行MONITOR命令可以将自己变为一个监视器,实时地接受并打印出服务器当前处理的命令请求的相关信息。
  2. 此时,当其他客户端向服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将这条命令请求的信息发送给所有监视器。

在这里插入图片描述
Redis客户端1

127.0.0.1:6379> monitor
OK
1589706136.030138 [0 127.0.0.1:42907] "COMMAND"
1589706145.763523 [0 127.0.0.1:42907] "set" "name:10" "zhaoyun"
1589706163.756312 [0 127.0.0.1:42907] "get" "name:10"

Redis客户端2

127.0.0.1:6379>
127.0.0.1:6379> set name:10 zhaoyun
OK
127.0.0.1:6379> get name:10
"zhaoyun"

Redis持久化-RDB

  1. Redis是内存数据库,宕机后数据会消失。Redis重启后快速恢复数据,要提供持久化机制,Redis持久化是为了快速的恢复数据而不是为了存储数据

  2. Redis有两种持久化方式:RDB和AOF,注意:Redis持久化不保证数据的完整性。

  3. 当Redis用作DB时,DB数据要完整,所以一定要有一个完整的数据源(文件、mysql),在系统启动时,从这个完整的数据源中将数据load到Redis中,数据量较小,不易改变,比如:字典库(xml、Table)

  4. 通过info命令可以查看关于持久化的信息

    # Persistence
    loading:0
    rdb_changes_since_last_save:1
    rdb_bgsave_in_progress:0
    rdb_last_save_time:1589363051
    rdb_last_bgsave_status:ok
    rdb_last_bgsave_time_sec:-1
    rdb_current_bgsave_time_sec:-1
    rdb_last_cow_size:0
    aof_enabled:1
    aof_rewrite_in_progress:0
    aof_rewrite_scheduled:0
    aof_last_rewrite_time_sec:-1
    aof_current_rewrite_time_sec:-1
    aof_last_bgrewrite_status:ok
    aof_last_write_status:ok
    aof_last_cow_size:0
    aof_current_size:58
    aof_base_size:0
    aof_pending_rewrite:0
    aof_buffer_length:0
    aof_rewrite_buffer_length:0
    aof_pending_bio_fsync:0
    aof_delayed_fsync:0
    
  5. RDB(Redis DataBase),是redis默认的存储方式,RDB方式是通过快照( snapshotting )完成的。这一刻的数据不关注过程

  6. 触发快照的方式:

    1. 符合自定义配置的快照规则
    2. 执行save或者bgsave命令
    3. 执行flushall命令
    4. 执行主从复制操作 (第一次)
  7. 配置参数定期执行:在redis.conf中配置:save 多少秒内 数据变了多少

    save "" # 不使用RDB存储 不能主从
    save 900 1 # 表示15分钟(900秒钟)内至少1个键被更改则进行快照。
    save 300 10 # 表示5分钟(300秒)内至少10个键被更改则进行快照。
    save 60 10000 # 表示1分钟内至少10000个键被更改则进行快照。
    
  8. 命令显式触发:在客户端输入bgsave命令。

    127.0.0.1:6379> bgsave
    Background saving started
    

RDB执行流程(原理)

在这里插入图片描述

  1. Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof(aof文件重写命令)的子进程,如果在执行则bgsave命令直接返回。
  2. 父进程执行fork(调用OS函数复制主进程)操作创建子进程,这个复制过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令。
  3. 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令。
  4. 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换。(RDB始终完整)
  5. 子进程发送信号给父进程表示完成,父进程更新统计信息。
  6. 父进程fork子进程后,继续工作。

RDB的优点

  1. RDB是二进制压缩文件,占用空间小,便于传输(传给slaver)
  2. 主进程fork子进程,可以最大化Redis性能,主进程不能太大,Redis的数据量不能太大,复制过程中主进程阻塞

RDB的缺点

  1. 不保证数据完整性,会丢失最后一次快照以后更改的所有数据

Redis持久化-AOF

  1. AOF(append only file)是Redis的另一种持久化方式。Redis默认情况下是不开启的。开启AOF持久化后,Redis 将所有对数据库进行过写入的命令(及其参数)(RESP)记录到 AOF 文件, 以此达到记录数据库状态的目的,这样当Redis重启后只要按顺序回放这些命令就会恢复到原始状态了。

  2. AOF会记录过程,RDB只管结果,

  3. AOF持久化实现配置 redis.conf

    # 可以通过修改redis.conf配置文件中的appendonly参数开启
    appendonly yes
    # AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
    dir ./
    # 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
    appendfilename appendonly.aof
    

AOF原理

  1. AOF文件中存储的是redis的命令,同步命令到 AOF 文件的整个过程可以分为三个阶段:
    1. 命令传播:Redis 将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中。
    2. 缓存追加:AOF 程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中。
    3. 文件写入和保存:AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存条件被满足的话,fsync 函数或者 fdatasync 函数会被调用,将写入的内容真正地保存到磁盘中。

命令传播

  1. 当一个 Redis 客户端需要执行命令时, 它通过网络连接, 将协议文本发送给 Redis 服务器。
  2. 服务器在接到客户端的请求之后, 它会根据协议文本的内容, 选择适当的命令函数, 并将各个参数从字符串文本转换为 Redis 字符串对象( StringObject )。
  3. 每当命令函数成功执行之后, 命令参数都会被传播到AOF 程序。

缓存追加

  1. 当命令被传播到 AOF 程序之后, 程序会根据命令以及命令的参数, 将命令从字符串对象转换回原来的协议文本。协议文本生成之后, 它会被追加到 redis.h/redisServer 结构的 aof_buf 末尾。
  2. redisServer 结构维持着 Redis 服务器的状态, aof_buf 域则保存着所有等待写入到 AOF 文件的协议文本(RESP)。

文件写入和保存

  1. 每当服务器常规任务函数被执行、 或者事件处理器被执行时, aof.c/flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作:
    1. WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件。
    2. SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。

AOF 保存模式

  1. Redis 目前支持三种 AOF 保存模式,它们分别是:
    1. AOF_FSYNC_NO :不保存。
    2. AOF_FSYNC_EVERYSEC :每一秒钟保存一次。(默认)
    3. AOF_FSYNC_ALWAYS :每执行一个命令保存一次。(不推荐)

AOF_FSYNC_NO :不保存。

  1. 在这种模式下, 每次调用 flushAppendOnlyFile 函数, WRITE 都会被执行, 但 SAVE 会被略过。
  2. 在这种模式下, SAVE 只会在以下任意一种情况中被执行:
    1. Redis 被关闭
    2. AOF 功能被关闭
    3. 系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)
    4. 这三种情况下的 SAVE 操作都会引起 Redis 主进程阻塞。

AOF_FSYNC_EVERYSEC :每一秒钟保存一次。(默认)

  1. 在这种模式中, SAVE 原则上每隔一秒钟就会执行一次, 因为 SAVE 操作是由后台子线程(fork)调用的, 所以它不会引起服务器主进程阻塞。

AOF_FSYNC_ALWAYS :每执行一个命令保存一次。(不推荐)

  1. 在这种模式下,每次执行完一个命令之后, WRITE 和 SAVE 都会被执行。
  2. 另外,因为 SAVE 是由 Redis 主进程执行的,所以在 SAVE 执行期间,主进程会被阻塞,不能接受命令请求

AOF 保存模式对性能和安全性的影响,它们对服务器主进程的阻塞情况如下

在这里插入图片描述
AOF重写过程分析(整个重写操作是绝对安全的):

在这里插入图片描述

  1. Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  2. 当子进程在执行 AOF 重写时, 主进程需要执行以下三个工作:
    1. 处理命令请求。
    2. 将写命令追加到现有的 AOF 文件中。
    3. 将写命令追加到 AOF 重写缓存中
  3. 这样一来可以保证:现有的 AOF 功能会继续执行,即使在 AOF 重写期间发生停机,也不会有任何数据丢失。所有对数据库进行修改的命令都会被记录到 AOF 重写缓存中。当子进程完成 AOF 重写之后, 它会向父进程发送一个完成信号, 父进程在接到完成信号之后, 会调用一个信号处理函数, 并完成以下工作:
    1. 将 AOF 重写缓存中的内容全部写入到新 AOF 文件中。
    2. 对新的 AOF 文件进行改名,覆盖原有的 AOF 文件。
  4. Redis数据库里的+AOF重写过程中的命令------->新的AOF文件---->覆盖老的
    1. 当步骤 1 执行完毕之后, 现有 AOF 文件、新 AOF 文件和数据库三者的状态就完全一致了
    2. 当步骤 2 执行完毕之后, 程序就完成了新旧两个 AOF 文件的交替
  5. 这个信号处理函数执行完毕之后, 主进程就可以继续像往常一样接受命令请求了。 在整个 AOF 后台重写过程中, 只有最后的写入缓存和改名操作会造成主进程阻塞, 在其他时候, AOF 后台重写都不会对主进程造成阻塞, 这将 AOF 重写对性能造成的影响降到了最低。
  6. 以上就是 AOF 后台重写, 也即是 BGREWRITEAOF 命令(AOF重写)的工作原理。

在这里插入图片描述
AOF触发方式

  1. 配置触发:在redis.conf中配置

    # 表示当前aof文件大小超过上一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,
    以启动时aof文件大小为准
    auto-aof-rewrite-percentage 100
    # 限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
    auto-aof-rewrite-min-size 64mb
    
  2. 执行bgrewriteaof命令

    127.0.0.1:6379> bgrewriteaof
    Background append only file rewriting started
    

混合持久化

  1. RDB和AOF各有优缺点,Redis 4.0 开始支持 rdb 和 aof 的混合持久化。如果把混合持久化打开,aofrewrite 的时候就直接把 rdb 的内容写到 aof 文件开头。
  2. RDB的头+AOF的身体---->appendonly.aof,开启混合持久化:aof-use-rdb-preamble yes
  3. 可以看到该AOF文件是rdb文件的头和aof格式的内容,在加载时,首先会识别AOF文件是否以REDIS字符串开头,如果是就按RDB格式加载,加载完RDB后继续按AOF格式加载剩余部分。

AOF文件的载入与数据还原

  1. 因为AOF文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态
  2. Redis读取AOF文件并还原数据库状态的详细步骤如下:
    1. 创建一个不带网络连接的伪客户端(fake client):因为Redis的命令只能在客户端上下文中执行,而载入AOF文件时所使用的命令直接来源于AOF文件而不是网络连接,所以服务器使用了一个没有网络连接的伪客户端来执行AOF文件保存的写命令,伪客户端执行命令 的效果和带网络连接的客户端执行命令的效果完全一样
    2. 从AOF文件中分析并读取出一条写命令
    3. 使用伪客户端执行被读出的写命令
    4. 一直执行步骤2和步骤3,直到AOF文件中的所有写命令都被处理完毕为止当完成以上步骤之后,AOF文件所保存的数据库状态就会被完整地还原出来,整个过程如下图所示:
      在这里插入图片描述

RDB与AOF对比

  1. RDB存某个时刻的数据快照,采用二进制压缩存储,AOF存操作命令,采用文本存储(混合)
  2. RDB性能高、AOF性能较低
  3. RDB在配置触发状态会丢失最后一次快照以后更改的所有数据,AOF设置为每秒保存一次,则最多丢2秒的数据
  4. Redis以主服务器模式运行,RDB不会保存过期键值对数据,Redis以从服务器模式运行,RDB会保存过期键值对,当主服务器向从服务器同步时,再清空过期键值对。
  5. AOF写入文件时,对过期的key会追加一条del命令,当执行AOF重写时,会忽略过期key和del命令。

缓存过期和淘汰策略

  1. Redis性能高:长期使用,key会不断增加,Redis作为缓存使用,物理内存也会满,内存与硬盘交换(swap) 虚拟内存 ,频繁IO 性能急剧下降

maxmemory 不设置的场景

  1. Redis的key是固定的,不会增加
  2. Redis作为DB使用,保证数据的完整性,不能淘汰 , 可以做集群,横向扩展
  3. 缓存淘汰策略:禁止驱逐 (默认)

maxmemory 设置的场景

  1. Redis是作为缓存使用,不断增加Key
  2. maxmemory : 默认为0 不限制
  3. 问题:达到物理内存后性能急剧下架,甚至崩溃
  4. 内存与硬盘交换(swap) 虚拟内存 ,频繁IO 性能急剧下降
  5. 设置maxmemory后,当趋近maxmemory时,通过缓存淘汰策略,从内存中删除对象
  6. 设置maxmemory maxmemory-policy 要配置

expire数据结构

  1. 在Redis中可以使用expire命令设置一个键的存活时间(ttl: time to live),过了这段时间,该键就会自动被删除

  2. expire命令的使用方法如下:expire key ttl(单位秒)

    127.0.0.1:6379> expire name 2 #2秒失效
    (integer) 1
    127.0.0.1:6379> get name
    (nil)
    127.0.0.1:6379> set name zhangfei
    OK
    127.0.0.1:6379> ttl name #永久有效
    (integer) -1
    127.0.0.1:6379> expire name 30 #30秒失效
    (integer) 1
    127.0.0.1:6379> ttl name #还有24秒失效
    (integer) 24
    127.0.0.1:6379> ttl name #失效
    (integer) -2
    

删除策略

  1. Redis的数据删除有定时删除、惰性删除和主动删除三种方式
  2. Redis目前采用惰性删除+主动删除的方式。
    1. 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。需要创建定时器,而且消耗CPU,一般不推荐使用
    2. 惰性删除:在key被访问时如果发现它已经失效,那么就删除它。调用expireIfNeeded函数,该函数的意义是:读取数据之前先检查一下它有没有失效,如果失效了就删除它
    3. 主动删除:在redis.conf文件中可以配置主动删除策略,默认是no-enviction(不删除)
      maxmemory-policy allkeys-lru
      

缓存穿透

  1. 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。
  2. 缓存穿透是指在高并发下查询key不存在的数据(不存在的key),会穿过缓存查询数据库。导致数据库压力过大而宕机

解决方案:

  1. 对查询结果为空的情况也进行缓存,缓存时间(ttl)设置短一点,或者该key对应的数据insert了之后清理缓存。问题:缓存太多空值占用了更多的空间
  2. 使用布隆过滤器。在缓存之前在加一层布隆过滤器,在查询的时候先去布隆过滤器查询 key 是否存在,如果不存在就直接返回,存在再查缓存和DB。
    在这里插入图片描述
  3. 布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机hash映射函数。
  4. 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法。

在这里插入图片描述

  1. 布隆过滤器的原理是,当一个元素被加入集合时,通过K个Hash函数将这个元素映射成一个数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。

缓存雪崩

  1. 当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力
  2. 突然间大量的key失效了或redis重启,大量访问数据库,数据库崩溃
  3. 解决方案:
    1. key的失效期分散开 不同的key设置不同的有效期
    2. 设置二级缓存(数据不一定一致)
    3. 高可用(脏读)

缓存击穿

  1. 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
  2. 缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
  3. 解决方案:
    1. 用分布式锁控制访问的线程,使用redis的setnx互斥锁先进行判断,这样其他线程就处于等待状态,保证不会有大并发操作去操作数据库。
    2. 不设超时时间,volatile-lru 但会造成写一致问题,当数据库数据发生更新时,缓存中的数据不会及时更新,这样会造成数据库中的数据与缓存中的数据的不一致,应用会从缓存中读取到脏数据。可采用延时双删策略处理

数据不一致

  1. 缓存和DB的数据不一致的根源 : 数据源不一样,保证数据的最终一致性(延时双删)
  2. 先更新数据库同时删除缓存项(key),等读的时候再填充缓存
  3. 2秒后再删除一次缓存项(key)
  4. 设置缓存过期时间 Expired Time 比如 10秒 或1小时
  5. 将缓存删除失败记录到日志中,利用脚本提取失败记录再次删除(缓存失效期过长 7*24)

数据并发竞争

  1. 并发指的是多个redis的client同时set 同一个key引起的并发问题。
  2. 多客户端(Jedis)同时并发写一个key,一个key的值是1,本来按顺序修改为2,3,4,最后是4,但是顺序变成了4,3,2,最后变成了2。
  3. 第一种方案:分布式锁+时间戳
    1. 整体技术方案:这种情况,主要是准备一个分布式锁,大家去抢锁,抢到锁就做set操作。
    2. 加锁的目的实际上就是把并行读写改成串行读写的方式,从而来避免资源竞争。
      在这里插入图片描述
  4. Redis分布式锁的实现
    1. 主要用到的redis函数是setnx(),用SETNX实现分布式锁
    2. 时间戳:由于上面举的例子,要求key的操作需要顺序执行,所以需要保存一个时间戳判断set顺序。
      系统A key 1 {ValueA 7:00}
      系统B key 1 { ValueB 7:05}
      
    3. 假设系统B先抢到锁,将key1设置为{ValueB 7:05}。接下来系统A抢到锁,发现自己的key1的时间戳早于缓存中的时间戳(7:00<7:05),那就不做set操作了。
  5. 第二种方案:利用消息队列
    1. 在并发量过大的情况下,可以通过消息中间件进行处理,把并行读写进行串行化。
    2. 把Redis的set操作放在队列中使其串行化,必须的一个一个执行。

分布式锁特性

  1. 互斥性:任意时刻,只能有一个客户端获取锁,不能同时有两个客户端获取到锁。
  2. 同一性:锁只能被持有该锁的客户端删除,不能由其它客户端删除。
  3. 可重入性:持有某个锁的客户端可继续对该锁加锁,实现锁的续租
  4. 容错性:锁失效后(超过生命周期)自动释放锁(key失效),其他客户端可以继续获得该锁,防止死锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值