目录
redis9大数据类型
类型介绍
- string类型 setnx(分布式锁)
- hash类型 京东早期购物车用过
- list类型 双端链表结构 可以应用于订阅号消息 商品评论列表等等
- set类型 可以用来做随机抽奖,随机弹出元素不删除或者出一个删除一个 集合运算:
- sdiff 集合的差集运算a-b 属于a但是不属于b的共同拥有的元素构成的集合
- sinter 属于a同时也属于b的共同拥有的元素构成的集合
- sunion 属于a或者属于b的元素合并后的集合
- zset类型 主要用作排行榜等
- zrange获取元素的排名 从小到大
- zrevrange获取元素的排名 从大到小
- zrangebyscope根据分数大小获取元素 从小到大
- zrevrangebyscope根据分数大小获取元素 从大到小
- bitmap新类型 位图,本质上是数组,由多个二进制位组成,每个二进制位都对应一个偏移量,最大支持2的32次方,极大的节约了存储空间
- HyPerLogLog新类型 去重统计功能的基数估计算法(可以用来计算UV)
- GEO新类型 地理位置的处理
名词介绍
- 什么是uv:
unique visitor,独立访客,一般理解为客户端ip(需要考虑去重) - 什么是pv:
page view,页面浏览量 不需要去重 - 什么是dau:
daily active user 日活跃用户量(反应系统的运营情况 正常是要去重的) - 什么是mau:
monthly active user 月活跃用户量
亿级系统常用的统计类型
必须存的进,取得快,能多维度统计
- 聚合统计:统计多个集合元素的聚合结果 类似set的集合运算等等
- 排序统计:用zset
- 二值统计:用bitmap
- 基数统计:统计一个集合中不重复元素的个数 去重求和
set类型实用案例
微信小程序抽奖
微信朋友圈点赞
好友关注社交关系
- 共同关注的人:用set的集合运算取交集
- 我关注的人也关注了他
qq推荐可能认识的人
取差集(算法可能更加复杂,先看差集再看交集)
zset类型实用案例
根据商品销售对商品进行排序显示或者热搜
list做排序的坑
bitmap详细介绍
基本命令
命令 | 作用 | 时间复杂度 |
---|---|---|
setbit key offset val | 指定key的值的第offset赋值val | O(1) |
getbit key offset | 获取指定key的第offset位 | O(1) |
bitcount key start end | 返回指定key中[start,end]中为1的数量 | O(n) |
bitop operation destkey key | 对不同的二进制存储数据进行位运算(and,or,not,xor) | O(n) |
使用场景
- 用户签到统计
- 用户月活统计等等
底层编码说明,get命令如何操作
用get命令获取bitmap的key 实质是去拿二进制的ascii编码的对应值
实际上他是用String类型作为底层数据结构实现的一种统计二值状态的数据类型(执行type命令返回string类型)
HyPerLogLog详细解析
概率算法
HyPerLogLog通过牺牲准确率来换取空间,对于不要求绝对准确率的场景下可以使用,因为概率算法不直接存储数据本身.通过一定的概率统计方法预估基数值,同时保证误差在一定范围内,由于又不存储数据故此可以大大的节约内存 他本质上属于一种概率算法的实现
误差仅仅只是0.81%左右 redis之父的解释
经典面试题:为什么redis的最大槽数是16384个
redis集群并没有使用一致性hash而是引入了哈希槽的概念.redis集群有16384个哈希槽,每个key通过crc16校验后对16384取模来决定放置到哪个槽中,集群的每个节点负责一部分hash槽,但是为什么哈希槽的数量是16384(2的14次方)个呢?
crc16算法产生的hash值有16bit,该算法可以产生65536个值,那为什么不用65536而是16384呢?
- 如果槽位为65536,发送心跳信息的消息头达到8kb,发送的心跳包过于庞大,在消息头中最占空间的是myslots[cluster_slots/8].当槽位为65536时,这块的大小是:65536/8/1024=8kb,因为每秒钟redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping的消息头太大了,浪费带宽
- redis集群主节点数量基本不可能超过1000个.集群节点越多,心跳包的消息体内携带的数据越多,如果节点超过1000个,也会导致网络拥堵,因此redis的作者不建议redis cluster节点数量超过1000个,那么对于节点数1000以内的redis cluster集群,16384个槽位就够用了
- 槽位越小,节点少的情况下,压缩比高,容易传输,redis的主节点的配置信息中他所负责的哈希槽是通过bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots/N很高的话(N代表节点数),bitmap的压缩率就很低.如果节点数很少,并且哈希槽数量多的话,bitmap的压缩率就很低,所以哈希槽也不宜设置的太大.
基本命令
命令 | 作用 |
---|---|
pfadd key element | 将所有元素添加到key中 |
pfcount key | 统计key的估算值(不精确) |
pgmerge new_key key1 key2 | 合并key至新key |
实现原理
在redis里面,每个hyperLogLog键只需要花费12kb内存,就可以计算接近2的64次方个不同元素的基数,这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比.
但是,因为hyperLogLog只会根据输入元素来计算基数,而不会存储输入元素本身,所以hyperLogLog不能像集合那样,返回输入的各个元素.
为什么是12kb大小
每个桶取6位, 16384*6/8/1024=12kb 每个桶有6位,最大值全部都是1,值就是63
GEO详细介绍
核心思路
核心思想就是将球体转换为平面,区块转换为一个点
主要分为三个步骤
- 将三维的地球转换为二维的坐标
- 再将二维的坐标转换为一维的点块
- 最后把一维的点块转换为二进制在通过base32编码
基本命令
命令 | 作用 |
---|---|
geoadd | 多个经度(longitude),纬度(latitude),位置名称(member)添加到指定的key |
geopos | 从键里面返回所有给定位置元素的位置(经度和纬度) |
geodist | 返回两个给定位置之间的距离 |
georadius | 以给定的经纬度为中心,返回与中心距离不超过给定最大距离的所有位置信息 |
georadiusbymember | 跟georadius类似 |
geohash | 返回一个或者多个位置元素的geohash表示 |
georadius详细用法
含义为以给定的经纬度为中心,返回键包含的位置元素中,与中心的距离不超过给定最大距离的所有位置元素((最常用的也是他,可以用做返回半径范围内的酒店或者交友信息等等))
georadius city 116.418017 39.914402 10 km withdist withcoord count 10 withhash desc
- withdist : 再返回位置元素的同时,将位置元素与中心之间的距离也一并返回.距离的单位和用户给定的范围单位保持一致
- withcoord : 将位置元素的经度和纬度也一并返回
- withhash : 以52位有符号整数的形式,返回位置元素经过原始geohash编码的有序集合分值,这个选项主要用于底层应用或者调试,实际中的作用不大
- count desc : 限定返回的记录数并排序
georadiusbymember
他就是把经纬度换成 具体的地址名称