19年6月第3周
<h4>布隆过滤器 (Bloom Filter)</h4>
<h5>简介</h5>
<p>布隆过滤器 是一种概率性的数据结构,或者说是一系列随机映射函数,主要用于检测一个元素是否在一个集合中,相较于传统的做法,能提高空间利用效率和查询效率,但可能将不存在集合的元素误判为存在,同时不支持从集合中删除元素</p>
<h5>原理</h5>
<ul>
<li>插入</li>
</ul>
<p>布隆过滤器将元素进行哈希后得到一个偏移量(位置),将位图中对应位置的值置为1,并使用不同的哈希函数多次进行该操作,最后将多个位置置为1</p>
<ul>
<li>检索</li>
</ul>
<p>与插入相同,依次对元素哈希,如果所有位置上都为1,则认为该元素存在(可能存在,实际可能不存在),如果遇到一个位置为0,则可以判断该元素肯定不存在</p>
<ul>
<li>应用</li>
</ul>
<p>一般用于无删除需求的大量记录,需要指定两个参数 哈希的次数 以及 位图的长度,两个参数越大,误判率越低、查询速度越慢、占用空间越高</p>
<p>使用 RedisBloom 拓展时可以直接指定 错误率 和 集合长度,拓展会根据这两个参数设定 哈希 和 位图</p>
<p>当设定容错率为 千分之一 和 集合长度为 1亿时,redis 占用 250m 内存</p>
<h5>实现</h5>
<p>依据布隆过滤器的原理,使用 php 内置的哈希函数,默认哈希 3次,位图长度 1亿</p>
<pre><code>$chip = 100000000;
$redis = new Redis();
$redis->connect('127.0.0.1');
$redis->flushAll();
$times = 1;
while($times++ < 100000) {
$item = uniqid();
bfAdd('learnBloom', $item);
if(!bfExists('learnBloom', $item))
echo 1;
}
function bfAdd($key, $item) {
global $redis;
global $chip;
$key = $key . intval(crc32($item) / $chip);
$redis->setBit($key, crc32($item) % $chip, 1);
$redis->setBit($key, crc32(md5($item)) % $chip, 1);
$redis->setBit($key, crc32(sha1($item)) % $chip, 1);
}
function bfExists($key, $item) {
global $redis;
global $chip;
$key = $key . intval(crc32($item) / $chip);
return $redis->getBit($key, crc32($item) % $chip) &&
$redis->getBit($key, crc32(md5($item)) % $chip) &&
$redis->getBit($key, crc32(sha1($item)) % $chip) ;
}</code></pre>
<h4>点赞功能迁移至 mongo</h4>
<ul>
<li>原有的点赞功能存在 mysql 中,并且设定了 appid、openid、article_id 的联合唯一索引,在网络波动环境下容易报 唯一性冲突 的错误</li>
<li>将点赞功能迁移到 mongo 中,按 appid 分表,将 article_id 存到 openid 行对应的一列集合中,可以显著减少点赞记录的条数</li>
<li>因为服务器在迁移,无法测试上线,使用该分支前务必测试,上线后务必在 mongo 加索引</li>
</ul>
<h4>swoole 功能迁出 first commit</h4>
<ul>
<li>.env 的相关配置从测试区中复制获得</li>
<li>修改 文章处理 和 定时文章处理 使之与迁出后的配置相适应</li>
</ul>
<h4>点开 视频合成 素材保存草稿</h4>
<ul>
<li>增加 素材 模型的 最后保存时间 和 最后制作时间 属性</li>
<li>根据 id 是否为空,如果是从 素材库进入 则根据 素材id 进行更新操作,如果是新增合成视频则 新增一个素材,并返回新增素材的 id</li>
<li>优化之前的代码,将新旧结构的转换逻辑从业务逻辑中分离出来,增加代码的可读性</li>
</ul>
<h5>收获</h5>
<ul>
<li>在数据规模较大时,使用布隆过滤器判断元素是否在集合中可以节省时间和空间</li>
</ul>