1

我正在编写一个 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 年 5 月 2 日,那么我要查找的分片是 shard3。如果日期是 2007-08-01,那么它是 shard1。

实际 PHP 代码的奖励积分,因为应用程序是 PHP。

谢谢你。

4

3 回答 3

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
于 2009-08-17T23:55:47.287 回答
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;
}

编辑:使用静态变量,以便排序只进行一次。

于 2009-08-18T00:11:49.860 回答
0

由于您的分片可以严格排序,因此似乎将它们存储在二叉树中,然后简单地通过该树运行二叉搜索会给您最快的结果。

于 2009-08-17T23:37:01.740 回答