redis五种数据结构详解(java实现对应的案例)

一、简述

Redis是一款高性能的键值对存储数据库,它支持五种基本数据类型,分别是字符串(String)、列表(List)、哈希(Hash)、集合(Set)、有序集合(Sorted Set)。

二、五种基本数据类型

2.1 字符串(String)

String是Redis最基本的类型,一个key对应一个value,它是数据安全的,并且可以包含任何数据,一个Redis的字符串最多可以是512M(字符串长度小于1M的时候,每次扩容都是加倍现有空间,如果超过1M,扩容的时候只会扩容1M空间)

常用的应用场景:缓存用户信息、用户登录状态、配置文件等等

常用命令

set <key><value> 添加键值对
get <key> 查询对应键值
append <key><value>将给定的 追加到原值的末尾
strlen <key> 获得值的长度
setnx <key><value> 只有在 key 不存在时 设置 key 的值
incr <key> 将 key 中储存的数字值增1只能对数字值操作,如果为空,新增值为
decr <key> 将 key 中储存的数字值减1只能对数字值操作,如果为空,新增值为-1
mset <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value对
mget <key1><key2><key3> .....同时获取一个或多个 value
msetnx <key1><value1><key2><value2> ..... 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
getrange <key><起始位置><结束位置> 获得值的范围,类似java中的substring,前包,后包
setrange <key><起始位置><value>用 <value> 覆写<key> 所储存的字符串值,从<起始位置>开始(索引从0开始)。
setex <key><过期时间><value> 设置键值的同时,设置过期时间,单位秒。

2.2 列表(List)

列表相当于是单个键对应多个值,它是一个有序的字符串元素集合,它按照插入的顺序来存储元素,可以在列表的头部或尾部进行插入和删除操作。它的底层实际是一个双向列表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差

常用的应用场景:消息队列,任务队列,历史记录等

常用命令

lpush/rpush <key><value1><value2><value3> .... 从左边/右边插入一个或多个值。
lpop/rpop <key> 从左边/右边吐出一个值。值在键在,值光键亡。
rpoplpush <key1><key2>从<key1> 列表右边吐出一个值,插到<key2>列表左边。
lrange <key><start><stop> 按照索引下标获得元素(从左到右)
lrange key 0 -1 0左边第一个,-1右边第一个,(0-1表示获取所有)
lindex <key><index> 按照索引下标获得元素(从左到右)
llen <key> 获得列表长度
linsert <key> before <value><newvalue> 在<value>的后面插入<newvalue>插入值
lrem <key><n><value> 从左边删除n个value(从左到右)
lset<key><index><value> 将列表key下标为index的值替换成value

2.3 集合(Set)

无序的字符串元素集合,跟List有点相似,不一样的是集合中的元素是唯一的,不允许重复的

常用的应用场景:签到系统,好友关系,去重等功能

常用的命令

sadd <key><value1><value2> ..... 将一个或多个 member 元素加入到集合 key 中,已经存在的member 元素将被忽略
smembers <key>取出该集合的所有值。
sismember <key><value>判断集合<key>是否为含有该<value>值,有1,没有0
scard<key>返回该集合的元素个数。
srem <key><value1><value2> .... 删除集合中的某个元素。
spop <key>随机从该集合中吐出一个值。
srandmember <key><n>随机从该集合中取出n个值。不会从集合中删除 。
smove <source><destination>value把集合中一个值从一个集合移动到另一个集合
sinter <key1><key2>返回两个集合的交集元素。
sunion <key1><key2>返回两个集合的并集元素。
sdiff <key1><key2>返回两个集合的差集元素(key1中的,不包含key2中的)

2.4 哈希(Hash)

哈希是一个键值对的集合,其中键和值都是字符串,它可以用来存储对象的属性,类似与关系型数据库中的表记录

常用的应用场景:存储用户信息,商品信息等对象数据        

常用的命令

hset <key><field><value>给<key>集合中的 <field>键赋值<value>
hget <key1><field>从<key1>集合<field>取出 value
hmset <key1><field1><value1><field2><value2>... 批量设置hash的值
hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在。
hkeys <key>列出该hash集合的所有field
hvals <key>列出该hash集合的所有value
hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 1 -1
hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

2.5 有序集合(Sorted Set/zset)

sorted Set和zset是一个东西,他们都是同一数据类型,只是称呼不同。有序集合和set是非常的相似,不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合成员是唯一的,但是评分可以重复。因为元素是有序的,所以我们也可以跟快的根据评分(score)或者次序(position)来获取范围元素

常用的应用场景:排行榜,热门话题等功能

常用的命令

zadd <key><score1><value1><score2><value2>…将一个或多个 member 元素及其score 值加入到有序集 key 当中
zrange <key><start><stop> [WITHSCORES] 返回有序集 key 中,下标在<start><stop>之间的元素,带WITHSCORES,可以让分数一起和值返回到结果集。
zrangebyscore key minmax [withscores] [limit offset count]返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
zrevrangebyscore key maxmin [withscores] [limit offset count] 同上,改为从大到小排列。
zincrby <key><increment><value> 为元素的score加上增量
zrem <key><value>删除该集合下,指定值的元素
zcount <key><min><max>统计该集合,分数区间内的元素个数
zrank <key><value>返回该值在集合中的排名,从0开始。

三、五种数据类型使用案例

3.1 连接redis

  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-redis</artifactId><version>1.4.7.RELEASE</version></dependency>

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.8.0</version>
</dependency>

 

注意点:这个是springboot的jar,其实也可以直接导入jedis的ajr 

下面连接redis调用的都是这个RedisTestUtil工具类

package com.study.redis;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** @author Administrator* @version 1.0* @project study* @description* @date 2025/5/20 星期二 17:11:46*/
public class RedisTestUtil {/*** 地址*/private static final String HOST = "127.0.0.1";/*** 端口*/private static final int PORT = 6379;/*** 缓存时间*/private static final int TIMEOUT = 30000;/*** 密码*/private static final String PASSWORD = "hm23";/*** 使用的redis库*/private static final int DATABASE = 0;private static final JedisPool jedisPool;static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(100);config.setMaxIdle(10);config.setMinIdle(5);config.setTestOnBorrow(true);jedisPool = new JedisPool(config, HOST, PORT, TIMEOUT, PASSWORD, DATABASE);}public static Jedis getJedis() {return jedisPool.getResource();}public static void close(Jedis jedis) {if (jedis != null) {jedis.close();}}
}

注意点:如果想springboot连接redis可以查看springboot连接redis_springboot链接单机redis bean注入地址信息-CSDN博客

3.2 String使用案例(存储token)

用字符串缓存一个token

 public static void main(String[] args) {String stringKey = "auth:token:";String token = "token222222222222222222222222222222";//连接redisJedis jedis = RedisTestUtil.getJedis();// redis缓存tokenjedis.set(stringKey, token);//redis获取对应的值String content = jedis.get(stringKey);System.out.println("获取到的值为>>>>>>>>"+content);}

3.3 List使用案例(用户操作历史记录)

用list缓存历史记录,每个用户对应一个list

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.time.LocalDateTime;
import java.util.Date;/*** @author Administrator* @version 1.0* @project study* @description* @date 2025/5/20 星期二 17:29:29*/
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class HistoryRecord {private Integer id;private String userId;      // 用户IDprivate String content;     // 记录内容private String time; // 记录时间
}
public class RedisTest {private static final String HISTORY_KEY_PREFIX = "user:history:";private static final int MAX_RECORDS = 20; // 每个用户最大记录数public static void main(String[] args) {// 缓存userId为1的历史记录RedisTest test = new RedisTest();for (int i = 0; i < 10; i++) {test.addRecord(i,"1","点击了"+i);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}//缓存userId为2的历史记录for (int i = 0; i < 10; i++) {test.addRecord(i,"2","点击了"+i);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}// 获取userId为1历史记录System.out.println("==============================获取userId为1历史记录=============================================");List<HistoryRecord> historyRecordList = test.getRecords("1");for (HistoryRecord historyRecord : historyRecordList) {System.out.println(JSON.toJSONString(historyRecord));}// 获取用户最新的n条历史记录System.out.println("==============================获取用户最新的n条历史记录=============================================");List<HistoryRecord> historyRecordList2 = test.getLatestRecords("1",2);for (HistoryRecord historyRecord : historyRecordList2) {System.out.println(JSON.toJSONString(historyRecord));}System.out.println("==============================删除单条历史记录=============================================");test.deleteRecord("1","2");// 第二个参数为操作idSystem.out.println("==============================清空用户的历史记录=============================================");test.clearHistory("1");}/*** 添加历史记录(自动去重,保持最新记录)*/public  void addRecord(Integer id,String userId, String content) {Jedis jedis = RedisTestUtil.getJedis();String key = HISTORY_KEY_PREFIX + userId;HistoryRecord record = new HistoryRecord(id,userId,content, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));String json = JSON.toJSONString(record);// 1. 从左边删除,先删除旧记录(如果存在)jedis.lrem(key, 0, json);// 2. 添加新记录到列表头部(最新记录在前)jedis.lpush(key, json);// 3. 限制列表长度,超出部分自动删除if (jedis.llen(key) > MAX_RECORDS) {jedis.rpop(key);}}/*** 获取用户的历史记录(按时间倒序)*/public List<HistoryRecord> getRecords(String userId) {Jedis jedis = RedisTestUtil.getJedis();String key = HISTORY_KEY_PREFIX + userId;List<String> jsonList = jedis.lrange(key, 0, -1);List<HistoryRecord> records = new ArrayList<>();for (String json : jsonList) {records.add(JSON.parseObject(json, HistoryRecord.class));}return records;}/*** 获取用户最新的N条历史记录*/public List<HistoryRecord> getLatestRecords(String userId, int count) {Jedis jedis = RedisTestUtil.getJedis();String key = HISTORY_KEY_PREFIX + userId;List<String> jsonList = jedis.lrange(key, 0, count - 1);List<HistoryRecord> records = new ArrayList<>();for (String json : jsonList) {records.add(JSON.parseObject(json, HistoryRecord.class));}return records;}/*** 删除单条记录实录* @param userId* @param recordId 操作的id*/public void deleteRecord(String userId, String recordId) {Jedis jedis = RedisTestUtil.getJedis();String key = HISTORY_KEY_PREFIX + userId;List<String> jsonList = jedis.lrange(key, 0, -1);// 查找并删除匹配ID的记录for (String json : jsonList) {HistoryRecord record = JSON.parseObject(json, HistoryRecord.class);if (record.getId().equals(Integer.valueOf(recordId))) {jedis.lrem(key, 0, json);break;}}}/*** 清空用户的历史记录*/public void clearHistory(String userId) {Jedis jedis = RedisTestUtil.getJedis();String key = HISTORY_KEY_PREFIX + userId;jedis.del(key);}
}

3.3 Set使用案例(当月签到情况)

利用set缓存一个签到功能,通过用户id可以查看到当月签到情况

public class RedisTest {private static final String HISTORY_KEY_PREFIX = "user:history:";private static final int MAX_RECORDS = 20; // 每个用户最大记录数private static final String SIGN_KEY_PREFIX = "sign:";public static void main(String[] args) {Long userId = 1001L;RedisTest test = new RedisTest();// 签到boolean isNewSign = test.doSign(userId);System.out.println("签到结果: " + (isNewSign ? "新签到" : "已签到"));// 检查是否签到System.out.println("今日是否签到: " + test.checkSign(userId));// 获取当月签到次数System.out.println("当月签到次数: " + test.getSignCount(userId));// 获取连续签到次数System.out.println("连续签到次数: " + test.getContinuousSignCount(userId));// 获取签到详情List<Boolean> signDetail = test.getSignDetail(userId);System.out.println("当月签到详情: " + signDetail);}// 生成 Key(格式:sign:{userId}:{yearmonth})private String getSignKey(Long userId) {LocalDate now = LocalDate.now();String yearMonth = now.format(DateTimeFormatter.ofPattern("yyyyMM"));return SIGN_KEY_PREFIX + userId + ":" + yearMonth;}// 签到(返回 true 表示首次签到,false 表示已签到)public boolean doSign(Long userId) {Jedis jedis = RedisTestUtil.getJedis();LocalDate now = LocalDate.now();int dayOfMonth = now.getDayOfMonth();String key = getSignKey(userId);// 使用 SADD 命令添加成员(Set 自动去重,存在则返回 0)return jedis.sadd(key, String.valueOf(dayOfMonth)) == 1;}// 检查今日是否已签到public boolean checkSign(Long userId) {Jedis jedis = RedisTestUtil.getJedis();LocalDate now = LocalDate.now();int dayOfMonth = now.getDayOfMonth();String key = getSignKey(userId);// 使用 SISMEMBER 命令检查成员是否存在return jedis.sismember(key, String.valueOf(dayOfMonth));}// 获取当月签到总次数public long getSignCount(Long userId) {Jedis jedis = RedisTestUtil.getJedis();String key = getSignKey(userId);// 使用 SCARD 命令获取集合大小return jedis.scard(key);}// 获取当月连续签到次数public long getContinuousSignCount(Long userId) {Jedis jedis = RedisTestUtil.

 

3.4 Hash使用案例(缓存商品信息)

利用Hash缓存商品信息

@Data
@Accessors(chain = true)
public class Product {private Long productId;private String name;private Double price;private Integer stock;private String category;private String description;private Long updateTime;}
public class RedisTest {private final Jedis jedis = RedisTestUtil.getJedis();private static final String PRODUCT_KEY_PREFIX = "product:";public static void main(String[] args) {// 创建商品对象Product product = new Product();product.setProductId(1001L);product.setName("iPhone 15 Pro");product.setPrice(6999.00);product.setStock(100);product.setCategory("手机/数码");product.setDescription("A17芯片,灵动岛设计");product.setUpdateTime(System.currentTimeMillis() / 1000);RedisTest redisTest = new RedisTest();// 存储商品到 Redis(过期时间 1天 = 86400秒)redisTest.saveProduct(product, 86400);System.out.println("商品已缓存");// 获取所有属性Map<String, String> productData = redisTest.getProduct(1001L);System.out.println("商品信息:" + productData);// 更新库存redisTest.updateProductField(1001L, "stock", "80");System.out.println("库存更新后:" + redisTest.getProductField(1001L, "stock"));// 删除描述字段redisTest.deleteProductField(1001L, "description");System.out.println("删除描述后:" + productData.get("description")); // 应输出 null}// 存储商品信息到 Redis Hash(带过期时间)public void saveProduct(Product product, int expireSeconds) {String key = getProductKey(product.getProductId());Map<String, String> hash = new HashMap<>();hash.put("name", product.getName());hash.put("price", String.valueOf(product.getPrice()));hash.put("stock", String.valueOf(product.getStock()));hash.put("category", product.getCategory());hash.put("description", product.getDescription());hash.put("update_time", String.valueOf(product.getUpdateTime()));jedis.hmset(key, hash); // 批量设置字段jedis.expire(key, expireSeconds); // 设置过期时间(秒)}// 获取商品的所有属性public Map<String, String> getProduct(Long productId) {String key = getProductKey(productId);return jedis.hgetAll(key); // 返回所有字段和值}// 获取单个属性(如价格)public String getProductField(Long productId, String field) {String key = getProductKey(productId);return jedis.hget(key, field);}// 更新商品属性(如库存)public Long updateProductField(Long productId, String field, String value) {String key = getProductKey(productId);return jedis.hset(key, field, value); // 返回 1 表示新增字段,0 表示更新现有字段}// 删除商品属性(如描述)public Long deleteProductField(Long productId, String field) {String key = getProductKey(productId);return jedis.hdel(key, field); // 返回删除的字段数}// 生成完整 Keyprivate String getProductKey(Long productId) {return PRODUCT_KEY_PREFIX + productId;}}

3.4 Sort Set使用案例(排行榜)

利用Sort Set缓存一个排行榜

@Accessors(chain = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RankItem {private  int rank;      // 排名private  String userId; // 用户 IDprivate  double score;  // 分数
}

 

public class RedisTest {private Jedis jedis = RedisTestUtil.getJedis();private static final String RANK_KEY = "rank:score"; // 排行榜 Keypublic static void main(String[] args) {RedisTest test = new RedisTest();// 添加测试数据test.updateScore("user:1001", 95.0);test.updateScore("user:1002", 88.0);test.updateScore("user:1003", 92.0);test.updateScore("user:1004", 76.0);test.updateScore("user:1005", 95.0); // 与 1001 分数相同// 获取前三名List<RankItem> top3 = test.getTopN(3);System.out.println("排名前三用户为:");top3.forEach(System.out::println);// 获取用户 1002 的排名long rank = test.getUserRank("user:1002");System.out.println("用户1002排名: " + rank);}// 添加/更新用户分数public void updateScore(String userId, double score) {jedis.zadd(RANK_KEY, score, userId);}// 获取排行榜前 N 名(降序)public List<RankItem> getTopN(int n) {// 获取前 N 名(分数从高到低)Set<Tuple> topN = jedis.zrevrangeWithScores(RANK_KEY, 0, n - 1);List<RankItem> result = new ArrayList<>();int rank = 1;for (Tuple tuple : topN) {result.add(new RankItem(rank++,tuple.getElement(),  // 用户 IDtuple.getScore()     // 分数));}return result;}// 获取用户排名(从 1 开始)public long getUserRank(String userId) {// ZREVRANK 返回 0 为第一名Long rank = jedis.zrevrank(RANK_KEY, userId);return rank != null ? rank + 1 : -1; // -1 表示未找到}// 获取用户分数public double getUserScore(String userId) {Double score = jedis.zscore(RANK_KEY, userId);return score != null ? score : 0;}}

参考文档:Redis五大基本数据类型(String、LIst、Set、Hash、ZSet)及其底层结构-腾讯云开发者社区-腾讯云

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

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

相关文章

大数据-273 Spark MLib - 基础介绍 机器学习算法 决策树 分类原则 分类原理 基尼系数 熵

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大模型篇章已经开始&#xff01; 目前已经更新到了第 22 篇&#xff1a;大语言模型 22 - MCP 自动操作 FigmaCursor 自动设计原型 Java篇开…

第十一章 Java基础-继承

文章目录 1.继承来源2.继承特点3.子类能继承父类中哪些内容1.继承来源 是为了解决代码的重复冗余。

Axure项目实战:驾驶舱(数据一张图)制作教程

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 视频展示(本文第三部分含所有echarts示例JS代码,可复制使用): Axure项目实战:驾驶舱(数据一张图…

针对Python开发的工具推荐及分析,涵盖集成开发环境(IDE)、轻量级工具、在线开发平台、代码管理工具等)

以下是针对Python开发的工具推荐及全面分析&#xff0c;涵盖集成开发环境&#xff08;IDE&#xff09;、轻量级工具、在线开发平台、代码管理工具等&#xff0c;结合不同场景和需求进行分类说明&#xff1a; 目录 一、集成开发环境&#xff08;IDE&#xff09; 1. PyCharm 2…

不使用绑定的方法

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // 初始设置 A 控件的宽度 ControlA.Width ControlB.Width / 2; // 监听 B 控件的 SizeChanged 事件 ControlB.SizeChanged (sender, e) > { ControlA.Width ControlB.Actual…

DDR5 ECC详细原理介绍与基于协议讲解

本文篇幅较长,涉及背景原理介绍方便大家理解其运作方式 以及 基于DDR5协议具体展开介绍。 背景原理介绍 上图参考:DDR 内存中的 ECC 写入操作时,On-die ECC的工作过程如下: SoC将需要写入到Memory中的数据发送给控制器控制器将需要写入的数据直接发送给DRAM芯片在DDR5 DR…

基于springboot的益智游戏系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

STM32软件spi和硬件spi

核心观点 本文主要介绍了SPI通信的两种实现方式&#xff1a;软件SPI和硬件SPI。详细阐述了SPI通信协议的基本概念、硬件电路连接方式、移位示意图、时序基本单元以及四种工作模式。同时&#xff0c;对W25Q64模块进行了详细介绍&#xff0c;包括其硬件电路、框图以及操作注意事…

NLP学习路线图(十五):TF-IDF(词频-逆文档频率)

在自然语言处理&#xff08;NLP&#xff09;的浩瀚宇宙中&#xff0c;TF-IDF&#xff08;词频-逆文档频率&#xff09; 犹如一颗恒星&#xff0c;虽古老却依然璀璨。当ChatGPT、BERT等大模型光芒四射时&#xff0c;TF-IDF作为传统方法的代表&#xff0c;其简洁性、高效性与可解…

爱其实很简单

初春时&#xff0c;元元买来两只芙蓉鸟。一只白色的&#xff0c;是雄鸟&#xff1b;另一只黄色的&#xff0c;是雌鸟。 每天清晨日出之前&#xff0c;雄鸟便开始“啁啾——啁啾”地啼鸣&#xff0c;鸣声清脆婉转&#xff0c;充满喜悦&#xff0c;仿佛在迎接日出&#xff0c;又…

CentOS 7 环境下部署 LAMP

在 CentOS 7 环境下部署 LAMP&#xff08;Linux Apache MySQL 5.7 PHP 7.4&#xff09; 环境的详细步骤如下&#xff1a; 1. 系统准备 1.1 更新系统 sudo yum update -y 1.2 安装依赖 sudo yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel e…

如何查看电脑电池性能

检查电脑电池性能的方法如下&#xff1a; 按下winR键&#xff0c;输入cmd回车&#xff0c;进入命令行窗口 在命令行窗口输入powercfg /batteryreport 桌面双击此电脑&#xff0c;把刚刚复制的路径粘贴到文件路径栏&#xff0c;然后回车 回车后会自动用浏览器打开该报告 红…

数据结构——优先级队列(PriorityQueue)

1.优先级队列 优先级队列可以看作队列的另一个版本&#xff0c;队列的返回元素是由是由插入顺序决定的&#xff0c;先进先出嘛&#xff0c;但是有时我们可能想要返回优先级较高的元素&#xff0c;比如最大值&#xff1f;这种场景下就由优先级队列登场。 优先级队列底层是由堆实…

在Windows本地部署Dify详细操作

Dify官网文档&#xff1a;产品简介 - Dify Docs 1.硬件要求 2.部署方式选择 本次我选择Docker Compose 部署&#xff0c;接下来我将根据官方文档指引&#xff0c;在windows电脑上完成dify本地部署 3.DockerCompose本地部署Dify 3.1 安装WSL2 官方安装WSL2的操作说明入口&…

Flutter 与 Android 原生布局组件对照表(完整版)

本对照表用于帮助 Android 开发者快速理解 Flutter 中的布局组件与原生布局的关系。 &#x1f4d8; Flutter ↔ Android 布局组件对照表 Flutter WidgetAndroid View/Layout说明ContainerFrameLayout / View通用容器&#xff0c;可设置背景、边距、对齐等RowLinearLayout (hor…

ps填充图层

在Photoshop&#xff08;PS&#xff09;中&#xff0c;填充图层是一种强大的工具&#xff0c;它允许用户在不破坏原始图像数据的情况下&#xff0c;快速为图像添加颜色、渐变或图案等填充效果。以下从填充图层的类型、创建方法、编辑与修改、应用场景等方面进行详细介绍。 填充…

网页前端开发(基础进阶1--盒子模型)

颜色表示方法3种&#xff1a; 1.关键字&#xff1a; color&#xff1a;green&#xff1b; gray red yellow 2.rgb表示法&#xff1a;红&#xff0c;绿&#xff0c;蓝三原色。rgb&#xff08;r&#xff0c;g&#xff0c;b&#xff09;&#xff0c;r表示红色&#xff0c;g表示绿…

第10讲、Odoo 18框架设计原理全解析

前言 Odoo是一套开源的企业资源规划(ERP)系统&#xff0c;以其模块化、可扩展性和全面的业务应用套件而闻名。Odoo 18作为其最新版本&#xff0c;在架构设计、前端技术和后端实现上都有显著的创新和优化。本文将从前端的OWL组件化、模块化&#xff0c;到后端的ORM封装&#xf…

CSS3 渐变、阴影和遮罩的使用

全文目录&#xff1a; 开篇语**前言****1. CSS3 渐变 (Gradient)****1.1 线性渐变 (linear-gradient)****1.2 径向渐变 (radial-gradient)** **2. CSS3 阴影 (Shadow)****2.1 盒子阴影 (box-shadow)****2.2 文本阴影 (text-shadow)** **3. CSS3 遮罩 (Mask)****3.1 基本遮罩 (m…

[Linux]虚拟地址到物理地址的转化

[Linux]虚拟地址到物理地址的转化 水墨不写bug 文章目录 一、再次认识地址空间二、页表1、页表的结构设计2、页表节省了空间&#xff0c;省在哪里&#xff1f;3、页表的物理实现 一、再次认识地址空间 OS和磁盘交互的内存基本单位是4KB&#xff0c;这4KB通常被称为内存块。OS对…