数据包的超时管理:TTL

TTL的起源

在各种需要进行数据包传送的场景下,数据包一般都有一个超时管理机制:Time To Live,即TTL。
为什么需要这么一个机制呢?
举个例子,在IP协议发送数据包的时候,可能会经过多个路由转发环节。若其中的某个环节出了问题,就可能造成这个数据包一直在数个路由器中反复转发。这样既不能正确到达目的地,也无法及时释放这些资源。
如何来避免这种情况发生呢?给每个数据包都加上一个超时时间即可,然后用另一个程序一直检查已用时间是否已经到达这个超时时间。这样便可以该数据包超时的时候进行灵活处理。

应用场景

本文主要分析各个资料可查证的应用,主要包括IP协议网络包的TTL设计、消息队列开源组件RabbitMQ、缓存开源组件Redis、数据库开源组件MariaDB等几个方面来进行分析。

IP协议TTL设计

RabbitMQ TTL设计

Redis TTL设计

参考【1】p99。
此处涉及到两个概念:生存时间和过期时间。
前者是针对一个key,设置一个倒计时,当倒计时归零时便由服务器删除这个键;后者则是给定一个绝对时间(此处为给定一个Unix时间戳),当时间到达这个给定的过期时间时,有服务器删除这个键。

这是同一个问题的两种灵活的设计方式,这样便能够考虑所有的应用场景了。

生存时间和过期时间的实现

这两者在实现的过程中是一样的,最终结果都是以设置绝对的过期时间来实现的。
设置生存时间的时候,获得当前时间的Unix时间戳,然后加上设定的生存时间,将这个时间作为绝对的过期时间,在本地时间达到这个时间的时候触发相应操作。
那么用什么样的数据结构来保存过期时间比较好呢? RedisDB中采用了一个字典expires来进行管理,我们称这个字典为过期字典。
这个过期字典的key是一个指针,指向要管理的某个键对象,value则是一个long long 类型的证书,保存了这个key对应数据库键的过期时间–一个毫秒精度的Unix时间戳。
这样就可以通过该过期字典中对某个key建立具体数据库的键的对应关系来设置过期时间,通过取消其关系而取消设置过期时间。

如何检查某个键的TTL
计算剩余生存时间

Redis中使用了TTL <key>来返回一个以秒为单位的剩余时间,使用PTTL <key>来返回以毫秒为单位的剩余时间。具体是怎么实现的呢?
实际上很简单,只需获得这个key当时设置的过期时间,然后将当前时间减去这个过期时间即可获得剩余时间。

判断是否过期

在过期字典中查找该键,若存在,则取得其过期时间,然后将当前时间与之进行对比,若大于过期时间则表示已经过期。

过期删除策略

在学习B树算法的时候,我们可以明显地感觉到对于具有任何特性的树(二叉搜索树、二叉平衡树、红黑树、B树、B+树等),插入和搜索的算法总是简单的,困难的是删除某个节点还要保证这棵树原有的特性,此时就需要一些额外的操作来保证原有的特性不丢失。即:删除总是最麻烦的。
因此发展出来了几种非即时删除的思路:定时删除、惰性删除、定期删除。这其实是通用的思路,很多数据库存储引擎中都或多或少采取了这种方法。后期将对多种存储引擎(LevelDB、…)的元数据组织算法进行对比分析。

定时删除

在设置键的过期时间时创建一个定时器,当键的过期时间来临时,立即执行对键的删除操作。

惰性删除

不管过期时间,但每次从键空间中获取键的时候,都检查取得的键是否过期。若过期的话,就删除改键,若没有过期,则返回该键。

过期删除

每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于一次删除多少个过期键,以及要检查多少个数据库,由相关算法决定。

MariaDB TTL设计

存储系统中TTL/TTO设计

Redis中考虑的很简单,过期就无效了,无需对该key再做操作,以任何的策略丢弃即可。而一些存储引擎则还需要对其进行操作,以避免丢失该数据造成数据不一致。

参考文献

【1】 《Redis设计与实现》
【2】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值