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

2 Redis的高级数据结构

1、Bitmaps

首先,最经典的应用场景就是用户日活的统计,比如说签到等。
字段串:“dbydc”,根据对应的ASCII表,最后可以得到对应的二进制,如图所示
在这里插入图片描述
在这里插入图片描述
一个字符占8位(bit),不够就在最高位补 0(零),我们只需设置值为 1 的位。如图所示,二进制最高位是在最左边的,但数组索引最高位是在最右边。字符“d”只需在偏移量(offset,即数组索引)第 1、2、5 位设置 1 ;字符“b”只需在偏移量(offset,即数组索引)第 9、10、14 位设置 1 ;字符“y”只需在偏移量(offset,即数组索引)第 17、18、19、20、23 位设置 1 ;字符“d”只需在偏移量(offset,即数组索引)第 25、26、29 位设置 1 ;字符“c”只需在偏移量(offset,即数组索引)第 33、34、38、39 位设置 1 。
在这里插入图片描述

  1. 字符“d”存储(第 1、2、5 位设置1)
127.0.0.1:6379> setbit mykey 1 1(integer) 0
127.0.0.1:6379> setbit mykey 2 1(integer) 0
127.0.0.1:6379> setbit mykey 5 1(integer) 0
  1. 字符“b”存储(第 9、10、14 位设置1)
127.0.0.1:6379> setbit mykey 9 1
(integer) 0
127.0.0.1:6379> setbit mykey 10 1
(integer) 0
127.0.0.1:6379> setbit mykey 14 1
(integer) 0
  1. 字符“y”存储(第 17、18、19、20、23 位设置1)
  127.0.0.1:6379> setbit mykey 17 1(integer) 0127.0.0.1:6379> setbit mykey 18 1(integer) 0127.0.0.1:6379> setbit mykey 19 1(integer) 0127.0.0.1:6379> setbit mykey 20 1(integer) 0127.0.0.1:6379> setbit mykey 23 1(integer) 0
  1. 字符“d”存储(第 25、26、29 位设置1)
  127.0.0.1:6379> setbit mykey 25 1(integer) 0127.0.0.1:6379> setbit mykey 26 1(integer) 0127.0.0.1:6379> setbit mykey 29 1(integer) 0
  1. 字符“c”存储(第 33、34、38、39 位设置1)
  127.0.0.1:6379> setbit mykey 33 1(integer) 0127.0.0.1:6379> setbit mykey 34 1(integer) 0127.0.0.1:6379> setbit mykey 38 1(integer) 0127.0.0.1:6379> setbit mykey 39 1(integer) 0
  1. 获取键 mykey 对应的值
127.0.0.1:6379> get mykey“dbydc”

所以,我们在统计某位用户系统签到的时候,sign=1就是签到,0就是没有签到。

setbit 2023-jack-sign 1 1		//第一日签到
setbit 2023-jack-sign 2 0		//第二日未签到
setbit 2023-jack-sign 3 1		//第三日签到
...

统计出全年的签到次数:

 127.0.0.1:6379> BITCOUNT 2023-jack-sign 0 3  #统计1的数量
(integer) 2
2、布隆过滤器与Bitmaps

1970 年布隆提出了一种布隆过滤器的算法,目的是用来判断一个元素是否在一个集合中
算法由一个二进制数组和一个 Hash 算法组成
在这里插入图片描述
布隆过滤器的误判问题?
在这里插入图片描述
布隆过滤器的使用场景之缓存穿透
当用户查询的时候,缓存中的key不存在,则进行数据库的大量查询导致的数据库的崩溃场景.
在这里插入图片描述
解决思路:在查询的时候快速判断查询的用户是否存在有效的缓存数据,布隆过滤器。
在这里插入图片描述
解决缓存穿透的问题,所以在用户查询缓存没有命中的时候,需要兜底去查询数据库,因此redis是无法完全取代数据库的。

3、布隆过滤器的代码实现
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.nengxing</groupId><artifactId>redis-base</artifactId><version>0.0.1-SNAPSHOT</version><name>redis-base</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.6.3</version></dependency><!--引入Redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-redis</artifactId><version>1.4.2.RELEASE</version></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.3</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1-jre</version></dependency><dependency><!-- this is needed or IntelliJ gives junit.jar or junit-platform-launcher:1.3.2 not found errors --><groupId>org.junit.platform</groupId><artifactId>junit-platform-launcher</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

布隆过滤器核心代码

import com.google.common.hash.Funnels;
import com.google.common.hash.Hashing;
import com.google.common.primitives.Longs;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;import java.nio.charset.Charset;/*仿Google的布隆过滤器实现,基于redis支持分布式*/
public class RedisBloomFilter {public final static String RS_BF_NS = "rbf:";private int numApproxElements; /*预估元素数量,在配合使用数组的时候使用*/private double fpp; /*布隆过滤器所能接受的最大误差*/private int numHashFunctions; /*自动计算的hash函数个数*/private int bitmapLength; /*自动计算的最优Bitmap长度*/@Autowiredprivate JedisPool jedisPool;/*** 构造布隆过滤器* @param numApproxElements 预估元素数量* @param fpp 可接受的最大误差* @return*/public RedisBloomFilter init(int numApproxElements,double fpp){this.numApproxElements = numApproxElements;this.fpp = fpp;/*位数组的长度*///this.bitmapLength = (int) (-numApproxElements*Math.log(fpp)/(Math.log(2)*Math.log(2)));this.bitmapLength=128;/*算hash函数个数,此处为了简便直接写死*///this.numHashFunctions = Math.max(1, (int) Math.round((double) bitmapLength / numApproxElements * Math.log(2)));this.numHashFunctions=2;return  this;}/*** 计算一个元素值哈希后映射到Bitmap的哪些bit上* 用两个hash函数来模拟多个hash函数的情况*     * @param element 元素值* @return bit下标的数组*/private long[] getBitIndices(String element){long[] indices = new long[numHashFunctions];/*会把传入的字符串转为一个128位的hash值,并且转化为一个byte数组*/byte[] bytes = Hashing.murmur3_128().hashObject(element, Funnels.stringFunnel(Charset.forName("UTF-8"))).asBytes();long hash1 = Longs.fromBytes(bytes[7],bytes[6],bytes[5],bytes[4],bytes[3],bytes[2],bytes[1],bytes[0]);long hash2 = Longs.fromBytes(bytes[15],bytes[14],bytes[13],bytes[12],bytes[11],bytes[10],bytes[9],bytes[8]);/*用这两个hash值来模拟多个函数产生的值*/long combinedHash = hash1;for(int i=0;i<numHashFunctions;i++){//数组下标indices[i]=(combinedHash&Long.MAX_VALUE) % bitmapLength;combinedHash = combinedHash + hash2;}System.out.print(element+"数组下标");for(long index:indices){System.out.print(index+",");}System.out.println(" ");return indices;}/*** 插入元素** @param key       原始Redis键,会自动加上前缀* @param element   元素值,字符串类型* @param expireSec 过期时间(秒)*/public void insert(String key, String element, int expireSec) {if (key == null || element == null) {throw new RuntimeException("键值均不能为空");}//为了与redis中的其他key进行区别String actualKey = RS_BF_NS.concat(key);try (Jedis jedis = jedisPool.getResource()) {try (Pipeline pipeline = jedis.pipelined()) {for (long index : getBitIndices(element)) {pipeline.setbit(actualKey, index, true);}pipeline.syncAndReturnAll();} catch (Exception ex) {ex.printStackTrace();}jedis.expire(actualKey, expireSec);}}/*** 检查元素在集合中是否(可能)存在** @param key     原始Redis键,会自动加上前缀* @param element 元素值,字符串类型*/public boolean mayExist(String key, String element) {if (key == null || element == null) {throw new RuntimeException("键值均不能为空");}String actualKey = RS_BF_NS.concat(key);boolean result = false;try (Jedis jedis = jedisPool.getResource()) {try (Pipeline pipeline = jedis.pipelined()) {for (long index : getBitIndices(element)) {pipeline.getbit(actualKey, index);}result = !pipeline.syncAndReturnAll().contains(false);} catch (Exception ex) {ex.printStackTrace();}}return result;}@Overridepublic String toString() {return "RedisBloomFilter{" +"numApproxElements=" + numApproxElements +", fpp=" + fpp +", numHashFunctions=" + numHashFunctions +", bitmapLength=" + bitmapLength +'}';}
}

判断不在的,一定不在,判断在的情况,大概率都不在,除非存在一定的hash冲突
测试:

@SpringBootTest
public class TestRedisBloomFilter {private static final int DAY_SEC = 60 * 60 * 24;@Autowiredprivate RedisBloomFilter redisBloomFilter;@Testpublic void testInsert() throws Exception {// System.out.println(redisBloomFilter);redisBloomFilter.insert("bloom:user", "20210001", DAY_SEC);redisBloomFilter.insert("bloom:user", "20210002", DAY_SEC);redisBloomFilter.insert("bloom:user", "20210003", DAY_SEC);redisBloomFilter.insert("bloom:user", "20210004", DAY_SEC);redisBloomFilter.insert("bloom:user", "20210005", DAY_SEC);}@Testpublic void testMayExist() throws Exception {System.out.println(redisBloomFilter.mayExist("bloom:user", "20210001"));System.out.println(redisBloomFilter.mayExist("bloom:user", "20210002"));System.out.println(redisBloomFilter.mayExist("bloom:user", "20210003"));System.out.println(redisBloomFilter.mayExist("bloom:user", "20211001"));}}
Guava的布隆
import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;/*单机下无Redis的布隆过滤器:使用Google的Guava的BloomFilter*/
public class GuavaBF {public static void main(String[] args) {long expectedInsertions = 100000;double fpp = 0.00005;BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), expectedInsertions, fpp);bloomFilter.put("10081");bloomFilter.put("10082");bloomFilter.put("10083");bloomFilter.put("10084");bloomFilter.put("10085");bloomFilter.put("10086");System.out.println("123456:BF--"+bloomFilter.mightContain("123456"));//falseSystem.out.println("10086:BF--"+bloomFilter.mightContain("10086"));//trueSystem.out.println("10084:BF--"+bloomFilter.mightContain("10084"));//true}
}
基于Redisson的实现
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/*Redisson底层基于位图实现了一个布隆过滤器,使用非常方便*/
public class RedissonBF {public static void main(String[] args) {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");//构造RedissonRedissonClient redisson = Redisson.create(config);RBloomFilter<String> bloomFilter = redisson.getBloomFilter("phoneList");//初始化布隆过滤器:预计元素为100000000L,误差率为3%bloomFilter.tryInit(100000000L,0.03);//将号码10081~10086插入到布隆过滤器中bloomFilter.add("10081");bloomFilter.add("10082");bloomFilter.add("10083");bloomFilter.add("10084");bloomFilter.add("10085");bloomFilter.add("10086");//判断下面号码是否在布隆过滤器中System.out.println("123456:BF--"+bloomFilter.contains("123456"));//falseSystem.out.println("10086:BF--"+bloomFilter.contains("10086"));//trueSystem.out.println("10084:BF--"+bloomFilter.contains("10084"));//true}
}

布隆过滤器的实现:
Redis + Redisson
Redis + 自主实现
无Redis + Guava

相关文章:

2 Redis的高级数据结构

1、Bitmaps 首先&#xff0c;最经典的应用场景就是用户日活的统计&#xff0c;比如说签到等。 字段串&#xff1a;“dbydc”&#xff0c;根据对应的ASCII表&#xff0c;最后可以得到对应的二进制&#xff0c;如图所示 一个字符占8位&#xff08;bit&#xff09;&#xff0c;…...

Hive默认分割符、存储格式与数据压缩

目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

update_engine-FilesystemVerifierAction和PostinstallRunnerAction

在介绍完了DownloadAction之后&#xff0c;还剩下FilesystemVerifierAction和PostinstallRunnerAction&#xff0c;下面开始对其进行分析。 FilesystemVerifierAction 在数据下载完成后&#xff0c;在DownloadAction中会切换到FilesystemVerifierAction void DownloadAction:…...

深度学习乳腺癌分类 计算机竞赛

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…...

【Python百宝箱】掌握Python Web开发三剑客:Flask、Django、FastAPI一网打尽

前言 在当今互联网时代&#xff0c;Web应用的开发变得愈发重要和复杂。选择一个合适的Web框架&#xff0c;掌握安全性与认证、数据库与ORM库、前端框架与交互、测试与调试工具等关键知识点&#xff0c;是每个Web开发者都必须面对的挑战。本文将带你深入了解三个流行的Python W…...

【人工智能时代的刑法体系与责任主体概述】

第一节&#xff1a;引言 随着科技的快速发展&#xff0c;人工智能 (Artificial Intelligence, AI) 正日益成为我们生活中不可或缺的一部分。从自动驾驶汽车到语音助手&#xff0c;从智能家居到金融机器人&#xff0c;AI 的广泛应用正不断改变着我们的生活方式和社会结构。然而…...

透视maven打包编译正常,intellj idea编译失败问题的本质

前言 maven多模块类型的项目&#xff0c;在Java的中大型应用中非常常见&#xff0c; 在 module 很多的情况&#xff0c;经常会出现各种各样的编辑依赖错误问题&#xff0c;今天记录一种比较常见的 case &#xff1a; A 子模块依赖 B 子模块&#xff0c;在 Terminal 上终端上 …...

npm报错

npm报错 npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution. npm ERR! npm ERR! npm ERR! For a full report s…...

【FFmpeg实战】ffmpeg播放器-音视频解码流程

音视频介绍 音视频解码流程 FFmpeg解码的数据结构说明 AVFormatContext&#xff1a;封装格式上下文结构体,全局结构体,保存了视频文件封装格式相关信息AVInputFormat&#xff1a;每种封装格式&#xff0c;对应一个该结构体AVStream[0]&#xff1a;视频文件中每个视频&#xff…...

基于SSM的高校毕业选题管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

一个简单的Oracle Redaction实验

本实验包含了&#xff1a; 简单的Oracle Redaction演示针对指定用户的Redaction 实验环境 假设有一个19c多租户数据库&#xff0c;PDB名为orclpdb1。 我们将在orclpdb1中建立2个用户&#xff1a; redact_user: redact管理员schema_user: schema用户 基础实验 首先进入数…...

getchar函数的功能有哪些

getchar函数是C语言标准库中的一个函数&#xff0c;主要用于从标准输入&#xff08;通常是键盘&#xff09;获取一个字符。它的功能包括&#xff1a; 从标准输入获取一个字符&#xff1a;getchar函数会等待用户输入一个字符&#xff0c;然后将其返回给程序。可以通过控制台输入…...

信息机房监控系统(动环辅助监控系统)

信息机房监控系统是一个综合性的系统&#xff0c;用于对机房的所有设备及其环境进行集中监控和管理。这种系统主要针对机房的各个子系统进行监控&#xff0c;包括动力系统、环境系统、消防系统、保安系统、网络系统等。 依托电易云-智慧电力物联网&#xff0c;以下是信息机房监…...

最强英文开源模型Llama2架构与技术细节探秘

prerequisite: 最强英文开源模型LLaMA架构探秘&#xff0c;从原理到源码 Llama2 Meta AI于2023年7月19日宣布开源LLaMA模型的二代版本Llama2&#xff0c;并在原来基础上允许免费用于研究和商用。 作为LLaMA的延续和升级&#xff0c;Llama2的训练数据扩充了40%&#xff0c;达到…...

编程刷题网站以及实用型网站推荐

1、牛客网在线编程 牛客网在线编程https://www.nowcoder.com/exam/oj?page1&tab%E8%AF%AD%E6%B3%95%E7%AF%87&topicId220 2、力扣 力扣https://leetcode.cn/problemset/all/ 3、练码 练码https://www.lintcode.com/ 4、PTA | 程序设计类实验辅助教学平台 PTA | 程…...

基于STC12C5A60S2系列1T 8051单片机的SPI总线器件数模芯片TLC5615实现数模转换应用

基于STC12C5A60S2系列1T 8051单片的SPI总线器件数模芯片TLC5615实现数模转换应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍SPI总线器件数模芯片TLC5615介绍通过按…...

【并发编程】Synchronized的使用

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…...

【Python】Python基础

文章目录 一、字面值常量和表达式二、变量2.1 定义变量2.2 变量的命名规则2.3 变量的类型2.4 不同类型大小2.5 动态类型 三、注释四、输入与输出五、运算符5.1 算术运算符5.2 关系运算符5.3 逻辑运算符5.4 赋值运算符 一、字面值常量和表达式 print(1 2 * 3) # 7 print(1 2 …...

gitlab环境准备

1.准备环境 gitlab只支持linux系统&#xff0c;本人在虚拟机下使用Ubuntu作为操作系统&#xff0c;gitlab镜像要使用和操作系统版本对应的版本&#xff0c;(ubuntu18.04,gitlab-ce_13.2.3-ce.0_amd64 .deb) book100ask:/$ lsb_release -a No LSB modules are available. Dist…...

Apache Doris (五十四): Doris Join类型 - Bucket Shuffle Join

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...