redis 面试相关
容器型数据结构的通用规则
list/set/hash/zset 这四种数据结构是容器型数据结构,它们共享下面两条通用规则:
1、create if not exists
如果容器不存在,那就创建一个,再进行操作。比如 rpush 操作刚开始是没有列表的,
Redis 就会自动创建一个,然后再 rpush 进去新元素。
2、drop if no elements
如果容器里元素没有了,那么立即删除元素,释放内存。这意味着 lpop 操作到最后一
个元素,列表就消失了
还有一个需要特别注意的地方是如果一个字符串已经设置了过期时间,然后你调用了
set 方法修改了它,它的过期时间会消失。
redis缓存穿透处理
譬如
新闻表的 id 范围 是 100~~~~~2000
这时如果查询2004 或者3000 等ID是没有的,但不代表未来没有。因此这里有其中一个做法如下:
1、譬如key=news200,如果数据库查询返回空
2、那么我们依然往redis存储一个我们约定好的数据结构 并且设置过期时间,譬如设置为200秒(到底多少秒
要根据实际情况来调整)
3、下次如果继续查到这个key,那么我们增加这个key的过期时间(譬如5秒)
伪代码如下:
StringnewsID=getParameter("id");
NewsgetNews= getFromRedis("news"+newsID);
if(getNews==null)
{
getNews=getFromDB("news"+newsID);
if(getNews==null)
{
getNews=defaultCache();//设置一个固定缓存-1
}
setToRedis(getNews,200); //塞入redis,初始过期时间为200秒
}
else if(getNews.equal(defaultCache)) //如果取出的缓存是 默认缓存,则增加5秒的过期时间
{
expireCache("news"+newsID,50);
}
response.write(getNews);
redis 应用之HyporLogLog
当统计一个网站的pv时,我们可以用redis 的计数器功能实现,给每个网页一个独立的计数器,技术器的key 后缀加上当天的日期,这样来一个请求,incrby 一次,最后算出所有的pv数据。
但是UV 的话,一天一个用户访问多次的话只统计一次,就要去重,这要每个网页求都要带上唯一的用户ID来标识(无论是登陆还是未登录)。你也许已经想到了一个简单的方案,那就是为一个页面一个独立的 set 集合来存储所有当天访问过此页面的用户 ID。当一个请求过来时,我们使用 sadd 将用户 ID 塞进去就可以了。通过 scard 可以取出这个集合的大小,这个数字就是这个页面的 UV 数据。但是,当访问量非常多,就需要一个很大的set集合来统计,这就非常浪费空间。
HyporLogLog很好地解决了这个问题,。HyperLogLog 提供不精确的去重计数方案,虽然不精确但是也不是非常不精确。HyperLogLog 提供了两个指令 pfadd 和 pfcount,根据字面意义很好理解,一个是增加计数,一个是获取计数。pfadd 用法和 set 集合的 sadd 是一样的,来一个用户 ID,就将用户 ID 塞进去就是。pfcount 和 scard 用法是一样的,直接获取计数值。
HyperLogLog 除了上面的 pfadd 和 pfcount 之外,还提供了第三个指令 pfmerge,用于将多个 pf 计数值累加在一起形成一个新的 pf 值。比如在网站中我们有两个内容差不多的页面,运营说需要这两个页面的数据进行合并。其中页面的 UV 访问量也需要合并,那这个时候 pfmerge 就可以派上用场了。
除此之外,HyporLogLog还可以统计一段时间用户注册量,比如pfmerge 把8月的每一天的数据合并为8月,pfcount 统计数量。