我正在编写一个PHP函数,根据我的日期戳,使用一个表来查找应用程序应该去哪个DB分片。
分片配置是这样的(伪代码):第一列是我正在寻找的事件的日期,第二列是事件所在的分片。
pre-2008 -> shard1
2008-2009 -> shard2
2009_01-2009_06 -> shard3
2009_07 -> shard4
2009_08 -> shard5
2009_09 and up -> shard6
正如您所看到的,我想要的配置非常灵活 - 它可以占用任何日期范围,无论大小,都可以映射到分片。
我正在寻找基于给定日期进行查找的最快方法。
例如,如果我的日期是2009-05-02,那么我所追踪的碎片是shard3。如果日期是2007-08-01,那么它是shard1。
实际PHP代码的加分点,因为应用程序是用PHP格式的。
谢谢。
答案 0 :(得分:2)
<?php
function get_shard($datetime)
{
$timestamp = strtotime($datetime);
$shards = array(array('start' => null, 'end' => '2007-12-31'),
array('start' => '2008-01-01', 'end' => '2008-12-31'),
array('start' => '2009-01-01', 'end' => '2009-06-30'),
array('start' => '2009-07-01', 'end' => '2009-07-31'),
array('start' => '2009-08-01', 'end' => '2009-08-31'),
array('start' => '2009-09-01', 'end' => null),
);
foreach ($shards as $key => $range) {
$start = strtotime($range['start']);
$end = strtotime($range['end']);
if ($timestamp >= $start && $timestamp <= $end) {
return $key + 1;
}
if ($timestamp >= $start && $end === false) {
return $key + 1;
}
}
}
$datetime = '2007-08-01';
echo 'shard' . get_shard($datetime) . "\n";
$datetime = '2009-05-02';
echo 'shard' . get_shard($datetime) . "\n";
$datetime = '2010-01-01';
echo 'shard' . get_shard($datetime) . "\n";
?>
输出:
shard1
shard3
shard6
答案 1 :(得分:2)
我猜你不想要在日期范围内打洞,所以我建议你 只需为每个分片指定结束日期,并明确命名一个默认分片 它包含了一些太新而无法容纳其他碎片的东西。
// configure shards
$SHARDS = array(
// <end date> => <shard number>
'2007-12-31' => 'shard1', // shard1 - up to end of 2007
'2008-12-31' => 'shard2', // shard2 - up to end of 2008
'2009-06-30' => 'shard3', // shard3 - up to end of June 09
'2009-07-31' => 'shard4', // shard4 - up to end of July 2009
'2009-08-31' => 'shard5', // shard4 - up to end of August 2009
'DEFAULT' => 'shard6', // everything else in shard 6
);
这样可以很容易地获得正确的日期,并且基于日期查找分片的代码很简单:
function findShardByDate($date) {
static $default = false;
static $sorted = false;
if($sorted === false) {
// copy of global $SHARDS
$SHARDS = $GLOBALS['SHARDS'];
$default = $SHARDS['DEFAULT'];
unset($SHARDS['DEFAULT']);
// make sure $SHARDS is sorted
ksort($SHARDS);
$sorted = $SHARDS;
unset($SHARDS);
}
// find the first shard which would contain that date
foreach($sorted as $endDate => $shardName)
if($endDate >= $date)
return $shardName;
// no shard found - use the default shard
return $default;
}
编辑:使用静态变量,以便只进行一次排序。
答案 2 :(得分:0)
由于您的分片可以严格排序,似乎将它们存储在二叉树中,然后只需通过该树运行二进制搜索就可以获得最快的结果。