
# 扫描并删除Redis实例的过期Key
在开源Redis的键空间中，有两种删除Key的方式。
- 使用DEL等命令直接对Key进行删除。
- 使用类似于EXPIRE等命令对Key设置过期时间，当达到过期时间时，Redis键空间中的Key将不可访问。对于设置了过期时间的Key，当达到过期时间时，Redis不会立即对Key进行删除。由于Redis当前主线程仍然为单线程，故Redis设计了几种机制对已经过期的Key进行内存释放：
  - 惰性删除：Redis的删除策略由主循环中的判断逻辑进行控制，所有Key读写命令执行之前都会调用函数对其进行检查，如果过期，则删除该键，然后返回Key不存在的结果；未过期则不做操作，继续执行原有的命令。
  
  
  
  - 定期删除：由Redis的定时任务函数实现，该函数以一定的频率运行，每次运行时，都从键空间中随机取出一定数量的Key进行检查，并删除其中的过期Key。开源Redis不是每次定时任务都会检查所有的Key，而是随机检查一定数量的Key（默认一次从设置过期时间的Key中随机检查20个，每秒10次，通过active-expire-num参数可调节随机检查数），该机制旨在防止阻塞Redis主进程太久而造成业务阻塞，所以会造成已过期的Key释放内存速度较慢。
   
基于开源Redis以上机制，分布式缓存服务提供了一种通用的"过期Key扫描"的方式，来定时释放所有已经过期Key占用的内存，通过自行配置定时任务，在任务执行期间，会对所有缓存实例的主节点进行扫描操作，扫描操作会遍历整个实例的键空间，触发Redis引擎中对Key过期的判断，从而释放已过期的Key。
#### 约束与限制
- 只有Redis 4.0及以上版本实例支持过期key扫描，企业版实例不支持。
- DCS不支持查询已释放的过期Key。
- 不支持查看删除的过期key。
- **过期Key扫描在主节点上执行，会对实例性能有一定的影响。**
- **执行过期Key扫描会占用CPU，建议在业务低峰时段执行过期Key扫描，降低CPU被用满的可能。**
 
#### 扫描并删除Redis实例的过期Key
1. 登录[分布式缓存服务管理控制台](https://console.huaweicloud.com/dcs)。
2. 在管理控制台左上角单击![](https://support.huaweicloud.com/usermanual-dcs/zh-cn_image_0000001549115173.png)，选择实例所在的区域。
3. 单击左侧菜单栏的"缓存管理"，进入实例信息页面。
4. 单击需要缓存分析的Redis实例名称，进入该实例的概览页面。
5. 选择"分析与诊断 \> 缓存分析"，进入缓存分析页面。
6. 在"过期key扫描"页签下，可以执行过期key扫描释放掉过期的key。 
   过期key扫描会对键空间进行Redis的scan扫描，释放内存中已过期但是由于惰性删除机制而没有释放的内存空间。
   - 单击"立即分析"，可立即按照DCS内部配置的扫描参数（迭代扫描key数量：100个，扫描超时时间：360分）对实例执行手动过期key扫描。
   
   - 开启"自动扫描"，通过设置定时任务，到设定时间将会执行自动扫描。自动扫描的配置说明请参考[表1]和[自动扫描性能说明和配置建议]。
   
   
    表1自动扫描配置参数 
   | 参数名称      | 参数说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   |:---|:---|
   | 首次扫描时间    | 设定的第一次扫描时间，须设定在当前时间之后。 取值格式：YYYY/MM/DD hh:mm:ss                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
   | 扫描间隔      | 从首次扫描时间开始，每隔一个时间间隔，便启动一次扫描。 - 如果到达启动时刻，上一次扫描还未结束，则本次轮空。  - 启动扫描的时间有五分钟冗余量，即超过本次启动时刻，不足五分钟，仍然会启动，不至于轮空。  - 连续扫描可能使CPU占用率较高，建议根据实例中key总量以及key增长情况来配置，可参考[自动扫描性能说明和配置建议]。   取值范围：0\~43,200 默认值：1440 单位：分 |
   | 扫描超时      | 此参数的目的在于避免因不可知原因造成的扫描超时，导致后面的定时任务无法执行。设定此参数，超过超时时间后，返回失败，以便能继续进行下一轮扫描。 - 超时时间不少于扫描间隔时间的2倍。  - 可根据每次过期key扫描的时间，以及使用场景所能承受的最大超时时间，设定一个经验值。   取值范围：1\~86,400 默认值：2880 单位：分                                                                                                                                                  |
   | 迭代扫描key数量 | SCAN命令用于迭代当前数据库中的key集合。 COUNT选项的作用就是让用户告知迭代命令， 在每次迭代中应该从数据集里返回多少元素。具体参见[scan命令介绍](https://redis.io/commands/scan/)。迭代式扫描可降低一次扫描过多key而造成扫描时间过长，影响redis性能的问题。 举例：redis中有1000万个key，迭代扫描key数量设为1000，则迭代10000次可完成全库扫描。 取值范围：10\~1,000 默认值：50 单位：个                                                                                                                                                                                                                           |
      
   
   
7. 当过期key扫描任务提交后，每次过期key扫描都会生成一个任务记录，通过任务记录可以查看扫描的任务ID、状态、扫描方式、扫描开始和结束的时间。 
   图1过期key扫描任务列表   
   ![](https://support.huaweicloud.com/usermanual-dcs/zh-cn_image_0000002446918897.png "点击放大")
   扫描失败的两种情况：
   - 出现异常导致扫描失败。
   
   - 扫描超时导致失败，可能是key数量太多，未能在超时时间内扫描完，也会失败，但其实已经删除了部分key了。
    
   
   
 
 #### 自动扫描性能说明和配置建议
**性能说明：**
- 数据面底层SCAN扫描间隔5ms，相当于1秒钟扫描200次。迭代扫描key数量设为10/50/100/1000时，每秒钟扫描2000/10000/20000/200000个key。
- 每秒钟扫描key数量越大，CPU占用率也相应增加。
**测试参考：**
使用主备实例测试，在有1000万不过期和500万过期的key，过期时间为1-10秒的场景下，完成一次全库扫描，测试数据如下：
![](https://support.huaweicloud.com/usermanual-dcs/public_sys-resources/note_3.0-zh-cn.png)
以下测试结果仅供参考，不同局点环境和网络波动等客观条件可能产生差异。
- 自然删除，每秒删除1万条过期key，删除500万过期key，耗时约为8分钟，CPU占用率约为5%。
- "迭代扫描key数量"设为10，耗时约为 1500万/0.2万/60秒 = 125分，CPU占用率约为8%。
- "迭代扫描key数量"设为50，耗时约为 1500万/1万/60秒 = 25分， 删除key时CPU占用率约10%。
- "迭代扫描key数量"设为100，耗时约为 1500万/2万/60秒 = 12.5分， 删除key时CPU占用率约20%。
- "迭代扫描key数量"设为1000，耗时约为 1500万/20万/60秒 = 1.25分，删除key时CPU占用率约为25%。
 
**配置** **建议**：
- 您可根据实例中key总量以及key增长情况，来配置迭代扫描key数量和扫描间隔。
- 如测试参考中，1500万key总量，"迭代扫描key数量"设为10，扫完一遍需约125分，那么扫描间隔建议设置4小时以上。
- 如果希望提高扫描速度，那么可以将"迭代扫描key数量"设为100，扫完一遍需约12.5分，那么扫描间隔建议设置30分钟以上。
- 迭代扫描key数量越大，扫描速度越快，CPU占用率也相应增加，用户要平衡耗时和CPU占用率。
- 如果过期key数量增长速度不快，可以一天执行一次过期key扫描。
- **建议将扫描开始时间设置为业务低峰期。将扫描间隔设为1天，超时时间设为2天。**
#### 相关文档
- 如果需要通过API执行过期Key扫描，相关文档请参见[创建过期key扫描任务](https://support.huaweicloud.com/api-dcs/CreateAutoExpireScanTask.html)、[立刻扫描过期Key](https://support.huaweicloud.com/api-dcs/ScanExpireKey.html)、[查询过期Key扫描记录](https://support.huaweicloud.com/api-dcs/ShowExpireKeyScanInfo.html)。
- [Key的保存时间是多久？如何设置Key的过期时间？](https://support.huaweicloud.com/dcs_faq/dcs-faq-210812001.html)
 
