当前位置: 首页 > news >正文

bitmap/hyperloglog/GEO详解与案例实战

在这里插入图片描述
痛点:类似今日头条,抖音这样的用户访问级别都是亿级别,请问如何处理?

​ 一句话 存的进+取得快+多维度,真正有价值的是统计…

大数据统计

聚合统计:

​ 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计。可以用Set实现

在这里插入图片描述

排序统计:

​ 抖音短视频最新评论留言的场景,设计一个展现列表。可以用Zset实现

在这里插入图片描述

二值统计

​ 集合的取值就只有0和1两种。比如钉钉打卡上班,我们只用记录有签到和没签到。可以使用bitmap实现

基数统计

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

基本术语:
  • UV(Unique View):多少个用户点击,独立访客,理解为客户端ip

  • PV(Page View):页面浏览量(不用去重)

  • DAU((Daily Active User):日活跃用户量(登陆或使用了某个产品的用户数)

  • MAU(Monthly Active User):月活跃用户量

  • 基数:是一种数据集,去重后的真实个数

需求:

很多计数类场景,比如每日注册IP数、每日访问IP数、页面实时访问数PV、访问用户数UV等。因为主要的目标高效、巨量地进行计数,所以对存储的数据的内容并不太关心。
也就是说它只能用于统计巨量数量,不太涉及具体的统计对象的内容和精准性。

  • 统计单日一个页面的访问量(PV),单次访问就算一次。
  • 统计单日一个页面的用户访问量(UV),即按照用户维度计算,单个用户一天内多次访问也只算一次。多个key的合并统计,某个门户网站的所有模块的PV聚合统计就是整个网站的总PV。
hyperloglog基本命令:
命令作用
pfadd key element…将所有元素添加到key中
pfcount key统计key的估算值
pgmerge new_key key1 key2…合并key至新key
原理:

对于亿级数据 bitmap去重:

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

HyperLogLog就是一种概率算法的实现,误差仅仅只是0.81%左右

在这里插入图片描述Redis中Hyperloglog前14位进行分桶,后50位进行获取Kmax
在这里插入图片描述
3.1 将数据转化为bit串
通过Hash函数,将数据转为64位的比特串,例如输入5,便转为:101。为什么要这样转化呢?

是因为要和抛硬币对应上,比特串中,0 代表了反面,1 代表了正面,如果一个数据最终被转化了 10010000,那么从右往左,从低位往高位看,我们可以认为,首次出现 1 的时候,就是正面。

那么基于上面的估算结论,我们可以通过多次抛硬币实验的最大抛到正面的次数来预估总共进行了多少次实验,同样也就可以根据存入数据中,转化后的出现了 1 的最大的位置 Kmax 来估算存入了多少数据。

3.2 分桶
分桶就是分多少轮。在抛硬币中我们可以将三次实验分为一组,用这一组的Kmax求平均值当作一次的Kmax,这样可以减少误差。

抽象到计算机存储中去,就是存储的是一个以单位是比特(bit),长度为 L 的大数组 S ,将 S 平均分为 m 组,注意这个 m 组,就是对应多少轮,然后每组所占有的比特个数是平均的,设为 P。容易得出下面的关系:

L = S.length
L = m * p
以 K 为单位,S 占用的内存 = L / 8 / 1024

为什么Hyperloglog大小为12K?

  1. 前14位用于分桶,也就是需要2^14 = 16384个桶(016383,也就是14位全0全1)

  2. 每个桶子需要存储后50位得到的Kmax值(起始开始最多连续零个数),而50位最多有50个0,因此Kmax最大取到50,2^6 = 64 > 50,因此每个桶只需要6个bit位就可以保存Kmax

  3. 每8个bit位为1字节,每1024字节为1K

  4. 综合以上两点:Hyperloglog的大小 = 16384 * 6 / 8 * 1024 = 12KB

  5. Redis将这种情况称为密集(dense)存储。

  6. 核心点:hyperloglog不存数据,可以理解为每个元素添加进去,一样的元素kmax不变,最后根据kmax估计所有桶去重个数 加和即可

案例实战
  • UV的统计需要去重,一个用户一天内的多次访问只能算作一次

  • 淘宝、天猫首页的UV,平均每天是1~1.5个亿左右

  • 每天存1.5个亿的IP,访问者来了后先去查是否存在,不存在加入

方案讨论:
  • 用mysql
  • 用 redis的hash结构存储
  • hyperloglog

代码实现:

//实现三层架构controller service  redisTemplete 即可

地理位置计算

在这里插入图片描述

GEO相关命令:

redis-cli --raw解决中文乱码问题

命令作用
GEOADD key longitude latitude member [longitude latitude member …]GEOADD 添加位置坐标
GEOPOS key member [member …]获取指定位置的坐标
GEOHASH key member [member …]返回坐标的geohash表示32位编码值 从三维编程二进制
GEODIST key member1 member2 [m\km\ft\mi]两个位置之间的距离
georadius key longitude latitude dist [m\km\ft\mi] withcoord count 10 desc以给定经纬度为中心,查找半径内附近的XXX
georadiusbymember key member dist [m\km\ft\mi] withlist withcoord count 10 withhash找出给定指定范围内的元素,中心点是由给定的位置元素决定
代码实例
//geoController
controller层调sevice层的方法	
//geoService调用redisTemplete层的对应geo方法写在service层下的方法即可//如geoadd()方法//注意点:整合springboot整合redis后 会有一个point类型,里面存经纬度public String geoadd(){Map<String,Point> map=new HashMap<>();map.put("天安门"new Point(116.403963,39.915119));...redisTemplete.opsForGeo().add(CITY,map);return map.toString();
}
//获得经纬度坐标public Point position(String member){				//key,member,如输入meber天安门,则返回天安门的经纬度坐标List<Point>list=redisTemplete.opsForGeo().position(CITY,member)}
//找出给定指定范围内的元素,中心点是由给定的位置元素决定
public GeoResults radiusByxy(){//北京王府井位置 116.418017,39.914402                 //以千米为单位给出半径Circle circle=new Circle(116.418017,39.914402,Metrics.KILOMETERS.getMultipler());//返回50条                              RedisGeoCommands.GeoRadiusCommandArgs args=     半径         距离           伴随经纬度      降序              50条记录 RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance.includeCoordinates().sortDescending().limit(50)reidsTemple.opsForGeo().radius(CITY,circle,args).var;return geoResults;
}

相关文章:

  • 【MySQL进阶】如何在ubuntu下安装MySQL数据库
  • Java—— 异常详解
  • 机器学习中的过拟合及示例
  • 计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 12.曲面细分
  • MySQL初阶:sql事务和索引
  • 深入解析Spring Boot与Redis集成:高效缓存实践
  • 如何彻底清空docker里面不使用的容器?
  • 面向对象详解和JVM底层内存分析
  • Windows运维工具批处理版
  • 使用Python和`python-docx`库复制Word文档样式
  • mysql中4种扫描方式和聚簇索引非聚簇索引【爽文一篇】
  • BG开发者日志517:demo数据分析与修改方向
  • muduo库TcpConnection模块详解——C++
  • MySQL只操作同一条记录也会死锁吗?
  • Linux面试题集合(5)
  • 通俗版解释CPU、核心、进程、线程、协程的定义及关系
  • AGI大模型(21):混合检索之混合搜索
  • CSS 浮动与定位以及定位中z-index的堆叠问题
  • 管理前端项目依赖版本冲突导致启动失败的问题的解决办法
  • 深度学习---知识蒸馏(Knowledge Distillation, KD)
  • 芬兰直升机相撞坠毁事故中五名人员全部遇难
  • 复旦建校120周年大型义诊举行,百余名专家服务市民超三千人次
  • 见微知沪|科学既要勇攀高峰,又要放低身段
  • 六省会共建交通枢纽集群,中部六省离经济“第五极”有多远?
  • 陕西三原高新区违法占用土地,被自然资源局罚款10万元
  • 刘强东坐镇京东一线:管理层培训1800人次,最注重用户体验