散列分片主要是根据基础键以及散列包含的键计算出分片键ID,然后再与基础键拼接成一个完整的分片键。在执行hset与hget以及大部分hash命令时,都需要先将key(field)通过shardKey方法处理,得到分片键才能够进行下一步操作。
3.2、分片式集合
如何构造分片式集合才能够让它更节省内存,性能更加强大呢?主要的思路就是,将集合里面的存储的数据尽量在不改变其原有功能的情况下转换成可以被解析为十进制的数据。根据前面所讲到的,当集合中的所有成员都能够被解析为十进制数据时,将会采用intset存储方式,这不仅能够节省内存,而且还可以提高响应的性能。
例子:
假若要某个大型网站需要存储每一天的唯一用户访问量。那么就可以使用将用户的唯一标识符转化成十进制数字,再存入分片式set中。
#ShardSet.class.php
<?php
class ShardSet
{
private $redis=''; #存储redis对象
/**
* @desc 构造函数
*
* @param $host string | redis主机
* @param $port int | 端口
*/
public function __construct($host,$port=6379)
{
$this->redis=new Redis();
$this->redis->connect($host,$port);
}
/**
* @desc 根据基础键以及散列包含的键计算出分片键
*
* @param $base string | 基础散列
* @param $key string | 要存储到分片散列里的键名
* @param $total int | 预计分片总数
*
* @return string | 返回分片键key
*/
public function shardKey ($base,$member,$total=512)
{
$shard_id=crc32($member)%$shards; #求余取模
return $base.'_'.$shard_id;
}
/**
* @desc 计算唯一用户日访问量
*
* @param $member int | 用户唯一标识符
*
* @return string | ok表示count加1 false表示用户今天已经访问过不加1
*/
public function count($member)
{
$shardKey=$this->shardKey('count',$member,$total=10); #$totla调小一点用于测试
$exists=$this->redis->sismember($shardKey,$member);
if(!$exists) #判断member今天是否访问过
{
$this->redis->sadd($shardKey,$member);
$this->redis->incr('count');
$ttl1=$this->redis->ttl('count');
if($ttl1===-1)
$this->redis->expireat('count',strtotime(date('Y-m-d 23:59:59'))); #设置过期时间
$ttl2=$this->redis->ttl($shardKey);
if($ttl2===-1)
{
$this->redis->expireat("$shardKey",strtotime(date('Y-m-d 23:59:59'))); #设置过期时间
#echo $shardKey; #测试使用
}
#echo $shardKey; #测试使用
return 'ok';
}
return 'false';
}
}
$str=substr(md5(uniqid()), 0, 8); #取出前八位
#将$str作为客户的唯一标识符
$str=hexdec($str); #将16进制转换为十进制
$obj=new ShardSet('192.168.95.11');
$obj->count($str);
?>
4、将信息打包转换成存储字节
结合前面所讲的分片技术,采用string分片结构为大量连续的ID用户存储信息。







