#test1.php <?php header("content-type: text/html;charset=utf8;"); $redis=new Redis(); $redis->connect('192.168.95.11','6379'); $start=time(); for ($i=0; $i<50000 ; $i++) { $redis->lpush('test-list',$i.'-aaaassssssddddddkkk'); } $end=time(); echo "插入耗时为:".($end-$start).'s'; ?>
结果耗时4秒
2、执行相应命令,查看耗时
#test2.php <?php header("content-type: text/html;charset=utf8;"); $redis=new Redis(); $redis->connect('192.168.95.11','6379'); $start=time(); $num=0; while($redis->rpoplpush('test-list','test-new')) { $num+=1; } echo '执行次数为:'.$num."<br/>"; $end=time(); echo "耗时为:".($end-$start).'s'; ?>
更改配置文件下测试
1、先修改配置文件
list-max-ziplist-entries 100000 #将这个值修改大一点,可以更好的凸显对性能的影响
list-max-ziplist-value 64 #此值可不做修改
2、插入数据
执行test1.php
结果为:耗时12s
3、执行相应命令,查看耗时
执行test2.php
结果为:执行次数:50000,耗时12s
结论:
在本机中执行测试50000条数据就相差8s,若在高并发下,长压缩列表和大整数集合将起不到任何的优化,反而使得性能降低。
3、片结构
分片的本质就是基于简单的规则将数据划分为更小的部分,然后根据数据所属的部分来决定将数据发送到哪个位置上。很多数据库使用这种技术来扩展存储空间,并提高自己所能处理的负载量。
结合前面讲到的,我们不难发现分片结构对于redis的重要意义。因此我们需要在配置文件中关于ziplist以及intset的相关配置做出适当的调整。
3.1、分片式散列
#ShardHash.class.php
<?php class ShardHash { 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 计算某key的分片ID * * @param $base string | 基础散列 * @param $key string | 要存储到分片散列里的键名 * @param $total int | 预计非数字分片总数 * * @return string | 返回分片键key */ public function shardKey ($base,$key,$total) { if(is_numeric($key)) { $shard_id=decbin(substr(bindec($key),0,5)); #取$key二进制高五位的十进制值 } else { $shard_id=crc32($key)%$shards; #求余取模 } return $base.'_'.$shard_id; } /** * @desc 分片式散列hset操作 * * @param $base string | 基础散列 * @param $key string | 要存储到分片散列里的键名 * @param $total int | 预计元素总数 * @param $value string/int | 值 * * @return bool | 是否hset成功 */ public function shardHset($base,$key,$total,$value) { $shardKey=$this->shardKey($base,$key,$total); return $this->redis->hset($shardKey,$key,$value); } /** * @desc 分片式散列hget操作 * * @param $base string | 基础散列 * @param $key string | 要存储到分片散列里的键名 * @param $total int | 预计元素总数 * * @return string/false | 成功返回value */ public function shardHget($base,$key,$total) { $shardKey=$this->shardKey($base,$key,$total); return $this->redis->hget($shardKey,$key); } } $obj=new ShardHash('192.168.95.11'); echo $obj->shardHget('hash-','key',500); ?>
散列分片主要是根据基础键以及散列包含的键计算出分片键ID,然后再与基础键拼接成一个完整的分片键。在执行hset与hget以及大部分hash命令时,都需要先将key(field)通过shardKey方法处理,得到分片键才能够进行下一步操作。
3.2、分片式集合
如何构造分片式集合才能够让它更节省内存,性能更加强大呢?主要的思路就是,将集合里面的存储的数据尽量在不改变其原有功能的情况下转换成可以被解析为十进制的数据。根据前面所讲到的,当集合中的所有成员都能够被解析为十进制数据时,将会采用intset存储方式,这不仅能够节省内存,而且还可以提高响应的性能。
例子:
假若要某个大型网站需要存储每一天的唯一用户访问量。那么就可以使用将用户的唯一标识符转化成十进制数字,再存入分片式set中。
#ShardSet.class.php