Redis 五大基本数据类型及其应用场景进阶(缓存预热、雪崩 、穿透 、击穿)

news2024/9/28 7:22:52

Redis 数据类型及其应用场景

Redis 是什么?

Redis是一个使用C语言编写的高性能的基于内存的非关系型数据库,基于Key/Value结构存储数据,通常用来 缓解高并发场景下对某一资源的频繁请求 ,减轻数据库的压力。它支持多种数据类型,如字符串、哈希、列表、集合、有序集合等。Redis以其高性能、高可靠性和丰富的特性而闻名,被广泛应用于缓存、消息队列、实时分析等领域。

Redis 的优势

  1. 高性能:Redis的所有数据都存储在内存中,支持每秒处理上百万的读写操作。
  2. 丰富的数据类型:Redis支持多种数据类型,可以灵活地满足不同的业务需求。
  3. 原子性操作:Redis提供了许多原子性操作,如INCR、DECR、RPOP等,可以避免并发问题。
  4. 持久化:Redis支持RDB和AOF两种持久化方式,可以保证数据的安全性。

Redis 数据类型详解以及应用场景

具体的业务场景下的代码参考(点这里噢🌹🌹🌹)

Redis数据类型简单描述结合Java理解
StringValue 是String类型Map<String,String> JSON
SetValue 是Set类型Map套SetSet放的是不重复的valueMap<String,Set>
ZsetValue 是Set类型Map套SetSet放的是不重复的value能排序Map<String,TreeSet>
ListMap套ListList可以重复的value Index 下标Map<String,List>
HashMap套MapMap<String,Map<String,Object>>

1. String(字符串)

String是Redis最基本的数据类型,它可以存储任何形式的字符串,包括二进制数据。在Redis中,String类型的值最大可以达到512MB。

String的常用命令
  • SET:设置一个键值对
  • GET:获取一个键对应的值
  • INCR:对一个整数类型的键进行自增操作
  • DECR:对一个整数类型的键进行自减操作
  • SETEX:设置一个键值对,同时指定过期时间
String的应用场景
  1. 缓存:String类型可以用于缓存用户信息、商品详情等常用数据,提高系统的查询效率。
// 将用户信息缓存到Redis中
String userId = "1001";
String userInfo = "{\"id\":\"1001\",\"name\":\"Tom\",\"age\":25}";
jedis.set("user:" + userId, userInfo);

// 从Redis中获取用户信息
String cachedUserInfo = jedis.get("user:" + userId);
  1. 计数器:利用INCR、DECR等命令,可以实现计数器功能,如统计网站的访问量、文章的点赞数等。
// 文章点赞数+1
String articleId = "1001";
jedis.incr("article:" + articleId + ":likes");

// 获取文章点赞数
String likesStr = jedis.get("article:" + articleId + ":likes");
int likes = Integer.parseInt(likesStr);
  1. 分布式锁:利用SET命令的NX选项(只在键不存在时才设置值)和EX选项(设置过期时间),可以实现简单的分布式锁功能。
String lockKey = "lock:1001";
String lockValue = UUID.randomUUID().toString();

// 获取锁,过期时间30秒
String result = jedis.set(lockKey, lockValue, "NX", "EX", 30);

if ("OK".equals(result)) {
    // 获取锁成功,执行业务逻辑
    // ...
    
    // 释放锁
    if (lockValue.equals(jedis.get(lockKey))) {
        jedis.del(lockKey);
    }
} else {
    // 获取锁失败,处理异常情况
    // ...
}

2. List(列表)

Redis的List类型是一个双向链表,支持从头部或尾部进行插入和删除操作。一个List类型的键可以存储多个字符串值。

List的常用命令
  • LPUSH:从列表左端插入一个或多个值
  • RPUSH:从列表右端插入一个或多个值
  • LPOP:移除并返回列表左端的第一个元素
  • RPOP:移除并返回列表右端的第一个元素
  • LRANGE:获取列表在给定范围上的所有值
List的应用场景
  1. 消息队列:List类型可以用作简单的消息队列,生产者使用LPUSH命令插入消息,消费者使用RPOP命令获取消息。
// 生产者代码
String taskQueue = "queue:tasks";
String task = "...";
jedis.lpush(taskQueue, task);

// 消费者代码
String taskQueue = "queue:tasks";
String task = jedis.rpop(taskQueue);
if (task != null) {
    // 处理任务
    // ...
}
  1. 最新列表:使用LPUSH命令可以将最新的数据插入到列表头部,使用LTRIM命令可以限制列表的长度,实现最新N个元素的列表。
String latestNewsKey = "latest:news";
String news = "...";

// 将最新新闻插入到列表头部
jedis.lpush(latestNewsKey, news);

// 只保留最新的100条新闻
jedis.ltrim(latestNewsKey, 0, 99);

// 获取最新的10条新闻
List<String> latestNews = jedis.lrange(latestNewsKey, 0, 9);

3. Set(集合)

Redis的Set类型是一个无序且不重复的字符串集合。可以对Set执行交集、并集、差集等操作。

Set的常用命令
  • SADD:向集合中添加一个或多个成员
  • SMEMBERS:返回集合中的所有成员
  • SISMEMBER:判断成员是否存在于集合中
  • SINTER:返回给定所有集合的交集
  • SUNION:返回给定所有集合的并集
  • SDIFF:返回给定所有集合的差集
Set的应用场景
  1. 标签系统:Set类型可以用于实现标签功能,一个用户可以对应多个标签,多个用户也可以对应同一个标签。
String user1Tags = "user:1001:tags";
String user2Tags = "user:1002:tags";

// 给用户添加标签
jedis.sadd(user1Tags, "music", "travel");
jedis.sadd(user2Tags, "music", "sports");

// 获取用户共同感兴趣的标签
Set<String> commonTags = jedis.sinter(user1Tags, user2Tags);
  1. 抽奖活动:Set类型可以用于实现抽奖功能,将所有参与用户加入到一个Set中,然后随机抽取若干个用户作为中奖者。
String lotteryKey = "lottery:users";

// 将用户加入抽奖活动
jedis.sadd(lotteryKey, "user:1001", "user:1002", "user:1003");

// 随机抽取2名中奖者
List<String> winners = jedis.srandmember(lotteryKey, 2);

4. Zset(有序集合)

Zset类型(Sorted Set)是一个有序的,不重复的字符串集合。与Set类型不同,Zset中的每个成员都关联了一个评分(score),评分用于对成员进行排序。

Zset的常用命令
  • ZADD:向有序集合中添加一个或多个成员,或者更新已存在成员的评分
  • ZRANGE:返回有序集合中,指定区间内的成员,成员按评分值递增排序
  • ZREVRANGE:返回有序集合中,指定区间内的成员,成员按评分值递减排序
  • ZRANGEBYSCORE:返回有序集合中,所有评分介于min和max之间(包括等于min或max)的成员
  • ZRANK:返回有序集合中指定成员的排名
Zset的应用场景
  1. 排行榜:Zset类型可以用于实现各种排行榜功能,如商品销量排行、游戏玩家积分排名等。
String rankingKey = "sales:ranking";

// 添加商品销量数据
jedis.zadd(rankingKey, 100, "product:1001");
jedis.zadd(rankingKey, 80, "product:1002");
jedis.zadd(rankingKey, 120, "product:1003");

// 获取销量前3名的商品
Set<String> topProducts = jedis.zrevrange(rankingKey, 0, 2);
  1. 延时队列:利用Zset的评分值代表任务的执行时间,可以实现延时队列的功能。
String delayQueueKey = "delay:queue";

// 添加延时任务
long now = System.currentTimeMillis();
jedis.zadd(delayQueueKey, now + 60000, "task:1"); // 1分钟后执行
jedis.zadd(delayQueueKey, now + 300000, "task:2"); // 5分钟后执行

// 获取当前需要执行的任务
Set<String> tasks = jedis.zrangeByScore(delayQueueKey, 0, now);

5. Hash(哈希)

Redis的Hash类型可以看作是一个字符串字段(field)和字符串值(value)的映射表,特别适合用于存储对象。每个哈希可以存储多达232-1个键值对。

Hash的常用命令
  • HSET:将哈希表中的字段设置为指定值
  • HGET:获取存储在哈希表中指定字段的值
  • HMSET:同时将多个field-value对设置到哈希表中
  • HGETALL:获取在哈希表中指定key的所有字段和值
  • HINCRBY:为哈希表中的字段值加上指定增量值
Hash的应用场景
  1. 用户信息存储:Hash类型可以用于存储用户信息,每个用户对应一个Hash,包含用户的各种属性。
String userKey = "user:1001";

// 存储用户信息
jedis.hset(userKey, "name", "Tom");
jedis.hset(userKey, "age", "25");
jedis.hset(userKey, "city", "New York");

// 获取用户信息
Map<String, String> userInfo = jedis.hgetAll(userKey);
  1. 购物车:Hash类型可以用于实现购物车功能,每个用户的购物车对应一个Hash,商品ID作为field,商品数量作为value。
String cartKey = "cart:1001";

// 添加商品到购物车
jedis.hset(cartKey, "product:1001", "2");
jedis.hset(cartKey, "product:1002", "1");

// 增加商品数量
jedis.hincrBy(cartKey, "product:1001", 1);

// 获取购物车信息
Map<String, String> cart = jedis.hgetAll(cartKey);

缓存预热、雪崩 、穿透 、击穿

在这里插入图片描述

缓存预热

缓存预热是指在应用启动时,提前将一些热点数据加载到Redis缓存中,避免请求直接访问数据库,提高系统的响应速度。常见的缓存预热方式包括:

  • 使用@PostConstruct注解(Bean对象的生命周期第三阶段)
  • 第二种则是实现applicationRunner接口,重写run方法

推荐第二种 按照业务逻辑,我们需要加载完对应依赖,其他的Bean对象,再进行业务逻辑的处理

@Slf4j
@Component
public class StationDataInit implements ApplicationRunner {
    /**
     * 在项目启动前执行一些业务
     * 可以使用@PostConstruct注解  速度很快  但是不推荐
     * 推荐使用  实现 applicationRunner接口
     */

    // @PostConstruct
    @PostConstruct
    public void init() {
        log.debug("使用@PostConstruct注解实现在服务启动前去数据库里面获取信息");
    }
    
 	@Override
    public void run(ApplicationArguments args) throws Exception {
        log.debug("使用实现 applicationRunner接口实现在服务启动前去数据库里面获取信息");
        
        log.debug("从数据库里面获取所有的场站信息");
        List<StationPO> stationPOList = stationRepository.getAllStation();
        log.debug("获取数据存入到redis中");
     }

缓存雪崩

缓存雪崩是指在同一时段内大量的缓存key同时失效或Redis服务不可用,导致大量请求直接访问数据库,引起数据库压力骤增,甚至宕机。常见的解决方案包括:

  1. 给不同的Key设置不同的过期时间,避免同时失效。
  2. 利用Redis集群提高可用性。
  3. 给缓存的访问加上超时限制,避免数据库过载。
  4. 提前演练,确保数据库能够承受缓存全部失效的压力。
// 给不同的Key设置不同的过期时间
jedis.setex("key1", 3600, "value1");
jedis.setex("key2", 7200, "value2");
jedis.setex("key3", 10800, "value3");

// 利用Redis哨兵或集群提高可用性
JedisPoolConfig poolConfig = new JedisPoolConfig();
// ...
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
        .master("mymaster")
        .sentinel("127.0.0.1", 26379)
        .sentinel("127.0.0.1", 26380);
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(sentinelConfig, poolConfig);

缓存穿透

缓存穿透是指查询一个不存在的数据,因为不存在则不会写到缓存中,所以每次都会去请求数据库。如果大量的请求查询不存在的数据,就会给数据库带来很大的压力。常见的解决方案包括:

  1. 对不存在的key也缓存其value为null,设置较短的过期时间。
  2. 利用布隆过滤器快速判断key是否存在,避免缓存和数据库的查询。
// 缓存空值
String key = "non_existent_key";
String value = jedis.get(key);

if (value == null) {
    // 从数据库查询
    value = db.get(key);

    if (value == null) {
        // 数据库中也不存在,缓存空值,过期时间设置较短
        jedis.setex(key, 60, "");
    } else {
        // 数据库中存在,写入缓存
        jedis.setex(key, 3600, value);
    }
}

// 利用布隆过滤器判断key是否存在
BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), 1000000);

if (!bloomFilter.mightContain(key)) {
    // key不存在,直接返回
    return null;
} else {
    // key可能存在,查询缓存
    String value = jedis.get(key);
    if (value != null) {
        return value;
    } else {
        // 缓存未命中,查询数据库
        // ...
    }
}

缓存击穿

缓存击穿是指一个热点Key在某个时间点过期,而恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端数据库加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端数据库压垮。常见的解决方案包括:

  1. 使用互斥锁,只让一个线程构建缓存,其他线程等待缓存构建完毕后从缓存中读取数据。
  2. 不同的Key设置不同的过期时间,避免同时失效。
String lockKey = "lock:key";
String lockValue = UUID.randomUUID().toString();

String value = jedis.get(key);
if (value == null) {
    // 获取分布式锁
    if ("OK".equals(jedis.set(lockKey, lockValue, "NX", "EX", 30))) {
        // 获取锁成功,查询数据库
        value = db.get(key);
        
        // 写入缓存
        jedis.setex(key, 3600, value);
        
        // 释放锁
        if (lockValue.equals(jedis.get(lockKey))) {
            jedis.del(lockKey);
        }
    } else {
        // 获取锁失败,等待一段时间后重试
        Thread.sleep(100);
        value = jedis.get(key);
    }
}

总结

Redis凭借其出色的性能和丰富的数据类型,已经成为现代互联网应用不可或缺的利器。深入理解Redis的各种数据类型及其适用场景,并结合Java客户端进行开发,可以帮助我们设计出更加高效、可靠的系统。同时,在使用Redis时也要注意一些高级主题,如缓存预热、缓存雪崩、缓存穿透和缓存击穿等,这些都是保证系统稳定运行的关键。

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

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

相关文章

Linux安装JDK及配置环境变量超详细教程

微服务Linux解析部署使用全流程 linux系统的常用命令 Linux安装vim超详细教程 Linux安装tomcat及配置环境变量超详细教程 1、上传压缩包 统一创建目录&#xff1a;/usr/local/jdk&#xff0c;将压缩包上传到这个目录下。拖动文件到这个目录下即可。 2、执行解压命令 先进…

ELMO理论

目录 1 优点 2 缺点 3.知识点个人笔记 2018年3月份&#xff0c;ELMo出世&#xff0c;该paper是NAACL18 Best Paper。在之前2013年的word2vec及2014年的GloVe的工作中&#xff0c;每个词对应一个vector&#xff0c;对于多义词无能为力。ELMo的工作对于此&#xff0c;提出了一…

在 Gitlab 中使用 ChatGPT 进行 CodeReview

ChatGPT集成Gitlab&#xff0c;实现自动代码审计并进行评论&#xff0c;为软件开发团队提供高效、智能的代码审查解决方案。支持其他模型如通义千问等 自动触发与及时响应&#xff1a;利用Gitlab的Webhook功能&#xff0c;实现代码提交、合并请求和标签创建等事件的自动触发。一…

安全帽检测系统丨OPENAIGC开发者大赛高校组AI创作力奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

国产化低功耗低延时广覆盖物联网无线通讯方案_LAKI模组

01 物联网系统中为什么要使用LAKI模组。 物联网系统中使用LAKI模组的原因可以归结为以下几个方面&#xff1a; 技术先进性 广覆盖能力&#xff1a;LAKI模组具有卓越的广覆盖能力&#xff0c;其射频SoC芯片接收灵敏度小于-120dBm125kbps&#xff0c;系统通讯距离可达5千米以上…

一款好用的多种格式电子书制作软件

在数字化阅读日益普及的今天&#xff0c;电子书已经成为人们日常生活中不可或缺的一部分。而一款功能强大、操作简便的电子书制作软件&#xff0c;无疑是满足广大用户需求的最佳选择。 这款软件名为“FLBOOK在线制作电子杂志平台”&#xff0c;它支持多种格式输入&#xff0c;如…

设计模式、系统设计 record part02

软件设计模式&#xff1a; 1.应对重复发生的问题 2.解决方案 3.可以反复使用 1.本质是面向对象 2.优点很多 1.创建型-创建和使用分离 2.结构型-组合 3.行为型-协作 571123种模式 UML-统一建模语言-Unified Modeling Language 1.可视化&#xff0c;图形化 2.各种图&#xff08;9…

Python编程:08- pycharm使用技巧

新建文件时,自动填充代码 设置方法&#xff1a; settings→editor→file and code templates,选择python script #${NAME} 文件名 #${DATE} 日期自动补齐 if name ‘main’: # 先输入main,然后按tab键自动补齐自定义的段落 settings→editor→live templates,在右侧点击号…

C语言进阶版第12课—字符函数和字符串函数1

文章目录 1. 字符分类函数1.1 库函数iscntrl1.2 库函数isspace1.3 库函数islower和isupper 2. 字符转换函数3. strlen函数的使用和模拟实现3.1 strlen函数的使用3.2 strlen函数的模拟实现 4. strcpy函数的使用和模拟实现4.1 strcpy函数的使用4.2 strcpy函数的模拟实现 5. strca…

manim页面中不规则分割整个人页面。

界面中的分割方式 在信息设计中&#xff0c;我们常常需要通过分割设计的方式来对信息进行分组&#xff0c;界面中的分割方式大致分为三种&#xff1a;卡片、线条、留白。 界面中的分割方式主要可以分为以下几种&#xff1a; 一、根据规则进行分割&#xff1a; 规则网格分割&…

Starrocks with 嵌套

在某些场景下需要进行 with 嵌套 需要以下进行处理&#xff0c;报如图错误 with abc as (select * from .. ) insert into xxx select * from abc尝试创建物化视图 CREATE MATERIALIZED VIEW IF NOT EXISTS ads_test.xxx_mv REFRESH DEFERRED MANUAL AS with abc as (select…

C#基于SkiaSharp实现印章管理(9)

将印章设计模块设计的印章保存为图片并集中存放在指定文件夹内。新建印章应用项目&#xff0c;主要实现对图片及PDF文件加盖印章功能。本文实现给图片加盖印章功能。   给图片加盖印章的逻辑比较简单&#xff0c;就是将印章图片绘制到图片指定位置&#xff0c;使用SKControl控…

如何选择数据库架构

选择合适的数据库架构是一个复杂的过程&#xff0c;它取决于多种因素&#xff0c;包括应用程序的需求、数据量的大小、并发访问量、数据一致性要求、预算以及技术团队的熟悉程度等。以下是一些关键的步骤和考虑因素&#xff0c;帮助你选择合适的数据库架构&#xff1a; 1. 分析…

JITWatch安装使用方法

JITWatch 版本1.4.2 JDK 版本 11以上 1.下载JITWatch&#xff1a; https://github.com/AdoptOpenJDK/jitwatch/releases/download/1.4.2/jitwatch-ui-1.4.2-shaded-win.jar 2.启动 bat脚本执行&#xff1a;通过启动jar包方式启动JITWatch echo off start cmd /c "ti…

人工智能 实验1 Python语法

我发现了有些人喜欢静静看博客不聊天呐&#xff0c; 但是ta会点赞。 这样的人呢帅气低调有内涵&#xff0c; 美丽大方很优雅。 说的就是你&#xff0c; 不用再怀疑哦 实验1 Python语言基础一 【实验目的】掌握Python及其集成开发环境的下载安装及其简单应用 【实验内容…

结合了LLM(大语言模型)的编辑器,不仅能理解人类语言,还能与用户互动,仿佛有了自己的思想。...

从前有一个神奇的编辑器王国&#xff0c;那里住着各种编辑器&#xff1a;开源的、AI代码编辑器、视频编辑器&#xff0c;还有专门处理邮件和音频的编辑器。一天&#xff0c;国王Markdown决定举办一场盛会&#xff0c;邀请所有编辑器展示各自的才华。 开源编辑器们自豪地展示了他…

解决hbase和hadoop的log4j依赖冲突的警告

一、运行hbase的发现依赖冲突的警告 这警告不影响使用 二、重命名log4j文件 进入HBase的lib包下&#xff0c;将HBase的log4j文件重命名&#xff0c;改成备份&#xff0c;这样再次运行hbase的时候&#xff0c;就没有依赖冲突了。 三、冲突成功解决

数据分析工具julius ai如何使用

什么是julius ai Julius AI 是一款强大的ai数据分析工具。用户可以使用excel、数据库、文本文件等多种格式的数据&#xff0c;Julius AI 会自动分析这些数据并提供详细的解释和可视化图表。官网显示它目前已经有三十万用户。它也支持手机版。 虽然openai也支持生成图表&#xf…

研究生如何利用ChatGPT帮助开展日常科研工作?

小白可做&#xff01;全自动AI影视解说一键成片剪辑工具https://docs.qq.com/doc/DYnl6d0FLdHp0V2ll 作为当代研究生&#xff0c;科研工作三部曲----读文献、开组会、数据分析。无论哪一个&#xff0c;都令研究生们倍感头疼&#xff0c;简直就是梦魇。每当看到导师发来的消息&a…

Redis的主要特点及运用场景

Redis的主要特点及运用场景 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的高性能键值对&#xff08;key-value&#xff09;数据库。它支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、散列&#xff08;hashes&…