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

Redis HyperLogLog底层实现和Redis 7.0特性主从复制优化

文章目录

  • Redis HyperLogLog和Redis 7.0
    • hyperloglog
      • 基本使用
      • 基本原理
    • Redis7新特性

Redis HyperLogLog和Redis 7.0

hyperloglog

基本使用

基数:在一个数据集合中不重复元素的个数

redis hyperloglog 是用来做基数统计的算法。它可以利用少量内存进行大量数据的统计。它是有误差的,误差在0.81%。

应用场景就比如:统计网页的UV (页面访问量 一个人访问一个网站多次但还是算一个人)。

# hyperloglog它只有三个命令:pfadd、pfcount、pfmerge
# 添加元素 可以添加1个 也可以添加多个
127.0.0.1:6379> pfadd mykey a b c d e f g h i j k 
(integer) 1
# 查询这个集合的基数
127.0.0.1:6379> pfcount mykey
(integer) 11

# 再创建一个集合
127.0.0.1:6379> pfadd mykey2 i j k l m n o p
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 8

# 还可以把两个集合合并成一个新集合
127.0.0.1:6379> pfmerge mykey3 mykey mykey2
OK
127.0.0.1:6379> pfcount mykey3
(integer) 16



基本原理

HyperLogLog基于概率论中伯努利试验并结合了极大似然估算方法,并做了分桶优化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bETsA5J-1680006850723)(picture/Redis/9922)]

Hyperloglog底层采用的是调和平均数,不是采用的算术平均数。

采用平均数的方式就是: (1000 + 30000) / 2 = 15500

采用调和平均数的方式就是: 2/(1/1000 + 1/30000) ≈ 1935.484

可见调和平均数比平均数的好处就是不容易受到大的数值的影响,比平均数的效果是要更好的。

hyperloglog在redis启动时是占12KB内存大小,随着时间推移可能会有一点点的变化,redis会把这12KB的内存分为16384个桶(桶其实就是比较长的bit数组),也就是2^14次方,

hyperloglog首先会将要存的值进行hash运算转换为64位的二进制比特串,取低14位,就得到当前值应该放进哪个桶中。剩余的50位的数据就决定往桶中放入什么内容,从第14位开始往前数,找到第一个为1的比特位数,比如17位是1,那么就是从第14位开始往前数第3位是1,然后把这个3转换为二进制数存入桶中,相当于就是存了一个K。

各个桶中会求出自己的Kmax值,然后根据所有通的估计值求出调和平均数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugX4uwni-1680006850723)(picture/Redis/9923)]



Redis7新特性

提升了主从复制是性能

redis7版本以前主从复制是有两种:全量复制、增量复制。

当master节点执行一条更新命令时,它处理本机执行之外,还会往从库复制缓冲区(复制给从库)、复制积压区进行保存(将执行的命令做一个备份,slave断开连接重连时会用到)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q4BbWypW-1680006850724)(picture/Redis/image-20230328193950775.png)]

这种方式的问题是:

  • 会为每一个slave节点都创建一个从库复制缓冲区,那么仅仅为了主从复制这个功能就会消耗master节点比较大的内存空间,从库越多消耗的内存也越多
  • 在全量备份时会生成一个rdb文件,然后发送到从库复制缓冲区中再发送给salve1节点,如果这个时候再来一个slave节点,生成一个rdb文件是比较耗时的,Redis底层是让这些slave节点共用的同一份rdb文件,redis会把一个从库负责缓冲区中的内容拷贝到另一个从库负责缓存区,但这个容量可能几百MB或者个GB,那么就可能造成毫秒甚至是秒级单位中Redis无法响应客户端的请求,去做复制的事情去了
  • 我们可以在运行时设置复制积压缓冲区的大小,这样就会造成重新分配一块新的内存空间,然后将原来的数据拷贝到新的内存块中。

redis7版本就提出来共享从库复制缓冲区的优化点。将原来一整大块内存拆分为了很多小块内存(Block),使用链表的结构将多个block连接起来,每个block中还维护了一个变量refcount用来表示从库引用计数,各个从库的复制缓冲区都是读取的一块内存,只是移动指针表示各个从库读取到了哪一个位置。这样也就不存在了多个从库复制缓冲区进行数据复制的问题了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-35HD2wMa-1680006850724)(picture/Redis/image-20230328195838348.png)]

因为使用了链表,假如链表上的节点非常多,如果想要获取其中一个block,那么遍历起来会非常耗时,底层用来rax树的数据结构来优化,它和Trie树的区别是进行了压缩,如下所示是一个Trie数的结构,一个字母就是一个节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fldkW2cq-1680006850724)(picture/Redis/image-20230328201933629.png)]

而rax数如果此时某一个节点不会再分叉了,那么就把多个字母放在一个节点中,rax树其实就是压缩后的trie树。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIxhuNOC-1680006850724)(picture/Redis/image-20230328202054482.png)]

在Rax树中它其实不是按照一个字母来存放的,而是按照bit位来存放的。


http://www.kler.cn/a/5312.html

相关文章:

  • 无网络时自动切换备用网络环境
  • 缓存-Redis-常见问题-缓存击穿-永不过期+逻辑过期(全面 易理解)
  • 在 PhpStorm 中配置命令行直接运行 PHP 的步骤
  • 【OJ刷题】同向双指针问题
  • 【 算法设计与分析-回顾算法知识点】福建师范大学数学与计算机科学学院 2006 — 2007学年第二学期考试 A 卷
  • 基于YOLO5的机械臂视觉抓取实现
  • TC275-点亮属于AutoSAR的灯之MCAL配置
  • 【机器学习】线性回归
  • 【C语言督学训练营 第五天】数组字符串相关知识
  • Ceres 自动求导解析-从原理到实践
  • mysql主从(单主)同步原理
  • 信号集操作函数
  • Matbox V1.0.7更新预览与手册
  • TryHackMe-harder(boot2root)
  • ShaderGraph前言
  • English Learning - L2 语音作业打卡 舌边音 [r] [l] Day37 2023.3.29 周三
  • 你知道Python 最常用的 20 个包吗(按照使用频率排序)
  • Java 抽象类中构造方法的作用?如何理解?
  • JS和Jquery
  • 大屏使用dv-digital-flop定时刷新显示总人数
  • 一文实战 | RISC-V Linux入口地址2M预留内存优化
  • 如何在 Linux 上安装和使用 exa?
  • 二值mask转polygon/RLE (coco segment格式)
  • RSA解密-第十届Java研究生组E题
  • Leetcode: 236.二叉树的最近公共祖先
  • 医用超声检查设备