Redis(十五)Bitmap、Hyperloglog、GEO案例、布隆过滤器

文章目录

  • 面试题
  • 常见统计类型
    • 聚合统计
    • 排序统计
    • 二值统计
    • 基数统计
  • Hyperloglog
    • 专有名词
      • UV(Unique Visitor)独立访客
      • PV(Page View)页面浏览量
      • DAU(Daily Active User)日活跃用户量
      • MAU(Monthly Active User)
    • 需求
    • 原理
    • 亿级UV的Redis统计方案
  • GEO
    • 面试题
    • 命令
      • GEOADD
      • 获取某位置的经纬度GEOPOS
      • 返回坐标的Geohash表示GEOHASH
      • 两个位置之间距离GEODIST
      • 半径范围内的坐标GEORADIUS
      • 半径范围内坐标中心点是给定元素GEORADIUSBYMEMBER
  • Bitmap
    • 面试题
    • 作用场景
  • 布隆过滤器BloomFilter
    • 需求
    • 概述
    • 作用
    • 原理
      • 概述原理
      • 添加、查询元素过程
      • 使用步骤
      • 使用场景
    • 手写布隆过滤器案例
      • 优缺点
      • 布谷鸟过滤器:解决布隆过滤器不能删除缺点

面试题

  1. 抖音电商直播,主播介绍的商品有评论,1个商品对应了1系列的评论,排序+展现+取前10条记录
  2. 用户在手机App上的签到打卡信息:1天对应1系列用户的签到记录,新浪微博、钉钉打卡签到,来没来如何统计?
  3. 应用网站上的网页访问信息:1个网页对应1系列的访问点击,淘宝网首页,每天有多少人浏览首页?
  4. 你们公司系统上线后,说一下UV、PV、DAU分别是多少?

记录对集合中的数据进行统计

  1. 在移动应用中,需要统计每天的新增用户数和第2天的留存用户数;
  2. 在电商网站的商品评论中,需要统计评论列表中的最新评论;
  3. 在签到打卡中,需要统计一个月内连续打卡的用户数;
  4. 在网页访问记录中,需要统计独立访客(Unique Visitor,UV)量。

需求
亿级数据的收集+清洗+统计+展现

常见统计类型

亿级系统常见统计方式

聚合统计

统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计
Redis(十五)Bitmap、Hyperloglog、GEO案例、布隆过滤器_第1张图片
交并差集和聚合函数的应用

排序统计

  • 抖音短视频最新评论留言的场景,请你设计一个展现列表。

在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,建议使用ZSet

二值统计

集合元素的取值就只有0和1两种
在钉钉上班签到打卡的场景中,我们只用记录有签到(1)或没签到(0)
bitmap

基数统计

指统计一个集合中不重复的元素个数
见hyperloglog

Hyperloglog

去重统计估计算法

专有名词

UV(Unique Visitor)独立访客

需要去重考虑

PV(Page View)页面浏览量

不用去重

DAU(Daily Active User)日活跃用户量

登录或者使用了某个产品的用户数(去重复登录的用户)
常用于反映网站、互联网应用或者网络游戏的运营情况

MAU(Monthly Active User)

月活跃用户量

需求

  1. 很多计数类场景,比如 每日注册 IP 数、每日访问 IP 数、页面实时访问数 PV、访问用户数 UV等。
  2. 因为主要的目标高效、巨量地进行计数,所以对存储的数据的内容并不太关心。
  3. 也就是说它只能用于统计巨量数量,不太涉及具体的统计对象的内容和精准性。
  4. 统计单日一个页面的访问量(PV),单次访问就算一次。
  5. 统计单日一个页面的用户访问量(UV),即按照用户为维度计算,单个用户一天内多次访问也只算一次。
  6. 多个key的合并统计,某个门户网站的所有模块的PV聚合统计就是整个网站的总PV。

问题
如果数据显较大亿级统计,使用bitmaps同样会有问题。

bitmap是通过用位bit数组来表示各元素是否出现,每个元素对应一位,所需的总内存为N个bit。

基数计数则将每一个元素对应到bit数组中的其中一位,比如bit数组010010101(按照从零开始下标,有的就是1、4、6、8)。

新进入的元素只需要将已经有的bit数组和新加入的元素进行按位或计算就行。这个方式能大大减少内存占用且位操作迅速。

但是,假设一个样本案例就是一亿个基数位值数据,一个样本就是一亿
如果要统计1亿个数据的基数位值,大约需要内存100000000/8/1024/1024约等于12M,内存减少占用的效果显著。

这样得到统计一个对象样本的基数值需要12M。
如果统计10000个对象样本(1w个亿级),就需要117.1875G将近120G,可见使用bitmaps还是不适用大数据量下(亿级)的基数计数场景,

但是bitmaps方法是精确计算的。

原理

概率算法
通过牺牲准确率来换取空间,对于不要求绝对准确率的场景下可以使用,因为概率算法不直接存储数据本身。
通过一定的概率统计方法预估基数值,同时保证误差在一定范围内,由于又不储存数据故此可以大大节约内存。
HyperLogLog就是一种概率算法的实现。

只是进行不重复的基数统计,不是集合也不保存数据,只记录数量而不是具体内容。
Hyperloglog提供不精确的去重计数方案
牺牲准确率来换取空间,误差仅仅只是0.81%左右
http://antirez.com/news/75

亿级UV的Redis统计方案

UV的统计需要去重,一个用户一天内的多次访问只能算作一次
淘宝、天猫首页的UV,平均每天是1~1.5个亿左右
每天存1.5个亿的IP,访问者来了后先去查是否存在,不存在加入

// 用于产生模拟后台访问数据
@Service
@Slf4j
public class HyperLogLogService
{
   
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 模拟后台有用户点击首页,每个用户来自不同ip地址
     */
    @PostConstruct
    public void init()
    {
   
        log.info("------模拟后台有用户点击首页,每个用户来自不同ip地址");
        new Thread(() -> {
   
            String ip = null;
            for (int i = 1; i <=200; i++) {
   
                Random r = new Random();
                ip = r.nextInt(256) + "." + r.nextInt(256) + "." + r.nextInt(256) + "." + r.nextInt(256);

                Long hll = redisTemplate.opsForHyperLogLog().add("hll", ip);
                log.info("ip={},该ip地址访问首页的次数={}",ip,hll);
                //暂停几秒钟线程
                try {
    TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {
    e.printStackTrace(); }
            }
        },"t1").start

你可能感兴趣的:(Java,redis,面试,数据库)