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

Redis Hash 介绍

Redis Hash 介绍

从基础命令、内部编码和使用场景三个维度分析如下:


一、基础命令

Redis Hash 提供了丰富的操作命令,适用于字段(field)级别的增删改查:

  1. 设置与修改

    • HSET:设置单个字段值(HSET key field value​)。

      # 存储用户信息(用户ID=1001)
      HSET user:1001 name "Alice" age 28 email "alice@example.com"  
      # 返回3(表示成功设置3个字段)
      
    • HSETNX:仅当字段不存在时设置值,避免覆盖。

      # 防止覆盖已存在的字段  
      HSETNX user:1001 email "new@example.com"  # 返回0(字段已存在,未修改)  
      HSETNX user:1001 address "New York"       # 返回1(新增字段)  
      
    • HINCRBY:对数值型字段进行增减操作(如计数器场景)。

      场景:计数器(库存、销量、点击量),支持原子增减,避免并发问题。

      # 商品ID=2001的库存增减  
      HINCRBY product:2001 stock -5  # 减少库存5(返回新值,如95)  
      HINCRBY product:2001 sales 10   # 增加销量10(返回新值,如150)  
      
  2. 查询与检索

    • HGET:获取单个字段值。

      HGET user:1001 name  # 返回"Alice"  
      
    • HMGET:批量获取多个字段值。

      HMGET user:1001 name age email  # 返回["Alice", "28", "alice@example.com"]  
      
    • HGETALL:获取所有字段及值(需谨慎使用,大数据量可能阻塞服务)。

      HGETALL user:1001  # 返回所有字段和值(适用于小规模数据)  
      
    • HKEYS/HVALS:分别获取所有字段名或值。

      HKEYS user:1001  # 返回["name", "age", "email", "address"]  
      HVALS user:1001  # 返回["Alice", "28", "alice@example.com", "New York"]  
      
  3. 删除与判断

    • HDEL:删除指定字段。

      场景:清理过期字段,例如用户注销后删除敏感信息。

    • HEXISTS:判断字段是否存在。

      场景:检查字段是否存在,例如权限校验或防止重复操作。

    • HLEN:统计字段数量。

      统计对象属性数量,例如监控购物车商品种类数。


二、内部编码

Redis Hash 根据数据规模和配置动态选择底层数据结构,以平衡性能与内存效率:

  1. ziplist(压缩列表)

    • 条件:当字段数 ≤ hash-max-ziplist-entries​(默认 512)且所有字段值 ≤ hash-max-ziplist-value​(默认 64 字节)时启用。
    • 特点:连续内存存储,无指针开销,内存利用率高,但插入/删除效率随数据量增长而下降。
  2. hashtable(哈希表)

    • 触发条件:超出 ziplist 配置限制时自动转换。
    • 特点:通过哈希表实现 O(1) 复杂度的读写操作,适合大规模数据,但内存占用较高。
  3. Redis 7.0 及以上版本已弃用 ziplist,改用 listpack 作为默认的紧凑数据结构。

    1. 数据结构设计对比

      特性ziplistlistpack
      存储结构连续内存块,元素通过prevlen​字段记录前一个元素的长度,形成隐式链表连续内存块,每个元素独立存储自身长度信息,无前后依赖。
      连锁更新风险存在:插入/删除元素时,可能触发后续元素的prevlen​字段更新,导致级联内存重分配。不存在:元素长度独立编码,无需依赖前驱元素,彻底避免连锁更新。
      内存布局通过prevlen​和encoding​字段实现变长编码。通过element-total-len​字段统一记录元素总长度,结构更简单。
      安全性易因prevlen​计算错误导致内存越界(历史漏洞)。长度信息自包含,访问更安全,减少内存越界风险。
    2. 性能与内存效率

      维度ziplistlistpack
      插入/删除效率平均 O(n),可能触发连锁更新(最坏 O(n^2))。平均 O(n),无连锁更新,性能更稳定。
      随机访问速度O(n),需遍历查找元素。O(n),与 ziplist 相同,但遍历更高效(长度解析更快)。
      内存占用较低(但存在prevlen​字段冗余)。与 ziplist 接近,甚至更优(更紧凑的长度编码)。
      并发操作适应性高并发写入时,连锁更新可能导致性能抖动。无连锁更新,高并发下性能更稳定。
    3. ziplist 的缺陷

      • 连锁更新问题
        在中间位置插入元素时,若后续元素的 prevlen​ 字段因长度变化需要扩展(例如从 1 字节变为 5 字节),会触发后续元素的连续内存重分配,导致性能骤降。
        示例:插入一个长度超过 254 字节的元素,导致后续元素的 prevlen​ 从 0xFE​(1 字节)变为 0xFF + 4字节长度​(5 字节)。
      • 安全性风险
        prevlen​ 解析错误可能引发内存越界(如 Redis 早期版本中的 CVE-2018-11213 漏洞)。
    4. listpack 的改进

      • 自包含长度信息
        每个元素头部使用 element-total-len​ 字段记录自身总长度(包含编码类型、数据长度等),解析时无需依赖前驱元素。

      • 编码优化
        长度字段采用更紧凑的变长编码(类似 UTF-8),例如:

        • 长度 ≤ 127:1 字节。
        • 长度 ≤ 16383:2 字节。
        • 更大长度:5 字节(1 字节标记 + 4 字节长度)。
    5. 使用场景对比

      场景推荐结构原因
      小规模只读数据ziplist/listpack内存紧凑,适合存储用户基础信息、配置项等(Redis 7.0+ 优先使用 listpack)。
      高频写入/随机修改listpack无连锁更新问题,适合计数器、动态元数据等场景(Redis 7.0+ 默认使用 listpack)。
      大规模数据存储hashtable数据量大时 O(1) 哈希表更高效(无论底层是 ziplist 还是 listpack,超阈值后均转为 hashtable)。
      高并发写入场景listpack避免 ziplist 的连锁更新抖动,性能更稳定。
  4. 数据结构特性对比

    特性ziplist(压缩列表)hashtable(哈希表)
    存储方式连续内存块存储,无指针开销,通过偏移量访问数据。散列桶结构,每个键值对通过哈希函数分配到桶中,通过指针链接。
    内存占用内存紧凑,无额外指针开销,内存利用率高。内存占用较高(存储指针、哈希表扩容时的冗余空间)。
    查询复杂度O(n)(需要遍历字段查找O(1)(哈希表直接定位)
    插入/删除效率平均 O(n),数据量大时效率低(需移动后续元素,可能触发连锁更新)。O(1)(哈希表直接操作,扩容时可能触发 rehash 耗时)。
    扩容机制不可动态扩容,超出阈值后直接转换为 hashtable。动态扩容(负载因子超过阈值时翻倍扩容,缩容时按需减少)。
    适用数据规模字段数少(默认 ≤512)且字段值小(默认 ≤64 字节)。字段数多或字段值大。
  5. 适用场景对比

    场景推荐编码原因
    小型对象存储ziplist字段数少且值小(如用户基础信息),内存利用率高。
    高频写入/随机访问hashtable避免 ziplist 的遍历开销和连锁更新问题(如频繁修改的计数器)。
    只读或低频修改数据ziplist利用内存紧凑特性减少内存占用(如静态配置数据)。
    大规模数据存储hashtable数据量大时 O(1) 查询效率显著优于 ziplist(如购物车、社交关系链)。
    需要遍历所有字段ziplist(小数据)连续内存布局遍历更快;大数据量时 hashtable 的HSCAN​更安全(避免HGETALL​阻塞)。
  6. 配置调优建议

    hash-max-ziplist-entries 512  # 字段数阈值,默认 512
    hash-max-ziplist-value 64     # 单个字段值最大字节数,默认 64
    
    • 降低阈值若需优先保障读写性能,可调小阈值(如 entries 128​),让更多 Hash 使用 hashtable。(空间)
    • 提高阈值:若内存紧张且数据规模可控,可增大阈值(如 entries 1024​),延长 ziplist 的使用。(时间)

三、使用场景

案例所需依赖 :

 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version></dependency></dependencies>
  1. 对象属性存储

    • 将对象的多个属性(如用户信息、商品详情)聚合存储为一个 Hash,键为对象 ID,字段为属性名,简化键管理并减少内存碎片。

      package com.example.redis.hash;/*** 描述: 将对象的多个属性(如用户信息、商品详情)聚合存储为一个 Hash,键为对象 ID,字段为属性名,简化键管理并减少内存碎片** @author ZHOUXIAOYUE* @date 2025/4/17 09:52*/
      import redis.clients.jedis.Jedis;
      import com.fasterxml.jackson.core.type.TypeReference;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import java.util.Map;
      class User {private String id;private String name;private String age;private String email;private String phone;// 构造器、getter、setter 略public User(String id, String name, String age, String email, String phone) {this.id = id;this.name = name;this.age = age;this.email = email;this.phone = phone;}public String getId() { return id; }public String getName() { return name; }public String getAge() { return age; }public String getEmail() { return email; }public String getPhone() { return phone; }
      }
      public class RedisHashExample {public static void main(String[] args) throws Exception {//创建链接Jedis jedis = new Jedis("localhost", 6379);// 定义对象User user = new User("user:1001", "Alice", "30", "alice@example.com", "1234567890");// 使用 Jackson 将对象转换为 Map<String, String>ObjectMapper objectMapper = new ObjectMapper();Map<String, String> userMap = objectMapper.convertValue(user, new TypeReference<Map<String, String>>() {});// 从 Map 中移除 id 字段(如果不需要存储到 Hash 中)userMap.remove("id");// 存储到 Redis 中jedis.hmset(user.getId(), userMap);System.out.println("存储用户信息成功,查询结果为:");Map<String, String> storedUserInfo = jedis.hgetAll(user.getId());storedUserInfo.forEach((field, value) -> System.out.println(field + ": " + value));jedis.close();}
      }
      
  2. 部分更新与原子操作

    • 支持单个字段的原子更新(如用户年龄修改),避免序列化整个对象。

      package com.example.redis.hash;/*** 描述: 支持单个字段的原子更新(如用户年龄修改),避免序列化整个对象。** @author ZHOUXIAOYUE* @date 2025/4/17 10:12*/
      import redis.clients.jedis.Jedis;
      import java.util.Map;
      import java.util.HashMap;
      public class RedisHashUpdateExample {public static void main(String[] args) {// 创建 Jedis 连接,连接到本地 Redis 服务Jedis jedis = new Jedis("localhost", 6379);// 假设已经存储了用户信息,键为 "user:1001"String userId = "user:1001";// 如果未事先存储用户数据,可以先初始化对象(仅供测试)if (!jedis.exists(userId)) {Map<String, String> userInfo = new HashMap<>();userInfo.put("name", "Alice");userInfo.put("age", "30");userInfo.put("email", "alice@example.com");userInfo.put("phone", "1234567890");jedis.hmset(userId, userInfo);System.out.println("初始化用户信息成功。");}// 查询更新前的年龄String oldAge = jedis.hget(userId, "age");System.out.println("更新前用户年龄: " + oldAge);// 对单个字段进行原子更新,这里更新年龄为 31jedis.hset(userId, "age", "31");// 查询更新后的年龄String newAge = jedis.hget(userId, "age");System.out.println("更新后用户年龄: " + newAge);// 关闭 Jedis 连接jedis.close();}
      }
      
  3. 计数器与统计

    • 利用 HINCRBY​ 实现实时计数(如商品销量、页面访问量)。

      package com.example.redis.hash;/*** 描述: 利用 HINCRBY 实现实时计数(如商品销量、页面访问量)** @author ZHOUXIAOYUE* @date 2025/4/17 10:15*/
      import redis.clients.jedis.Jedis;
      public class RedisCounterExample {public static void main(String[] args) {// 连接 Redis 服务器Jedis jedis = new Jedis("localhost", 6379);// 示例1:统计商品销量// 商品 ID 为 product:2001,对应的销量字段为 "sales"String productKey = "product:2001";// 初始化销量字段,注意如果该字段不存在,则 hincrby 会默认其值为 0// jedis.hset(productKey, "sales", "0");// 模拟一次商品销售,使用 HINCRBY 将销量加 1long salesCount = jedis.hincrBy(productKey, "sales", 1);System.out.println("商品 " + productKey + " 当前销量为:" + salesCount);// 示例2:统计页面访问量// 页面标识为 page:homepage,对应的访问量字段为 "views"String pageKey = "page:homepage";// 初始化访问量字段,若不存在则 hincrby 默认从 0 开始计数// jedis.hset(pageKey, "views", "0");// 模拟页面访问,使用 HINCRBY 将访问量加上 5(比如一次批量更新)long viewCount = jedis.hincrBy(pageKey, "views", 5);System.out.println("页面 " + pageKey + " 当前访问量为:" + viewCount);// 关闭 Jedis 连接jedis.close();}
      }
      
  4. 购物车实现

    • 以用户 ID 为键,商品 ID 为字段,数量为值,便于动态增删商品。

      package com.example.redis.hash;/*** 描述: 以用户 ID 为键,商品 ID 为字段,数量为值,便于动态增删商品。** @author ZHOUXIAOYUE* @date 2025/4/17 10:18*/
      import redis.clients.jedis.Jedis;
      import java.util.Map;
      public class ShoppingCartDemo {public static void main(String[] args) {// 创建 Jedis 连接,连接到本地 Redis 服务,默认端口 6379Jedis jedis = new Jedis("localhost", 6379);// 以用户ID构建购物车的 key(建议加上 cart 前缀以示区分)String cartKey = "cart:user:1001";// -------------------------------// 示例1:添加商品到购物车// -------------------------------// 将商品 product:2001 添加至购物车,数量 2jedis.hset(cartKey, "product:2001", "2");System.out.println("添加商品 product:2001 数量 2 到购物车 " + cartKey);// 添加另一个商品 product:2002,数量 3jedis.hset(cartKey, "product:2002", "3");System.out.println("添加商品 product:2002 数量 3 到购物车 " + cartKey);printCart(jedis, cartKey);// -------------------------------// 示例2:动态增加已有商品的数量// -------------------------------// 将商品 product:2001 的数量原子性增加 1jedis.hincrBy(cartKey, "product:2001", 1);System.out.println("将商品 product:2001 的数量增加 1");printCart(jedis, cartKey);// -------------------------------// 示例3:删除商品// -------------------------------// 从购物车中删除商品 product:2002jedis.hdel(cartKey, "product:2002");System.out.println("从购物车中删除商品 product:2002");printCart(jedis, cartKey);// 关闭 Jedis 连接jedis.close();}// 打印购物车中所有商品信息private static void printCart(Jedis jedis, String cartKey) {System.out.println("购物车 " + cartKey + " 当前内容:");Map<String, String> cartItems = jedis.hgetAll(cartKey);if(cartItems.isEmpty()){System.out.println("购物车为空。");} else {cartItems.forEach((productId, quantity) ->System.out.println("商品ID:" + productId + ", 数量:" + quantity));}System.out.println("--------------------------------------------------");}
      }
      
  5. 分布式锁与缓存

    • 通过 HSETNX​ 实现轻量级锁,或缓存计算结果减少重复计算。

      package com.example.redis.hash;/*** 描述: 通过 HSETNX 实现轻量级锁,或缓存计算结果减少重复计算* 连接 Redis 后,使用哈希 key "cache:calc" 保存缓存数据和锁信息。* 首先通过 hget 检查是否已经有计算结果存入缓存,如果存在则直接返回。* 如果未命中缓存,通过 HSETNX 尝试对字段 "lock" 加锁。如果返回 1,则表示当前线程获得锁,然后执行耗时计算,将结果存入 "result" 字段,最后释放锁(删除 "lock" 字段)。* 若 HSETNX 返回 0,则表示已有线程在计算,当前线程等待一段时间后轮询 "result" 字段,直到获取到已缓存的计算结果。\* @author ZHOUXIAOYUE* @date 2025/4/17 10:26*/
      import redis.clients.jedis.Jedis;
      public class CacheLockExample {// 模拟一个耗时计算,例如求 1~1000000 的和private static long doExpensiveComputation() {long sum = 0;for (int i = 1; i <= 1_000_000; i++) {sum += i;}// 模拟延迟try {Thread.sleep(1000);} catch (InterruptedException e) {// 忽略异常处理}return sum;}public static void main(String[] args) {// 连接 Redis 服务Jedis jedis = new Jedis("localhost", 6379);// 使用哈希结构保存缓存与锁信息String hashKey = "cache:calc";String lockField = "lock";String resultField = "result";// 判断缓存中是否已有计算结果String cachedResult = jedis.hget(hashKey, resultField);if (cachedResult != null) {System.out.println("直接从缓存中获取结果: " + cachedResult);jedis.close();return;}// 尝试通过 HSETNX 获取轻量级锁(lockField 不存在时设置锁)long lockAcquired = jedis.hsetnx(hashKey, lockField, String.valueOf(System.currentTimeMillis()));if (lockAcquired == 1) {// 获取锁成功,执行耗时计算System.out.println("获取锁成功,开始计算...");long computedValue = doExpensiveComputation();// 将计算结果缓存到 resultField 中jedis.hset(hashKey, resultField, String.valueOf(computedValue));// 释放锁(删除 lockField)jedis.hdel(hashKey, lockField);System.out.println("计算完成并缓存结果: " + computedValue);} else {// 获取锁失败,其他线程正在计算,等待缓存结果System.out.println("其他线程正在计算,等待获取结果...");int maxWaitTime = 10; // 最长等待时间(单位:循环次数,每次 100 毫秒)int waited = 0;while (waited < maxWaitTime) {try {Thread.sleep(100); // 每次等待100毫秒} catch (InterruptedException e) {// 忽略异常}cachedResult = jedis.hget(hashKey, resultField);if (cachedResult != null) {System.out.println("等待期间缓存中获取结果: " + cachedResult);break;}waited++;}if (cachedResult == null) {System.out.println("等待超时,还未获取到计算结果。");}}jedis.close();}
      }
      

总结

Redis Hash 通过灵活的字段操作、高效的内存管理和多样化的应用场景,成为存储结构化数据的理想选择。

相关文章:

Redis Hash 介绍

Redis Hash 介绍 从基础命令、内部编码和使用场景三个维度分析如下&#xff1a; 一、基础命令 Redis Hash 提供了丰富的操作命令&#xff0c;适用于字段&#xff08;field&#xff09;级别的增删改查&#xff1a; 设置与修改 HSET&#xff1a;设置单个字段值&#xff08;HSET…...

[redis进阶一]redis的持久化(2)AOF篇章

目录 一 为什么有了RDB持久化机制还要有AOF呢 板书介绍具体原因: ​编辑二 详细讲解AOF机制 (1)AOF的基本使用 1)板书如下 2)开启AOF机制: 3) AOF工作流程 (2)AOF是否会影响到redis性能 ​编辑 (3)AOF缓冲区刷新策略 (4)AOF的重写机制 板书如下: 为什么要有这个重写机…...

【Linux我做主】探秘gcc/g++和动静态库

TOC Linux编译器gcc/g的使用 github地址 有梦想的电信狗 前言 在软件开发的世界中&#xff0c;编译器如同匠人的工具&#xff0c;将人类可读的代码转化为机器执行的指令。 对于Linux开发者而言&#xff0c;gcc和g是构建C/C程序的核心工具链&#xff0c;掌握它们的原理和使…...

Linux `init 0` 相关命令的完整使用指南

Linux init 0 相关命令的完整使用指南—目录 一、init 系统简介二、init 0 的含义与作用三、不同 Init 系统下的 init 0 行为1. SysVinit&#xff08;如 CentOS 6、Debian 7&#xff09;2. systemd&#xff08;如 CentOS 7、Ubuntu 16.04&#xff09;3. Upstart&#xff08;如 …...

【英语语法】基本句型

目录 前言一&#xff1a;主谓二&#xff1a;主谓宾三&#xff1a;主系表四&#xff1a;主谓双宾五&#xff1a;主谓宾补 前言 英语基本句型是语法体系的基石&#xff0c;以下是英语五大基本句型。 一&#xff1a;主谓 结构&#xff1a;主语 不及物动词 例句&#xff1a; T…...

Vue3中发送请求时,如何解决重复请求发送问题?

文章目录 前言一、问题演示二、使用步骤1.One组件2.Two组件封装工具函数处理请求 总结 前言 在开发过程中&#xff0c;重复请求发送问题可能会导致数据不一致、服务器压力增加或用户操作异常。以下是解决重复请求问题的常见方法和最佳实践&#xff1a; 一、问题演示 我们看着…...

信息学奥赛一本通 1622:Goldbach’s Conjecture | 洛谷 UVA543 Goldbach‘s Conjecture

【题目链接】 ybt 1622&#xff1a;Goldbach’s Conjecture 洛谷 UVA543 Goldbach’s Conjecture 【题目考点】 1. 筛法求质数表 埃筛线性筛&#xff08;欧拉筛&#xff09; 知识点讲解见信息学奥赛一本通 2040&#xff1a;【例5.7】筛选法找质数 【解题思路】 首先使用埃…...

在极狐GitLab 身份验证中如何使用 OIDC?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 使用 OpenID Connect 作为认证提供者 (BASIC SELF) 您可以使用极狐GitLab 作为客户端应用程序&#xff0c;与 OpenID Connec…...

计算机视觉与深度学习 | 基于YOLOv8与光流法的目标检测与跟踪(Python代码)

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 目标检测与跟踪 关键实现逻辑检测-跟踪协作机制‌特征点选择策略‌运动…...

解决 VSCode 中 NVM 配置后无法识别 Node 和 NPM 的问题

在开发中&#xff0c;我们经常需要使用 Node.js 和 NPM 来管理 JavaScript 项目依赖&#xff0c;而 NVM&#xff08;Node Version Manager&#xff09;是开发者在本地环境中管理多个 Node.js 版本的得力工具。不过&#xff0c;有时候在 VSCode 中配置完 NVM 后&#xff0c;可能…...

观察者模式:从博客订阅到消息队列的解耦实践

观察者模式&#xff1a;从博客订阅到消息队列的解耦实践 一、模式核心&#xff1a;用事件驱动实现对象间松耦合 在新闻 APP 中&#xff0c;当热点事件发生时需要实时通知所有订阅用户&#xff1b;在电商系统中&#xff0c;库存变化需触发价格监控模块重新计算。这类场景的核心…...

ReportLab 导出 PDF(页面布局)

ReportLab 导出 PDF&#xff08;文档创建&#xff09; ReportLab 导出 PDF&#xff08;页面布局&#xff09; ReportLab 导出 PDF&#xff08;图文表格) PLATYPUS - 页面布局和排版 1. 设计目标2. 开始3. Flowables3.1. Flowable.draw()3.2. Flowable.drawOn(canvas,x,y)3.3. F…...

qt与html通信

**Cef视图&#xff08;CefView&#xff09;**是指在使用Chromium Embedded Framework&#xff08;CEF&#xff09;时&#xff0c;嵌入到应用程序中的浏览器视图。CEF是一个开源项目&#xff0c;它基于Google的Chromium浏览器&#xff0c;允许开发者将Web浏览器功能嵌入到自己的…...

git 根据http url设置账号密码

1. 原因 场景&#xff1a;有一种情况&#xff0c;比如在github上面有多个账号&#xff0c;并且每个账号都有些仓库的内容需要修改&#xff0c;并且这些账号自己&#xff0c;不是协作者的关系。这个时候需要针对每个仓库的url设置用户名密码, 2. 设置 2.1 第一步&#xff1a;…...

【CVE-2024-10929】ARM CPU漏洞安全通告

安全之安全(security)博客目录导读 目录 一、概述 二、CVE详情 三、受影响产品 四、建议措施 五、致谢 六、版本历史 一、概述 在部分基于Arm架构的CPU中发现了一个潜在安全问题&#xff0c;称为Spectre-BSE&#xff08;Branch Status Eviction&#xff0c;分支状态驱逐…...

OpenCV 图形API(33)图像滤波-----高斯模糊函数gaussianBlur()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用高斯滤波器对图像进行模糊处理。 该函数使用指定的高斯核对源图像进行滤波。输出图像必须与输入图像具有相同的类型和通道数。 cv::gapi::g…...

【Android】 如何将 APK 内置为系统应用(适用于编辑设置属性)

如何将 APK 内置为系统应用(适用于编辑设置属性) 在 Android 中&#xff0c;将 APK 文件内置为系统应用涉及到一系列的命令和步骤。以下是详细的操作流程&#xff0c;帮助您解决常见问题&#xff0c;如 /system not in /proc/mounts 的错误。 挂载system/app获取可读写权限 …...

【2025最新版】火鸟门户v8.5系统源码+PC、H5、小程序 +数据化大屏插件

一.介绍 火鸟地方门户系统V8.5源码 系统包含4端&#xff1a; PCH5小程序APP 二.搭建环境 系统环境&#xff1a;CentOS、 运行环境&#xff1a;宝塔 Linux 网站环境&#xff1a;Nginx 1.2.22 MySQL 5.6 PHP-7.4 常见插件&#xff1a;fileinfo &#xff1b; redis 三.测…...

关于 传感器 的详细解析,涵盖定义、分类、工作原理、常见类型、应用领域、技术挑战及未来趋势,结合实例帮助理解其核心概念

以下是关于 传感器 的详细解析&#xff0c;涵盖定义、分类、工作原理、常见类型、应用领域、技术挑战及未来趋势&#xff0c;结合实例帮助理解其核心概念&#xff1a; 一、传感器的定义与核心功能 1. 定义 传感器&#xff08;Sensor&#xff09;是一种能够将物理量&#xff…...

EtherCAT转ProfiNet边缘计算网关配置优化:汽车制造场景下PLC与机器人协同作业案例

1.行业背景与需求分析 智能汽车焊装车间是汽车制造的核心工艺环节&#xff0c;某德国豪华品牌在其上海MEB工厂新建的焊装车间中&#xff0c;采用西门子S7-1500PLC作为ProfiNet主站&#xff0c;负责整线协调与质量追溯&#xff1b;同时部署KUKAKR1500Titan机器人&#xff08;Eth…...

极狐GitLab CI/CD 流水线计算分钟数如何管理?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 计算分钟管理 (PREMIUM SELF) 在极狐GitLab 16.1 中&#xff0c;从 CI/CD 分钟数重命名为计算配额或计算分钟数。 管理员可…...

HTTP协议 --- 超文本传输协议 和 TCP --- 传输控制协议

是基于 TCP 协议的 80 端口的一种 C/S 架构协议。 特点&#xff1a;无状态 --- 数据传输完成后&#xff0c;会断开 TCP 连接&#xff0c;哪怕浏览器还正常运行。 请求报文 --- 方法 响应报文 --- 状态码 是一种面向连接的可靠传输协议 。 面向连接 --- 在传输数据之前&am…...

类和对象(下篇)(详解)

【本节目标】 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5. 再次理解封装 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 #include <iostream> using name…...

Uniapp:获取当前定位坐标

目录 一、出现场景二、具体使用 一、出现场景 在项目的开发中&#xff0c;会出现打卡、定位当前位置的功能&#xff0c;那我们如何获取当前位置呢&#xff1f;这就需要使用getLocation来获取当前位置坐标 二、具体使用 uni.getLocation({type: wgs84, // 返回可以用于uni.op…...

最大子序和问题——动态规划/贪心算法解决

目录 一&#xff1a;问题描述 二&#xff1a;解决思路1——动态规划思想 三&#xff1a;C 语言代码实现 四&#xff1a;复杂度分析 五&#xff1a;解决思路2——贪心算法思想 六&#xff1a;具体步骤 七: C语言代码实现 八&#xff1a;复杂度分析 一&#xff1a;问题描述 …...

【Unity】JSON数据的存取

这段代码的结构是为了实现 数据的封装和管理&#xff0c;特别是在 Unity 中保存和加载玩家数据时。以下是对代码设计的逐步解释&#xff1a; 1. PlayerCoin 类 PlayerCoin 是一个简单的数据类&#xff0c;用于表示单个玩家的硬币信息。它包含以下字段&#xff1a; count&…...

LeetCode【剑指offer】系列(位运算篇)

剑指offer15.二进制中1的个数 题目链接 题目&#xff1a;编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中数字位数为 ‘1’ 的个数&#xff08;也被称为 汉明重量).&#xff09;。 思路一&#xff…...

unity socket 客户端和c#服务器通信

服务器 using BarrageGrab; using System; using System.Collections.Concurrent; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading;namespace Lyx {class Server{private TcpListener listener;private Concurre…...

如何在Vue中实现取消聚焦el-select——从零到部署的完整指南

如何在Vue中实现取消聚焦el-select——从零到部署的完整指南 在开发Vue项目时&#xff0c;经常会遇到需要处理用户交互和组件状态管理的情况。特别是在使用Element UI组件库时&#xff0c;如何优雅地管理组件的状态显得尤为重要。本文将详细介绍如何在取消对话框时自动取消el-s…...

网络安全领域的AI战略准备:从概念到实践

网络安全领域的AI准备不仅涉及最新工具和技术的应用&#xff0c;更是一项战略必需。许多企业若因目标不明确、数据准备不足或与业务重点脱节而未能有效利用AI技术&#xff0c;可能面临严重后果&#xff0c;包括高级网络威胁数量的激增。 AI准备的核心要素 构建稳健的网络安全…...