【问题标题】:Redis modeling reservationsRedis 建模预留
【发布时间】:2016-04-24 16:36:22
【问题描述】:

我正在从事一个了解 Redis 的个人项目。我正在尝试将其用作管理酒店的数据库。我正在努力思考如何管理预订。

问题是,有多个房间,每个房间可以有多个预订,存储 date-from 和 date-to。我只是不确定如何对此进行建模,以便在给定的给定时间段内有效地找到一个空房间。

目前,我一直在考虑将每个单独房间的预订存储在已排序的集合中,但这样我就必须逐个遍历房间,直到找到合适的房间。

欢迎任何意见。谢谢

【问题讨论】:

  • 预订是否有最小固定时间长度?例如,任何预订都必须至少为一天,从中午开始到结束?
  • 是的,这正是您描述的方式。预订至少 24 小时,中午开始/结束。另一方面,没有最大长度。

标签: node.js redis data-modeling key-value key-value-store


【解决方案1】:

一种方法是使用集合来表示日期范围,其中每个集合代表一天并由整数标识。然后,一组成员将代表当天哪些房间可供预订。由于预订每天在同一时间开始和结束,并且任何预订都可以用一整天来衡量,因此您可以将任何一天表示为整数。例如,使用 Unix 纪元(1970 年 1 月 1 日)作为开始时间,今天(2016 年 4 月 24 日)将是 16915。或者在 JavaScript 中:

Math.floor(new Date().getTime() / (1000 * 60 * 60 * 24));

然后,您可以通过在输入范围内的天数上进行设置交集来查找在给定日期范围内哪些房间可用。 This gives you O(n * m) lookup time 其中n 是最小集合的大小,m 是集合的数量。由于该集合最多包含每个房间一次,这意味着n 受房间总数的限制。例如:

var _ = require("lodash");

var dateToInt = function(date){
  return Math.floor(date.getTime() / (1000 * 60 * 60 * 24));
};

var roomsInRange = function(client, start, end, callback){
  client.sinter(_.range(dateToInt(start), dateToInt(end)), callback);
};

当用户为某个日期范围预订房间时,您会从该日期范围内的每个集合中删除该房间号。

var _ = require("lodash");

var dateToInt = function(date){
  return Math.floor(date.getTime() / (1000 * 60 * 60 * 24));
};

var reserveRoom = function(client, start, end, room, callback){
  var trx = client.multi();
  _.each(_.range(dateToInt(start), dateToInt(end), function(day){
    trx.srem(day, room);
  });
  trx.exec(callback);
};

这种方法复制了大量数据,因为每个房间都被多次表示,但大小受房间数量和您需要表示的最大日期范围的限制。例如,我认为不允许用户提前 5 年进行预订,也不允许他们在过去进行预订,这意味着除了限制输入范围的上限之外,您还可以清理过去的条目。鉴于键是整数,并且房间也可能用整数表示,如果一年的预订需要超过 1 或 2 MB 的空间,我会感到惊讶。

【讨论】:

  • 这是一种非常有趣的解决问题的方法,它应该适用于我正在做的事情。它还利用了 redis 在集合方面的优势。我不确定我是否理解最后一个示例中异步在做什么。你能详细说明一下吗?
  • 哦,糟糕,在使用 redis 事务之前,我在之前的编辑中就有了它。现在删除它。
  • 这样就搞定了。您提供的解决方案清晰且经过深思熟虑,它让我对在使用 redis 及其功能集时如何创造性地思考有了新的看法。感谢您花时间写下所有这些。
  • 没问题,很高兴它有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
  • 1970-01-01
  • 2020-07-04
  • 2022-01-25
相关资源
最近更新 更多