redis-py中ttl返回None 但是键没消失

问题复现

r = redis.Redis()
lock_name = "test_lock"
r.set(lock_name, "test")
r.expire(lock_name, 1)

t1 = 0
t2 = 0
while True:
    # 过期
    if not r.ttl(lock_name):
        # 记录下过期的时间
        if t1 == 0: t1 = time.time()
        # 记录键消失的时间
        if not r.exists(lock_name):
            t2 = time.time()
            break
    time.sleep(.01)
print t2 - t1

expire方法设置过期时间,ttl方法获取过期时间(不存在则为None),按理说过期之后,键就会消失,即t2 - t1 应该为0,但上面的case返回大约是0.5s。

解决方法

  • 使用pttl(返回毫秒数)代替ttl
  • 使用StrictRedis 代替Redis

原因

首先要确认一点,这是redis-py的锅,人家redis在某个版本之后已经能在1毫秒以内干掉过期的键了。具体是啥锅,得好好理一理

redis正常的返回值
  • 当 key 不存在时,返回 -2 。
  • 当 key 存在但没有设置剩余生存时间时,返回 -1 。
  • 否则,以秒为单位,返回 key 的剩余生存时间。
  • 注意 上边以秒为单位的生存时间,在我测试后发现是四舍五入后的,如果时间为0.4秒则会为0
StrictRedis 和Redis 区别
  • Redis 是StrictRedis 的子类,覆写了几个方法,大多是参数位置变一变,据说是为了兼容之前的版本所做的。
  • Redis 中跟TTL 相关的是这样一句 'TTL': lambda r: r >= 0 and r or None,这是一个解析redis返回的方法,StrictRedis 会直接返回值,而Redis会做一次包装。

问题就出在Redis 对redis返回的值的包装上,lambda r: r >= 0 and r or None 我猜测他本意应该是当对象存在ttl时返回ttl,不存在key或者没有设置expire时返回None(即返回值为-2 或者为-1 或者返回值就是None的时候),然而因为四舍五入的存在,0.4会变为0,lambda r: r >= 0 and r or None返回值则为None。私以为这里变为lambda r: r >= 0 and r is not None or None更为合适。

综上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,992评论 19 139
  • 1 Redis介绍1.1 什么是NoSql为了解决高并发、高可扩展、高可用、大数据存储问题而产生的数据库解决方...
    克鲁德李阅读 5,371评论 0 36
  • 本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概...
    kelgon阅读 61,286评论 23 625
  • 小雪日里雨雪淋 经霜晚菊散余馨 树头飞鸟叹枝寒 地上黄叶舞叠影 风斜只为摇竹林 云横不掩落花亭 洗却秋尘待梅开 处...
    牛德元阅读 748评论 0 6
  • 4月29日咖啡冥想 1、昨天下午回家看望婆婆,带着爱注视婆婆,听婆婆唠叨, 感觉婆婆真的老了,祝福老人身体健康!种...