乐趣区

关于redis:深入理解redis新类型bitmaphyperloglgoGEO

1. 为什么会有这三种类型?

2. 统计的类型有哪些?

3.bitmap 类型及其利用

4.hyperloglog 类型及其利用

5.GEO 类型及其利用

6. 总结

1. 为什么会有这三种类型?
假如咱们当初有上面这三个需要:
1. 有一个签到打卡的性能,须要统计一个月内间断打卡的用户。
2. 统计一个网站的用户浏览量(PV)。
3. 打车软件中,查出左近闲暇的车辆

如果以上的数据都是 亿级别,请问你该如何统计?

需要痛点:
1.存储 问题:数据量太大,如何省空间存储
2. 取数 问题:数据量大的时候,数据可能存的进,取不出

2. 统计的类型有哪些?

在咱们的日常报表开发中,常见的有以下四种统计

1)聚合统计:统计多个元素聚合的后果,比方总和,交并差汇合。

2)排序统计:依照某个值进行排序,并返回列表的统计,比方排行榜。

3)二值统计:汇合元素取值只有 0 或者 1 两种,比方签没签到。

4)基数统计:统计汇合中不反复的元素个数,比方统计网站 UV 值。

3.bitmap 类型及其利用
咱们先看一下 bitMap 的数据结构:

阐明:用 String 类型作为底层数据结构实现的一种统计 二值状态(0 或者 1)的数据类型。
bitMap 把一个字节拆分成了 8 位,每一个位别离能存 0 或者 1,这是一种把一个字节拆成八个位的存储方法,空间利用率比拟高。
Bitmap 反对的最大位数是 2^32 位,它能够极大的节约存储空间,应用 512M 内存就能够存储多大 42.9 亿的字节信息(2^32 = 4294967296)

利用:
签到性能,日沉闷数统计,该用户一年中登录的天数等等。

假如咱们当初要制作一个签到性能

惯例的思路:mysql 作为解决方案:

CREATE TABLE user_sign
(
keyid BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
user_key VARCHAR(200),# 京东用户 ID
sign_date DATETIME,# 签到日期(20210618)
sign_count INT #间断签到天数
)

创立一张这样的表,而后依据业务逻辑 crud 就能够了,然而数据量一旦达到 亿级 ,就有可能呈现 存的进,取不出 的难堪状况,而后存储的空间也会变得十分大。

改良办法:基于 Redis 的 BitMaps 实现签到日历。

咱们后面提到过,bitMap 将一个字节拆分成了 8bit,咱们只须要用到一个 bit,就能够示意 一天的签到状况 (值为 0 或者 1)。
一个月最多 31 天,那么只须要用到 31 个 bit 位 ,一年的签到状况也只须要用到365 个 bit 位,咱们再拿 “ 年 - 月 ” 等值作为 key, 就能够极大节俭空间。

根本命令:
redis:

setbit key offset value //setbit 键   偏移位  只能零或者 1 
getbit key offset 
strlen // 统计字节数占用多少
bitcount // 全副键外面含有 1 的有多少个?bitop // 将两个值做与运算,比方统计两天同时都签到的人



java:

stringRedisTemplate.opsForValue().setBit(key, offset, value);

4.hyperloglog 类型及其利用
hyperloglog 是什么:
它是一种去重统计性能的基数预计算法 , 它并 不保留数据自身 ,而是依据输出的元素,而 判断总共有多少个元素是不反复的

基数是什么:是一种数据集,去反复后的数据的个数。

如果有这样一个需要:统计一个有亿万级并发的网站上面,每天拜访的用户数(UV 数),要依据用户去重,咱们会有以下几种统计办法:
1)mysql
2)HashSet
以上两种办法,随着元素内容的一直减少,数据量越来越宏大,难以管控,而且存的艰巨,取地艰巨。

3)hyperloglog
后面也说过,它不保留元素的具体数据,只是进行不反复的基数统计,而且应用固定的空间。

留神:
hyperloglog 有误差,就义准确率来换取空间,误差仅仅只是 0.81% 左右。

根本命令:
redis:

pfadd key element // 增加元素
pfcount key // 基数统计
pfmerge new_key key1 key2 // 合并两个 hyperloglog

java:

stringRedisTemplate.opsForHyperLogLog().add()

5.GEO 类型及其利用
GEO 是什么:
互联网利用中,定位系统用的越来越多,比方打车,左近的店铺等等。在咱们还没有学习 GEO 之前,咱们都是用 SQL 进行查找的:

select taxi from position where x0-r 

这样做呈现的问题:
1) 查问性能问题 ,如果并发高,这张表便会始终更新,因为司机的地位是一直变动的。
2)这个查问时一个 矩形拜访 ,不是圆周形
3) 精准度问题,地球是一个圆球,会产生误差。

这个时候,GEO 就诞生了!帮咱们解决两点之间的间隔,范畴查找等问题。

redis 命令:

GEOADD  多个经度 (longitude)、纬度(latitude)、地位名称(member) 增加到指定的 key 中
GEOPOS  从键外面返回所有给定地位元素的地位(经度和纬度)GEODIST 返回两个给定地位之间的间隔。GEORADIUS 以给定的经纬度为核心,返回与核心的间隔不超过给定最大间隔的所有地位元素。GEORADIUSBYMEMBER 跟 GEORADIUS 相似
GEOHASH 返回一个或多个地位元素的 Geohash 示意

增加:

获取地位:

获取两个点的间隔:

范畴查问:

java:

stringRedisTemplate.opsForGeo().add();

6. 总结

明天学习了 redis 的新类型
bitmap 位图统计
hyperloglgo 去重基数统计
GEO 地位统计

退出移动版