Redis 缓存 + MySql 持久化 实现点赞服务
前言
为什么所用 redis 作为缓存来实现点赞服务, 而不是直接就使用 mysql 来完成?
-
使用 Redis 的集合数据结构来存储点赞用户的 ID,方便快速判断用户是否已点赞;
-
当用户频繁的点赞和取消点赞时, 无需操作数据库, 减轻服务器压力
-
Redis 可以承受高并发的读写操作。当大量用户同时点赞时,Redis 可以先将这些点赞请求缓存起来,然后由后台线程逐步将数据持久化到 MySQL
实现
查询流程
数据存储格式
redis
# 存储用户点赞状态(SET)
SADD picture_likes:{picture_id} {user_id} # 用户点赞图片
SREM picture_likes:{picture_id} {user_id} # 取消点赞# 存储点赞计数器(String)
INCR picture_like_count:{picture_id} # 点赞数+1
DECR picture_like_count:{picture_id} # 点赞数-1# 存储用户点赞历史(ZSET)用于做增量同步
ZADD user_likes:{picture_id} {timestamp} {user_id} # 按时间排序
mysql
下面是用户点赞关系表, 至于 likesCount 则作为字段添加进 picture 表
create table user_likes
(id bigint auto_incrementprimary key,user_id bigint not null,picture_id bigint not null,created_time timestamp default CURRENT_TIMESTAMP not null,constraint uk_user_pictureunique (user_id, picture_id)
);
核心代码实现
点赞或取消点赞
相关参数构建
根据自己实际情况来
Long userId = userService.getLoginUser().getId();
String key = PICTURE_LIKE_PREFIX + request.getPictureId();
String userIdStr = userId.toString();
String likeCountKey = PICTURE_LIKE_COUNT_PREFIX + request.getPictureId();
String likeTimeKey = PICTURE_LIKE_TIME_PREFIX + request.getPictureId();// 查询用户是否已经点赞
boolean isLiked = Boolean.TRUE.equals(stringRedisTemplate.opsForSet().isMember(key, userId.toString())
);
操作 redis
为了防止指令穿插导致不一致性, 需要保证操作的原子性, 这里使用 管道 + MULTI 和 EXEC 命令来保证原子性和隔离性(也可以使用 lua 脚本来完成)
stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {connection.multi(); // 开启事务if (!isLiked) {// 记录用户点赞关系connection.sAdd(key.getBytes(), userIdStr.getBytes());// 记录用户点赞时间connection.zAdd(likeTimeKey.getBytes(), System.currentTimeMillis() / 1000.0, userIdStr.getBytes());// 增加点赞计数connection.incr(likeCountKey.getBytes());} else {// 移除用户点赞关系connection.sRem(key.getBytes(), userIdStr.getBytes());// 用处用户赞时间connection.zRem(likeTimeKey.getBytes(), userIdStr.getBytes());// 减少点赞计数connection.decr(likeCountKey.getBytes());}return connection.exec();
});
补充: redis 的事务机制
当使用事务来执行多个指令时,通过 MULTI 命令开启事务,将多个指令放入一个事务中,然后使用 EXEC 命令来原子性地执行这些指令。在 EXEC 执行期间,Redis 会按照顺序依次执行事务中的指令,不会被其他客户端的命令打断,从而保证了事务内指令执行的原子性和顺序性,也就确保了两条指令执行的间隔内没有其他指令被执行。
查询点赞数据
这里需要查询出用户是否给图片点赞, 以及图片对应的点赞总数
public List<LikeInfoVO> batchCheckLikeStatus(Long userId, List<Long> pictureIds) {// 1. 使用Pipeline同时查询两种数据List<Object> results = stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {// 查询用户点赞状态for (Long picId : pictureIds) {connection.sIsMember((PICTURE_LIKE_PREFIX + picId).getBytes(),userId.toString().getBytes());}// 查询点赞总数// 未匹配的项会返回空for (Long picId : pictureIds) {connection.get((PICTURE_LIKE_COUNT_PREFIX + picId).getBytes());}return null;});// 2. 处理混合结果List<LikeInfoVO> resultMap = new ArrayList<>();int halfSize = results.size() / 2;for (int i = 0; i < halfSize; i++) {Boolean isLiked = (Boolean) results.get(i);Integer likeCount = results.get(i + halfSize) != null ?Integer.parseInt((String) results.get(i + halfSize)) : 0;resultMap.add(new LikeInfoVO(isLiked, likeCount));}return resultMap;
}
将点赞数据封装进响应结果
List<LikeInfoVO> likeStatus = batchCheckLikeStatus(userId, pictureIds);List<PictureVO> vos = IntStream.range(0, records.size()).mapToObj(i -> {PictureVO pictureVO = new PictureVO();BeanUtils.copyProperties(records.get(i), pictureVO);pictureVO.setLike(likeStatus.get(i).getIsLike());pictureVO.setLikesCount(likeStatus.get(i).getLikesCount());return pictureVO;
}).collect(Collectors.toList());
数据同步
增量同步 or 全量同步
使用定时任务来完成将 redis 中数据同步到 mysql, 这里就不使用全量同步了, 一方面全量同步性能底, 再未处理 redis 删除的点赞关系
代码
@Scheduled(fixedRate = 300000)
public void syncIncrementally() {log.info("开始: 增量同步图片用户点赞关系到数据库, 并处理Redis已删除的点赞关系");// 1. 获取Redis最后同步时间戳long lastSyncTime = getLastSyncTimestamp();// 2. 同步新增点赞syncNewLikes(lastSyncTime);// 3. 同步取消点赞syncUnlikes();// 5. 同步图片点赞数量syncPicLikesCount();// 4. 更新同步时间updateSyncTimestamp();log.info("结束: 增量同步图片用户点赞关系到数据库, 并处理Redis已删除的点赞关系");
}
设置同步时间和获取最后同步时间
// 获取最后同步时间(默认返回24小时前的时间戳)
private long getLastSyncTimestamp() {String timestampStr = stringRedisTemplate.opsForValue().get(LAST_SYNC_KEY);return timestampStr != null ?Long.parseLong(timestampStr) :System.currentTimeMillis() - 86400_000; // 默认24小时前
}// 更新同步时间戳为当前时间
private void updateSyncTimestamp() {stringRedisTemplate.opsForValue().set(LAST_SYNC_KEY,String.valueOf(System.currentTimeMillis()));
}
同步新增点赞
private void syncNewLikes(long sinceTime) {// 使用ZSET记录点赞时间戳Set<String> newLikeKeys = stringRedisTemplate.keys(PICTURE_LIKE_PREFIX + "*");Objects.requireNonNull(newLikeKeys).forEach(key -> {long pictureId = Long.parseLong(StrUtil.removePrefix(key, PICTURE_LIKE_PREFIX));// 获取新增点赞用户(ZRANGEBYSCORE)Set<String> newUserIds = stringRedisTemplate.opsForZSet().rangeByScore(PICTURE_LIKE_TIME_PREFIX + pictureId, sinceTime, Double.MAX_VALUE);List<UserLikes> entityList = Objects.requireNonNull(newUserIds).stream().map(userId -> {UserLikes userLikes = new UserLikes();userLikes.setPictureId(pictureId);userLikes.setUserId(Long.parseLong(userId));return userLikes;}).collect(Collectors.toList());// 批量插入并忽略重复的元素if (CollUtil.isNotEmpty(entityList)) {userLikesMapper.insertIgnoreBatch(entityList);}});
}
同步取消点赞
private void syncUnlikes() {Set<String> likeKeys = stringRedisTemplate.keys(PICTURE_LIKE_PREFIX + "*");Objects.requireNonNull(likeKeys).forEach(key -> {Long pictureId = Long.parseLong(key.substring(PICTURE_LIKE_PREFIX.length()));Set<String> members = stringRedisTemplate.opsForSet().members(key);Set<Long> redisUserIds = Objects.requireNonNull(members).stream().map(Long::parseLong).collect(Collectors.toSet());QueryWrapper<UserLikes> wrapper = new QueryWrapper<>();wrapper.select("user_id").eq("picture_id", pictureId);Set<Long> mysqlUserIds = userLikesMapper.selectList(wrapper).stream().map(UserLikes::getUserId).collect(Collectors.toSet());// 找出MySQL有但Redis没有的记录mysqlUserIds.removeAll(redisUserIds);if (CollUtil.isNotEmpty(mysqlUserIds)) {UpdateWrapper<UserLikes> userLikesUpdateWrapper = new UpdateWrapper<>();userLikesUpdateWrapper.eq("picture_id", pictureId).in("user_id", mysqlUserIds);userLikesMapper.delete(userLikesUpdateWrapper);}});
}
相关文章:
Redis 缓存 + MySql 持久化 实现点赞服务
前言 为什么所用 redis 作为缓存来实现点赞服务, 而不是直接就使用 mysql 来完成? 使用 Redis 的集合数据结构来存储点赞用户的 ID,方便快速判断用户是否已点赞; 当用户频繁的点赞和取消点赞时, 无需操作数据库, 减轻服务器压力 Redis 可以承受高并发的读写操作…...
Oracle OCP知识点详解2:yum 等服务的搭建
一、YUM/DNF 服务架构解析 1.1 核心组件交互流程 sequenceDiagram participant Client participant YUM participant Repository participant RPMDBClient->>YUM: yum install oracle-database-preinstall YUM->>Repository: 获取元数据(repodata) Repository--&…...
JavaScript Hook XMLHttpRequest操作:逆向与调试实战指南
在JavaScript逆向工程中,Hook XMLHttpRequest操作是一种重要的技术,可以用来捕获、修改或分析网络请求的发送和接收过程。本文将结合具体案例,详细讲解如何实现XMLHttpRequest的Hook操作。 一、Hook XMLHttpRequest的基本原理 (…...
21 天 Python 计划:MySQL视图、触发器、存储过程、函数与流程控制
文章目录 一、视图1.1 创建视图1.2 使用视图1.3 修改视图1.4 删除视图 二、触发器2.1 创建触发器2.2 使用触发器2.3 删除触发器 三、存储过程3.1 介绍3.2 创建简单存储过程(无参)3.3 创建存储过程(有参)3.4 执行存储过程3.5 删除存…...
机器学习 Day10 逻辑回归
1.简介 流程就是: 就是我们希望回归后激活函数给出的概率越是1和0. 2.API介绍 sklearn.linear_model.LogisticRegression 是 scikit-learn 库中用于实现逻辑回归算法的类,主要用于二分类或多分类问题。以下是对其重要参数的详细介绍: 2.1.…...
Hadoop的序列化和反序列化
//1 package com.example.sei;import org.apache.hadoop.io.Writable;import java.io.DataInput; import java.io.DataOutput; import java.io.IOException;//学生类,姓名,年龄 //支持hadoop的序列化 //1.要实现Writable接口 //2.补充一个空参构造 publi…...
Altera Cyclone EP1C20F400C8N FPGA 阿尔特拉 介绍
在可编程逻辑器件领域,Altera 的 Cyclone 系列 FPGA 以其低成本、低功耗和灵活的 I/O 支持而著称。EP1C20F400C8N 作为 Cyclone I 家族中规模最大的成员之一,提供约 20 060 个逻辑单元,面向通信、工业控制、视频处理等多种嵌入式应用场景。…...
VTK随笔十四:QT与VTK的交互示例(平移)
VTK(Visualization Toolkit)是一个开源的软件系统,用于三维计算机图形学、图像处理和可视化。它提供了丰富的工具和类来处理三维数据和交互。在 VTK 中,拾取操作通常通过 vtkCellPicker 或 vtkPointPicker 等类来实现。 本文将展示…...
用户注册(阿里云手机验证码)
阿里云开通三网106短信 ①、在阿里云市场搜索“短信”,开通三网短信,并可以查看其中的请求示例(java PHP^) 并在个人中心的管理控制台中查到,获取其中的AppKey AppCode ②、接口开发 service-user模块中依赖spr…...
【BFT帝国】20250409更新PBFT总结
2411 2411 2411 Zhang G R, Pan F, Mao Y H, et al. Reaching Consensus in the Byzantine Empire: A Comprehensive Review of BFT Consensus Algorithms[J]. ACM COMPUTING SURVEYS, 2024,56(5).出版时间: MAY 2024 索引时间(可被引用): 240412 被引:…...
学习海康VisionMaster之边缘交点
一:进一步学习了 今天学习下VisionMaster中的边缘交点,这个还是拟合直线的衍生应用,可以同时测量两条直线并且输出交点或者判定是否有交点 二:开始学习 1:什么是边缘交点? 按照传统的算法,必须…...
公司级项目-AD9914扫频源(三)评估板与上位机的初步调试
硬件平台搭建1-评估板与上位机 第一阶段,先使用评估板配套的上位机软件进行控制,学习一下各种功能的实现方式和寄存器配置方式。 硬件连接 需要的设备仪器包括:多路直流稳压电源、信号发生器、示波器、电脑。 按照图中的方式进行连接&am…...
技术优化实战解析:Stream重构与STAR法则应用指南
目录 一、真实案例背景:老代码的"历史厚重感" 二、屎山代码解剖课:这些写法到底烂在哪? 三、Stream流式重构:给老代码做个大保健 2.1 重构后代码实现 2.2 核心API技术拆解 2.3 进阶优化技巧 三、STAR法则技术文档…...
基于Qt的串口通信工具
程序介绍 该程序是一个基于Qt的串口通信工具,专用于ESP8266 WiFi模块的AT指令配置与调试。主要功能包括: 1. 核心功能 串口通信:支持串口开关、参数配置(波特率、数据位、停止位、校验位)及数据收发。 AT指令操作&a…...
Xilinx FPGA XCZU5EV‑2FBVB900I Zynq UltraScale+™ MPSoC EV 系列
XCZU5EV‑1FBVB900I XCZU5EV‑2FBVB900E XCZU5EV‑1FBVB900I 是 Xilinx Zynq UltraScale™ MPSoC EV 系列中功能最为丰富的器件之一,采用 16 nm FinFET 工艺,封装为 31 mm 31 mm、900‑ball FCBGA(FBVB900)。该系列在传统的…...
如何更改OCP与metadb集群的连接方式 —— OceanBase运维管理
背景 许多用户都会借助OCP平台来进行OceanBase集群的运维与监控,且因为考虑单节点的OCP部署,在遇故障时可能会短时间出现无法管控 OceanBase集群,多数用户倾向于采用多节点方式来部署OCP,即 OCP的 metadb集群也是三节点的集群部署…...
Databricks: Why did your cluster disappear?
You may found that you created a cluster many days ago, and you didnt delete it, but it is disapear. Why did this happen? Who deleted the cluster? Actually, 30 days after a compute is terminated, it is permanently deleted automaticlly. If your workspac…...
深入解析Java内存与缓存:从原理到实践优化
一、Java内存管理:JVM的核心机制 1. JVM内存模型全景图 ┌───────────────────────────────┐ │ JVM Memory │ ├─────────────┬─────────────────┤ │ Thread │ 共享…...
macos下 ragflow二次开发环境搭建
参考官网链接 https://ragflow.io/docs/dev/launch_ragflow_from_source虚拟环境 git clone https://github.com/infiniflow/ragflow.git cd ragflow/ # if not pipx, please install it at first pip3 install pipxpipx install uv uv sync --python 3.10 --all-extras 安装 …...
从 Excel 到你的表格应用:条件格式功能的嵌入实践指南
一、引言 在日常工作中,面对海量数据时,如何快速识别关键信息、发现数据趋势或异常值,是每个数据分析师面临的挑战。Excel的条件格式功能通过自动化的视觉标记,帮助用户轻松应对这一难题。 本文将详细介绍条件格式的应用场景&am…...
安徽京准:NTP网络时钟服务器功能及同步模式的介绍
安徽京准:NTP网络时钟服务器功能及同步模式的介绍 安徽京准:NTP网络时钟服务器功能及同步模式的介绍 1、NTP网络时钟服务器概念: NTP时钟服务器,表面意思是时间计量工具的服务设备,其在现代工业中是用于对客户端设备…...
基于ueditor编辑器的功能开发之百度编辑器自带的查找和替换功能无法对目标文字进行滚动定位修复
在查找百度编辑器的查找和替换功能,发现当页面文字过多,用户在检索文字点击上一个下一个的时候,滚动条不跟随滚动了 分析了ueditor关于searchpalce方法的处理时,他会在目标文字的前面插入一个span标签用户获取当前需要高亮的文字节…...
MYSQL——SQL语句到底怎么执行
查询语句执行流程 MySQL 查询语句执行流程 查询缓存(Query Cache) MySQL内部自带了一个缓存模块,默认是关闭的。主要是因为MySQL自带的缓存应用场景有限。 它要求SQL语句必须一摸一样表里面的任何一条数据发生变化时,该表所有缓…...
[蓝桥杯 2022 省 B] 李白打酒加强版
题目链接: 思路: ①定义dp数组,f[i][j][k],表示经过 i 店, 遇到 j 花, 还有 k 酒。如果酒的数量超过了花的数量,那么一定喝不完。因此,k 不能超过 M。 ②从店推过来,f[…...
计算机视觉——图像金字塔与目标图像边缘检测原理与实践
一、两个图像块之间的相似性或距离度量 1.1 平方差和(SSD) 平方差和(SSD) 是一种常用的图像相似性度量方法。它通过计算两个图像在每个对应位置的像素值差的平方和来衡量两个图像之间的整体差异。如果两个图像在每个位置的像素值…...
复现QGIS-MCP教程
由于Claude国内下载不了尝试使用Cursor 下载安装Cursor Cursor - The AI Code Editor 本示例安装的是0.46版本 UV安装 简介 安装 安装成功 配置环境变量 验证 下载代码 git clone gitgithub.com:jjsantos01/qgis_mcp.git QGIS插件安装 文件拷贝 您需要将 qgis_mcp_plu…...
人工智能图像识别Spark Core
Spark Core 一.spark运行架构 1.运行架构 Spark 框架的核心是一个计算引擎,整体来说,它采用了标准 master-slave 的结构。 如下图所示,它展示了一个 Spark 执行时的基本结构。图形中的 Driver 表示 master,负责管理整个集群中的作…...
决策树+泰坦尼克号生存案例
决策树简介 学习目标 1.理解决策树算法的基本思想 2.知道构建决策树的步骤 【理解】决策树例子 决策树算法是一种监督学习算法,英文是Decision tree。 决策树思想的来源非常朴素,试想每个人的大脑都有类似于if-else这样的逻辑判断,这其中…...
怎么查看苹果手机和ipad的设备信息和ios udid
你知道吗?我们每天使用的iPhone和iPad,其实隐藏着大量详细的硬件与系统信息。除了常见的系统版本和序列号外,甚至连电池序列号、摄像头序列号、销售地区、芯片型号等信息,也都可以轻松查到! 如果你是开发者、维修工程…...
智能驱动教育变革:人工智能在高中教育中的实践路径与创新策略
一、引言 随着信息技术的飞速发展,人工智能(Artificial Intelligence, AI)已成为推动社会进步的重要力量。在教育领域,人工智能的应用正逐渐改变着传统的教学模式和方法,为教育现代化注入了新的活力。高中教育作为教育…...
TCP 和 UDP 可以使用同一个端口吗?
TCP 和 UDP 可以使用同一个端口吗? 前言 在深入探讨 TCP 和 UDP 是否可以使用同一个端口之前,我们首先需要理解网络通信的基本原理。网络通信是一个复杂的过程,涉及到多个层次的协议和机制。在 OSI 模型中,传输层是负责端到端数…...
MySQL事务管理
MySQL事务管理 事务的概念 事务由一条或多条SQL语句组成,这些语句在逻辑上存在相关性,共同完成一个任务,事务主要用于处理操作量大,复杂度高的数据。比如转账就涉及多条SQL语句,包括查询余额(select&…...
通过 SSH 方式访问 GitHub 仓库
我们来一步一步讲解如何让 Git 通过 SSH 方式访问 GitHub 仓库,包括从零开始的详细步骤,适用于大多数系统(Linux、macOS、Windows Git Bash)。 注意最好只用 Git bash 比较好!他能够直接在 Windows 系统上面使用一些 L…...
数据库学习
DDL(数据定义语言)、DML(数据操纵语言)、DQL(数据查询语言)和DCL(数据控制语言)。 DDL用于创建、删除和修改数据库对象,如表和数据库;DML涉及数据的增删改操…...
DeepSeek在安全领域的应用案例全景解析
DeepSeek作为人工智能领域的标杆技术,已在网络安全、公共安全、工业安全、军事防护等领域形成系统性应用。以下从六大核心场景展开分析,结合技术实现与行业标杆案例,呈现其多维度的安全赋能价值。 一、网络安全防护体系创新 威胁检测与响应闭环安胜"星盾"平台:通…...
AI驱动SEO关键词精准定位
内容概要 在传统SEO实践中,关键词定位往往依赖人工经验与有限的数据样本,导致策略滞后性与覆盖盲区并存。随着AI技术的深度介入,这一过程正经历系统性重构:从搜索意图的智能识别到关键词的自动化挖掘,算法模型通过分析…...
邮件营销:如何巧妙平衡发送频率与客户体验
在邮件营销领域,发送频率和客户体验就像跷跷板的两端,需要精心平衡。如果邮件发得太多,客户可能会觉得烦,甚至取消订阅,对品牌产生不好的印象;但如果发得太少,客户又容易把你忘了,错…...
Acrel-1000DP分布式光伏监控系统在嘉兴亨泰新能源有限公司2996.37KWP分布式光伏项目中的应用
摘 要:分布式光伏发电系统其核心特点是发电设备靠近用电负荷中心,通常安装在屋顶、建筑立面或闲置空地上,截至2025年,分布式光伏发电系统在全球和中国范围内取得了显著发展,成为能源转型和可持续发展的重要推动力量。国…...
vue3中左右布局两个个组件使用vuedraggable实现左向右拖动,右组件列表可上下拖动
需求:左侧是个菜单组件,有对应的表单类型。 右侧是渲染组件,点击左侧菜单或者拖动即可渲染出对应的组件 项目中采用vuedraggable实现拖拽功能。 具体实现是使用elementplus的组件,然后根据tagName的类型去渲染不同的组件。 首先…...
gevent 高并发、 RabbitMQ 消息队列、Celery 分布式的案例和说明
1. gevent 高并发请求示例 gevent:基于协程的Python库,通过异步非阻塞模式实现高并发请求。例如,同时抓取100个网页时,无需等待每个请求完成,提升效率。 import gevent from gevent import monkey monkey.patch_…...
直线模组在电子行业具体的应用
在工业自动化高速发展的今天,直线模组作为重要的传动和控制元件,凭借其高效、精准、稳定的特性。在众多行业中得到了广泛应用,尤其是在电子行业中,通过提供精确的运动控制和定位,帮助提高电子制造过程的效率、质量和自…...
Ubuntu 24.04启用root账户
1.启用ubuntu中的root账号 ubuntu默认是禁用了root账号的,需要手动开始root权限 # 设置root账号密码 sudo passwd root # 用以下命令启用 root 账户: sudo usermod -aG sudo rootsu - root 然后输入你之前设置的 root 密码。 一旦你成功登录为 root 用户&#x…...
【ES系列】Elasticsearch简介:为什么需要它?(基础篇)
🔥 本文将详细介绍Elasticsearch的前世今生,以及为什么它在当今的技术栈中如此重要。本文是ES起飞之路系列的基础篇第一章,适合想要了解ES的读者。 文章目录 一、什么是Elasticsearch?1. ES的定义2. ES的核心特性2.1 分布式存储2.2 实时搜索2.3 高可用性2.4 RESTful API3.…...
SvelteKit 最新中文文档教程(19)—— 最佳实践之身份认证
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
Droris(强制)删除某一个分区数据
Doris如果想删除某一个分区的数据,可以这么操作: DROP PARTITION [IF EXISTS] partition_name [FORCE]需要注意的是: 必须为使用分区的表保留至少一个分区。执行DROP PARTITION一段时间后,可以通过RECOVER语句恢复被删除的分区:…...
Meta 最新 AI 模型系列 ——Llama 4
Meta 发布了最新 AI 模型系列 ——Llama 4,这是其 Llama 家族的最新成员。 在大模型竞技场(Arena),Llama 4 Maverick 的总排名第二,成为第四个突破 1400 分的大模型。其中开放模型排名第一,超越了 DeepSeek…...
软考 系统架构设计师系列知识点 —— 设计模式之工厂模式
本文内容参考: 软考 系统架构设计师系列知识点之设计模式(2)_系统架构设计师中考设计模式吗-CSDN博客 https://baike.baidu.com/item/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F?fromModulelemma_search-box 设计模式-工厂方法模式࿰…...
Jetpack Compose 状态保存机制全面解析:让UI状态持久化
在Android开发中,Jetpack Compose 的状态管理是一个核心话题,而状态保存则是确保良好用户体验的关键。本文将深入探讨Compose中各种状态保存技术,帮助你在配置变更和进程重建时保持UI状态。 一、基础保存:rememberSaveable reme…...
阿里云原生AI网关Higress:架构解析与应用实践
摘要 随着云原生与AI技术的深度融合,API网关作为流量治理的核心组件,正面临新的挑战与机遇。阿里云开源的Higress网关,凭借其“三网合一”(流量网关、微服务网关、安全网关)的高集成能力,以及面向AI场景的…...
如何在数据仓库中集成数据共享服务?
目录 1. Snowflake 数据共享服务:云端的最佳实践 2. 数据共享服务的重要性 3. 麦聪 QuickAPI:企业本地的理想选择 4. 云端与本地的互补 总结 数据共享服务是现代数据仓库的核心功能,能够提升协作效率、降低成本并释放数据潜力。 以 Sno…...