Redis的bitmap使用不当,我内存爆了

news2025/1/27 12:35:43

背景

最近发现Redis的内存持续暴涨, 涨的有点吓人,机器都快扛不住了,不得不进行Redis内存可视化分析,发现大量的String类型的大key

经分析,最近上线了页面UV的统计,那目前如何做的呢?

  1. 通过访客的IP地址来标识和追踪访客。当一个访问者首次访问网站时,服务器会记录其IP地址,并将其计算为一个UV。随后,如果同一IP地址再次访问网站,服务器将不会将其计算为一个UV。
  2. 将IP地址转换为整数,用位图(Bitmap)进行存储IP,实现UV的统计

这方案看上去没啥问题,也达到了去重的效果,统计也比较精确,内存占用率也低(bitmap优势就是内存占用率低),那为什么实际内存占用的这么夸张呢?我接着继续分析。

IP4

IP4介绍

目前的全球因特网所采用的协议族是TCP/IP协议族。IP是TCP/IP协议族中网络层的协议,是TCP/IP协议族的核心协议。IP协议定义了一种地址编码,称为IP地址,它是网络中网络段、网络设备接口、主机的编码,它并不是一种物理地址,而是逻辑地址,即地址是可以被分配、并且非固定、可修改的。

IPv4,是互联网协议(Internet Protocol,IP)的第四版,也是第一个被广泛使用,构成现今互联网技术的基石的协议。1981年 Jon Postel 在RFC791中定义了IP,IP可以运行在各种各样的底层网络上,比如端对端的串行数据链路、卫星链路等等。局域网中最常用的是以太网。

IPv4的下一个版本就是IPv6,IPv6正处在不断发展和完善的过程中,它在不久的将来将取代目前被广泛使用的IPv4。

ip4构成

IP地址有是一个32位的二进制数逻辑地址。因此,除了全0,拥有2的32次方-1个地址。全0地址用来表示一个无效的,未知的,或者不可用的目标。

为了方便使用,把这32位二进制数分成八位一组,被称为八位组(octet)。每个八位组书写时用点分十进制的格式标识。每个八位组取值为0000000011111111(二进制数),使用十进制数表示则值为0255。

二进制与十进制的转化非常简单,用二进制数的每一位乘以2的N次方,N是相应的位,从低位到高位以0次方开始,将二进制是1的每位结果相加得到的就是相应的十进制数。

IP地址分类

IP地址(0.0.0.0——255.255.255.254)分类:

A类

0.0.0.0—127.255.255.255 (其中私有:10.0.0.0—10.255.255.255,保留:0.0.0.0,127.0.0.0—127.255.255.255)

B类

128.0.0.1—191.255.255.254(其中私有:172.16.0.0—172.31.255.255,保留:169.254.0.0-169.254.255.255,191.255.255.255是广播地址,不能分配)

C类:

192.0.0.1—223.255.255.254(其中:私有:192.168.0.0—192.168.255.255)

D类

224.0.0.1—239.255.255.254

E类

240.0.0.1—255.255.255.254

什么是公网IP(外网IP)

公网IP就是除了保留IP地址以外的IP地址,可以与Internet上的其他计算机随意互相访问。我们通常所说的IP地址,其实就是指的公网IP。互联网上的每台计算机都有一个独立的IP地址,该IP地址唯一确定互联网上的一台计算机。

IP如何转为整数

把一个IPv4地址的每段可以看成是一个0-255的整数,先把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成一个长整数。

以10.0.3.193这个IP地址为例

每段数字相对应的二进制数
1000001010
000000000
300000011
19311000001

组合起来即为:00001010 00000000 00000011 11000001,转换为十进制数就是:167773121,所以10.0.3.193这个IPv4地址转换为Int数字就是167773121。

得到数字 167773121,作为bitmap 的偏移量

BitMap

BitMap可以看下如何统计百万用户在线状态-bitmap这篇文章,有详细的介绍,这里就简单分析下:

BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。

在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量

位图不是实际的数据类型,而是在 String 类型上定义的一组面向位的操作,将其视为位向量。由于字符串是二进制安全 blob,其最大长度为 512 MB,因此它们适合设置最多 2^32 个不同位。

例子: 10.0.3.193 ****这个IP访问了页面page1

10.0.3.193 转换为数字167773121,167773121作为bitmap 的偏移量,值设置为1


setbit uv:page1 167773121 1
# 统计

内存分析

页面page1,第一次被10.0.3.193 访问,进行记录,偏移量是167773121

1Byte(Byte 字节) = 8Bit

167773121/8/1024/1024=20MB

一次就分配了20mb的内存空间,前面的空间就造成了浪费,使用都是后面的位

如果IP是224开头,比如:224.1.2.1,转为数字3758162433

3758162433/8/1024/1024=448MB

一次就分配448mb,这样的统计页面如果有上万个,我们的资源根本没法承受,想想都可怕

如何优化呢?分段统计

分段统计

IPv4地址是一个32位的二进制数,每8位作为一段,分为四段进行储存,比如:10.255.1.12分割,如图:

# 第一段
setbit uv:page1:seg1 10 1
# 第二段
setbit uv:page1:seg2 255 1
# 第三段
setbit uv:page1:seg3 1 1
# 第四段
setbit uv:page1:seg4 12 1

最大偏移量值是255位,四段占用内存:4*255/8/1024=0.12kb

假设10w个页面进行统计,10000*0.12kb=121mb ,最大内存也只占用121mb。统计的页面越多,效果也是明显。不过这里有个问题,都分段了,那如果统计这个页面的uv呢,没分段之前,我们可以

bitcount uv:page1

分段之后,

# 第一段
bitcount uv:page1:seg1 
# 第二段
bitcount uv:page1:seg2 
# 第三段
bitcount uv:page1:seg3 
# 第四段
bitcount uv:page1:seg4 

统计分段后的四个key,然后相加吗,明显不对,那怎么办呢?

# 第一段
setbit uv:page1:seg1 10 1
# 第二段
setbit uv:page1:seg2 255 1
# 第三段
setbit uv:page1:seg3 1 1
# 第四段
setbit uv:page1:seg4 12 1
# 记录UV,上面四个只要有一个返回0,说明是一个新的IP,那就加1
INCR uv:page1

#统计uv
get uv:page1

使用Jedis客户端代码实现

 public static void main(String[] args) {
        Jedis jedis = new Jedis("10.1.250.157", 6379);
        jedis.auth("google00");
        jedis.del("ip");
        //添加四个IP统计uv,有一个是重复的,访问页面page1
        List<String> ipList = new ArrayList<>();
        ipList.add("10.1.255.10");
        ipList.add("255.1.255.10");
        ipList.add("10.1.195.10");
        ipList.add("10.1.255.10");
        for (String ip : ipList) {
            String[] ips = ip.split("\.");

            boolean seg1 = jedis.setbit("uv:page1:seg1",Long.valueOf(ips[0]).longValue(),true);
            boolean seg2 = jedis.setbit("uv:page1:seg2",Long.valueOf(ips[1]).longValue(),true);
            boolean seg3 = jedis.setbit("uv:page1:seg3",Long.valueOf(ips[2]).longValue(),true);
            boolean seg4 = jedis.setbit("uv:page1:seg4",Long.valueOf(ips[3]).longValue(),true);
            if (seg1&&seg2&&seg3&seg4){
                System.out.println(ip+"已访问过");
            }else {
                jedis.incr("uv:page1");
            }

        }
        String uv = jedis.get("uv:page1");
        System.out.println("页面page1的UV为:"+uv);

    }

结果:

10.1.255.10已访问过
页面page1的UV为:3

小结

bitmap最大的优势是节约内存空间,但是在使用的时候,需要根据实际的场景分析,上面的例子,就是没考虑偏移量的浪费。好多时候,理论跟实际差距还是有的,多实践。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1426935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

151基于matlab的齿轮-轴-轴承系统的含间隙非线性动力学模型

基于matlab的齿轮-轴-轴承系统的含间隙非线性动力学模型&#xff0c;根据牛顿第二定律&#xff0c;建立齿轮系统啮合的非线性动力学方程&#xff0c;同时也主要应用修正Capone模型的滑动轴承无量纲化雷诺方程&#xff0c;利用这些方程推到公式建模&#xff1b;用MATLAB求解画出…

Python中使用HTTP代理进行网络请求:轻松玩转网络世界的“魔法门“

嘿&#xff0c;小伙伴们&#xff01;今天我们来聊一聊Python中一个超级有用的功能——使用HTTP代理进行网络请求。这不是在念咒语&#xff0c;而是开启网络世界的"魔法门"。 首先&#xff0c;让我们了解一下什么是HTTP代理。简单来说&#xff0c;HTTP代理就是一个中…

影响计算机性能的前10大因素,看你到底关注了几个

计算机性能被定义为计算机系统在给定时间内完成的有价值的工作量。它是根据执行程序或指令的效率、准确性和速度来估计的。因此,当你想知道为什么你的设备速度慢,而其他时候它一直在有效工作时,有几个因素可能会导致这个问题。 其中一些包括CPU、RAM大小、硬盘空间、速度、…

OJ刷题:《剑指offer》之左旋字符串!

目录 1.题目描述 2.方法一&#xff08;元素一一挪&#xff09; 2.1算法解析 2.2代码实现 3.方法二&#xff08;三次逆置&#xff09; 3.1算法解析 3.2代码实现 4.方法三&#xff08;库方法&#xff09; 4.1算法解析 4.2代码实现 5.完结散花 创作不易&#xff0c;宝子…

做研究系列:快速总结大量研究论文的成果

快速总结大量研究论文的成果时&#xff0c;可以遵循以下步骤和策略来提高效率并确保准确性&#xff1a; 系统性筛选与阅读摘要&#xff1a; 首先根据研究主题或关键词筛选出相关论文。快速阅读每篇论文的摘要&#xff0c;了解其主要目的、方法、关键结果和结论。 构建大纲与分类…

EtherCAT FP介绍系列文章—UDP gateway

EtherCAT主站上的Mailbox Gateway功能&#xff0c;可以用于将EtherCAT mailbox相关协议从外部设备的工具通过邮箱网关路由到EtherCAT从站设备。在EtherCAT规范中定义的所有邮箱协议在此功能中都可用&#xff0c;例如CoE, FoE, VoE, SoE。 但是&#xff0c;这里特别注意的是Mai…

Elasticsearch-内存结构

ElasticSearch的内存从大的结构可以分堆内存&#xff08;On Heap&#xff09;和堆外内存&#xff08;Off Heap&#xff09;。Off Heap部分由Lucene进行管理。On Heap部分存在可GC部分和不可GC部分&#xff0c;可GC部分通过GC回收垃圾对象&#xff0c;从而释放内存。不可GC部分不…

英码科技携手昇腾共建算力底座:推出EA500I超强AI处理能力边缘计算盒子!

在数字经济浪潮中&#xff0c;算力已成为不可或缺的驱动力&#xff0c;为各行各业的数字化转型提供了强大的推动力。面对多元化和供需不平衡的挑战&#xff0c;需要实现从理论架构到软硬件实现的质的飞跃&#xff0c;以满足持续增长的算力需求&#xff0c;华为昇腾在这一方面展…

基于JAVA和Vue的宠物医院诊所商城论坛管理系统

摘要&#xff1a; 随着人们生活水平的提高&#xff0c;宠物逐渐成为家庭中不可或缺的成员。伴随着宠物行业的迅猛发展&#xff0c;宠物医疗服务需求也日益增长&#xff0c;传统的宠物医院管理模式已无法满足现代化、信息化的管理需求。因此&#xff0c;开发一款高效、智能的宠物…

ElasticSearch-IK分词器(elasticsearch插件)安装配置和ElasticSearch的Rest命令测试

四、IK分词器(elasticsearch插件) IK分词器&#xff1a;中文分词器 分词&#xff1a;即把一段中文或者别的划分成一个个的关键字&#xff0c;我们在搜索时候会把自己的信息进行分词&#xff0c;会把数据库中或者索引库中的数据进行分词&#xff0c;然后进行一一个匹配操作&…

Java密码校验(正则表达式):密码由这四种元素组成(数字、大写字母、小写字母、特殊字符),且必须包含全部四种元素;密码长度大于等于8个字符。

1. 需求 对用户密码的强度进行校验&#xff0c;要求用户密码达到一定的强度&#xff0c;符合安全性要求。 1.1. 基础版需求 密码必须由字母和数字组成&#xff08;同时包括数字和数字&#xff09;&#xff1b;密码长度大于等于8个字符。 1.2. 进阶版需求 密码由这四种元素…

【ARM Coresight 系列文章 8.1 - ARM Coresight 通过 APBIC arbiter】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 APBIC arbiter仲裁使用举例APBIC arbiter 在 SoC-600中,APBIC 是用来为 APB4 master 和 APB4 slave 提供 连接关系的组件。APB 是一种简单的总线协议,通常用于低带宽或低性能外设,如定时器、接口控制等。APBIC …

2024美赛数学建模C题思路分析 - 网球的动量

1 赛题 问题C&#xff1a;网球的动量 在2023年温布尔登绅士队的决赛中&#xff0c;20岁的西班牙新星卡洛斯阿尔卡拉兹击败了36岁的诺瓦克德约科维奇。这是德约科维奇自2013年以来首次在温布尔登公开赛失利&#xff0c;并结束了他在大满贯赛事中历史上最伟大的球员之一的非凡表…

Spring Cloud Config核心功能和原理解析

配置管理的前世今生 随着技术的发展&#xff0c;配置项管理变得越来越简单&#xff0c;尽管如今它只限于管理业务属性或者配置初始化参数等等&#xff0c;但是当年它可肩负着 Spring IOC 的光荣使命&#xff0c;风光无限。 想当年刚入行的时候还是 SSH&#xff08;Struts Sp…

【数据分享】1929-2023年全球站点的逐年最高气温数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2023年全球气象站…

22.云原生之GitLab CICD实战及解析【干货】

云原生专栏大纲 文章目录 准备工作gitlab-ci.yml流水线mven打包项目制作并推送镜像kaniko方式docker方式 部署到k8s验证执行情况 GitLab Runner k8s执行器工作流程注册配置kubernetes runnerkubernetes runner配置通过修改 Pod 规范为每个构建作业创建一个 PVC自定义卷装载持久…

负压自动放水器不如早来永成购

CWG&#xff0d;FY型负压自动放水器的结构与性能等参数 &#xff08;1&#xff09;结构 负压自动放水器主要由通大气阀1、负压平衡管2、托盘3、侧导向杆4、磁铁5、中心导向杆6、外筒7、放水阀保护罩8、放水阀9、导向座10、浮漂11、进水阀12等组成。 &#xff08;2&#xff09;性…

Quick BI中lod函数之lod_fixed

一、lod函数简介 LOD函数的全称是详细级别表达式&#xff08;Level Of Detail Expressisons&#xff09;。它主要是为了克服一些表达式之间计算颗粒度不一致的问题。比如&#xff0c;要计算第一季度各月销售收入占比&#xff0c;这里分子计算颗粒度为’月’&#xff0c;但是分…

UML---用例图,类图

用例图 用例图&#xff08;Use Case Diagram&#xff09;主要描述系统的功能需求和参与者与系统之间的交互。它是用户与系统交互的最简表示形式&#xff0c;展现了用户和与他相关的用例之间的关系。用例图被视为系统的蓝图&#xff0c;通过它&#xff0c;人们可以获知系统不同种…

【win】vscode无法使用ctrl+shift+p快捷键的解决方案

本文首发于 ❄️慕雪的寒舍 今天使用vscode的时候遇到的这个问题&#xff0c;明明快捷键设置的是ctrlshiftp&#xff0c;但是在电脑上怎么敲都敲不出来&#xff0c;因为用这个快捷键打开命令面板都习惯了&#xff0c;也不想换&#xff0c;就在找原因。 同时百度的时候还遇到了…