Redis中Key过期时间的设置与应用方式
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、设置Key过期时间的命令</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">(一)EXPIRE命令</a></li><li><a href="#_lab2_0_1">(二)PEXPIRE命令</a></li><li><a href="#_lab2_0_2">(三)EXPIREAT命令</a></li><li><a href="#_lab2_0_3">(四)PEXPIREAT命令</a></li></ul><li><a href="#_label1">二、在设置值时同时设置过期时间</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_4">(一)SET命令结合EX参数</a></li><li><a href="#_lab2_1_5">(二)SET命令结合PX参数</a></li><li><a href="#_lab2_1_6">(三)SETEX命令</a></li></ul><li><a href="#_label2">三、获取Key的剩余过期时间</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_7">(一)TTL命令</a></li><li><a href="#_lab2_2_8">(二)PTTL命令</a></li></ul><li><a href="#_label3">四、移除Key的过期时间</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">五、应用场景及案例</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_9">(一)缓存场景</a></li><li><a href="#_lab2_4_10">(二)会话管理场景</a></li><li><a href="#_lab2_4_11">(三)分布式锁场景</a></li></ul><li><a href="#_label5">总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、设置Key过期时间的命令</h2><p class="maodian"><a name="_lab2_0_0"></a></p><h3>(一)EXPIRE命令</h3>
<p>EXPIRE用于设置一个Key在指定秒数后过期。其语法为:<code>EXPIRE key seconds</code> 。</p>
<p>比如,我们要将名为<code>user:1:session</code>的Key设置为3600秒(1小时)后过期,在Redis客户端中执行:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> EXPIRE user:1:session 3600
(integer) 1
</pre></div>
<p>返回值<code>1</code>表示设置成功,如果Key不存在或设置失败则返回<code>0</code> 。此命令适用于对时间精度要求不高,以秒为单位设置过期时间的场景,像一般的缓存数据失效时间设置。</p>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>(二)PEXPIRE命令</h3>
<p>PEXPIRE与EXPIRE类似,不过它是以毫秒为单位设置Key的过期时间,语法为:<code>PEXPIRE key milliseconds</code> 。</p>
<p>若要将<code>message:1</code>这个Key设置为5000毫秒(5秒)后过期,操作如下:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> PEXPIRE message:1 5000
(integer) 1
</pre></div>
<p>该命令适用于对时间精度要求较高的场景,例如某些对消息时效性要求严格的消息队列场景。</p>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>(三)EXPIREAT命令</h3>
<p>EXPIREAT通过指定一个Unix时间戳(以秒为单位),让Key在该时间点过期。语法为:<code>EXPIREAT key timestamp</code> 。</p>
<p>假设我们获取到当前时间戳为<code>1693382400</code>(对应2023年9月1日00:00:00),要让<code>cache:data</code>这个Key在2023年9月2日00:00:00过期,即时间戳<code>1693468800</code>,则执行:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> EXPIREAT cache:data 1693468800
(integer) 1
</pre></div>
<p>这种方式适用于需要在特定时间点让Key失效的场景,如限时活动相关数据的过期控制。</p>
<p class="maodian"><a name="_lab2_0_3"></a></p><h3>(四)PEXPIREAT命令</h3>
<p>PEXPIREAT同样是基于时间戳设置过期时间,但时间戳是以毫秒为单位,语法为:<code>PEXPIREAT key milliseconds - timestamp</code> 。</p>
<p>比如要让<code>token:user1</code>在2023年9月1日00:00:01.500过期,对应的毫秒时间戳为<code>1693382401500</code>,操作如下:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> PEXPIREAT token:user1 1693382401500
(integer) 1
</pre></div>
<p>适用于对过期时间点精度要求极高的场景,如金融交易中某些临时凭证的过期时间设置。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、在设置值时同时设置过期时间</h2>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>(一)SET命令结合EX参数</h3>
<p>使用<code>SET key value EX seconds</code>可以在设置Key值的同时指定其在多少秒后过期。</p>
<p>例如,设置<code>product:1:price</code>的值为<code>99.9</code>,并让它在86400秒(1天)后过期:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> SET product:1:price 99.9 EX 86400
OK
</pre></div>
<p>这种方式在需要创建新的缓存数据并设置过期时间时非常便捷,代码更简洁。</p>
<p class="maodian"><a name="_lab2_1_5"></a></p><h3>(二)SET命令结合PX参数</h3>
<p><code>SET key value PX milliseconds</code>用于在设置Key值时指定毫秒级别的过期时间。</p>
<p>比如设置<code>tmp:data</code>的值为<code>some temp data</code>,并在3000毫秒(3秒)后过期:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> SET tmp:data "some temp data" PX 3000
OK
</pre></div>
<p>适用于对时间精度要求高且在设置值时就确定过期时间的场景。</p>
<p class="maodian"><a name="_lab2_1_6"></a></p><h3>(三)SETEX命令</h3>
<p><code>SETEX key seconds value</code>专门用于设置一个带有过期时间(秒为单位)的字符串值。</p>
<p>如设置<code>news:1:content</code>的值为一篇新闻内容,并让它在7200秒(2小时)后过期:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> SETEX news:1:content "This is a news" 7200
OK
</pre></div>
<p>在只针对字符串类型的Key设置值和过期时间时,SETEX命令更为直观。</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、获取Key的剩余过期时间</h2>
<p class="maodian"><a name="_lab2_2_7"></a></p><h3>(一)TTL命令</h3>
<p>TTL用于获取一个Key的剩余过期时间(以秒为单位)。语法为:<code>TTL key</code> 。</p>
<p>对于之前设置的<code>user:1:session</code>,可以这样获取其剩余过期时间:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> TTL user:1:session
(integer) 3590
</pre></div>
<p>返回值<code>3590</code>表示该Key还有3590秒过期。如果Key不存在或已过期,返回<code>-2</code>;如果Key没有设置过期时间(即永久有效),返回<code>-1</code> 。此命令常用于检查缓存数据何时失效,以便提前进行数据更新等操作。</p>
<p class="maodian"><a name="_lab2_2_8"></a></p><h3>(二)PTTL命令</h3>
<p>PTTL获取Key的剩余过期时间(以毫秒为单位),语法为:<code>PTTL key</code> 。</p>
<p>对于设置了毫秒级过期时间的<code>message:1</code>,获取剩余过期时间操作如下:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> PTTL message:1
(integer) 4990
</pre></div>
<p>返回值<code>4990</code>表示还有4990毫秒过期。同样,Key不存在或已过期返回<code>-2</code>,永久有效返回<code>-1</code> 。适用于需要精确了解剩余毫秒级过期时间的场景。</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、移除Key的过期时间</h2>
<p>使用PERSIST命令可以移除一个Key的过期时间,使其变为永久有效。语法为:<code>PERSIST key</code> 。</p>
<p>例如,之前设置了过期时间的<code>cache:data</code>,若要让它永久有效,执行:</p>
<div class="jb51code"><pre class="brush:sql;">127.0.0.1:6379> PERSIST cache:data
(integer) 1
</pre></div>
<p>返回值<code>1</code>表示操作成功,之后再使用<code>TTL cache:data</code>查询,会返回<code>-1</code>,表示该Key已变为永久有效。在某些情况下,原本设置了过期时间的Key,由于业务需求变更,需要长期保存时,就可使用PERSIST命令。</p>
<p class="maodian"><a name="_label4"></a></p><h2>五、应用场景及案例</h2>
<p class="maodian"><a name="_lab2_4_9"></a></p><h3>(一)缓存场景</h3>
<p>在Web应用中,常使用Redis作为缓存来提升数据读取速度。例如,电商网站中商品详情数据的缓存。</p>
<p>假设我们有一个商品详情页面,每次查询数据库获取商品详情数据开销较大。可以将商品详情数据缓存到Redis中,并设置合理的过期时间。</p>
<div class="jb51code"><pre class="brush:sql;">import redis
r = redis.Redis(host='localhost', port=6379, db=0)
def get_product_detail(product_id):
product_key = f'product:{product_id}:detail'
product_detail = r.get(product_key)
if product_detail is None:
# 从数据库获取商品详情数据
product_detail = get_product_detail_from_db(product_id)
if product_detail:
# 将数据缓存到Redis,设置1小时过期
r.setex(product_key, 3600, product_detail)
return product_detail
</pre></div>
<p>这里使用<code>SETEX</code>命令在设置商品详情数据时,同时设置了1小时的过期时间。当缓存过期后,下次请求会重新从数据库获取数据并更新缓存,保证数据的实时性。</p>
<p class="maodian"><a name="_lab2_4_10"></a></p><h3>(二)会话管理场景</h3>
<p>在Web应用的用户会话管理中,Redis可用于存储用户会话信息。</p>
<p>例如,用户登录成功后,将用户的会话信息存储在Redis中,并设置过期时间,以自动清理长时间未活动的会话。</p>
<div class="jb51code"><pre class="brush:sql;">import redis
import uuid
r = redis.Redis(host='localhost', port=6379, db=0)
def create_session(user_id):
session_id = str(uuid.uuid4())
session_key = f'session:{session_id}'
session_data = {'user_id': user_id}
# 将会话信息存储到Redis,设置30分钟过期
r.setex(session_key, 1800, str(session_data))
return session_id
def get_session(session_id):
session_key = f'session:{session_id}'
session_data = r.get(session_key)
if session_data:
return eval(session_data.decode('utf - 8'))
return None
</pre></div>
<p>上述代码中,<code>CREATE_SESSION</code>函数创建用户会话时,使用<code>SETEX</code>设置会话信息在30分钟后过期。<code>GET_SESSION</code>函数用于获取会话信息,若会话已过期,<code>GET</code>操作返回<code>None</code>,提示用户重新登录。</p>
<p class="maodian"><a name="_lab2_4_11"></a></p><h3>(三)分布式锁场景</h3>
<p>在分布式系统中,使用Redis实现分布式锁时,设置Key的过期时间可防止死锁。</p>
<div class="jb51code"><pre class="brush:sql;">import redis
import time
r = redis.Redis(host='localhost', port=6379, db=0)
def acquire_lock(lock_key, expire_time=10):
lock_value = str(uuid.uuid4())
success = r.set(lock_key, lock_value, ex=expire_time, nx=True)
return success, lock_value
def release_lock(lock_key, lock_value):
pipe = r.pipeline()
while True:
try:
pipe.watch(lock_key)
if pipe.get(lock_key).decode('utf - 8') == lock_value:
pipe.multi()
pipe.delete(lock_key)
pipe.execute()
return True
pipe.unwatch()
break
except redis.WatchError:
continue
return False
</pre></div>
<p>在<code>ACQUIRE_LOCK</code>函数中,使用<code>SET</code>命令结合<code>EX</code>参数设置锁的过期时间为10秒。如果持有锁的进程在10秒内未完成操作并释放锁,Redis会自动删除锁Key,防止其他进程永远无法获取锁,即避免死锁。</p>
<p class="maodian"><a name="_label5"></a></p><h2>总结</h2>
<p>以上为个人经验,希望能给大家一个参考,也希望大家多多支持琼殿技术社区。</p>
頁:
[1]