Redis 缓存 & 分布式锁

缓存

Redis最主要的使用场景就是作为缓存

缓存的更新策略:

1.定期生成

2.实时生成

面试重点:

缓存预热(Cache preheating):

缓存穿透(Cache penetration)

缓存雪崩 (Cache avalanche)

缓存击穿 (Cache breakdown)

分布式锁

分布式锁的基本实现:

引入过期时间:

引入校验Id:

引入lua脚本:

引入watch dog(看门狗)

引入Redlock算法:

缓存

核心思路就是把⼀些常见的数据放到触手可及(访问速度更快)的地方, 方便随时读取.

访问速度特别的快,但由于存储空间是有限的,所有我们只能存储“热点数据”(频繁访问的数据)在Redis中
俗称“二八定律”:20%的热点数据,可以应对80%的应用场景,从而整体上的性能得到提升

Redis最主要的使用场景就是作为缓存
对应MySQL这种访问硬盘的数据库,Redis是内存数据库,Redis用做为MySQL的缓存

为什么MySQL性能不高?

1.首先数据存储在硬盘上,硬盘IO需要花费大量时间,尤其是随机访问;

2.如果查询中不能命中索引,那么将需要表的遍历,大大增加硬盘IO的次数

3.对应执行SQL需要一系列的解析,校验等等工作

4.如果是一些复杂查询,例如联合查询,笛卡尔积之类的操作效率会很低…

如果数据库并发量特别高,那么它将会可能出现宕机(出现故障,罢工了,不做了)的情况

如何解决?

1.开源:增加多个设备,部署更多的数据库机器,构成数据库集群

2.节流:引入缓存,访问的时候尽量访问缓存内的数据,从而降低直接访问数据库的请求数量

实际开发中,往往是俩种方法结合起来使用

Redis为什么可以作为MySQL的缓存:

R

### Redis 缓存分布式锁和限流的使用场景与示例 #### 1. Redis 缓存 Redis 是一种高性能的内存键值存储系统,常用于缓存以提升系统的响应速度和吞吐量。以下是 Redis 缓存在不同场景中的具体应用: ##### 场景描述 - **减少数据库压力**:通过将频繁访问的数据存储在 Redis 中,可以显著降低数据库查询次数[^1]。 - **提高读取性能**:由于 Redis 数据驻留在内存中,因此它的读写速度远高于传统的关系型数据库。 ##### 示例代码 ```java // 获取 Redis 客户端连接 Jedis jedis = new Jedis("localhost", 6379); // 设置缓存数据 jedis.setex("user:1000:name", 3600, "John Doe"); // 查询缓存数据 String userName = jedis.get("user:1000:name"); if (userName == null) { // 如果缓存未命中,则从数据库获取并更新缓存 String dbUserName = fetchFromDatabase("SELECT name FROM users WHERE id=1000;"); jedis.setex("user:1000:name", 3600, dbUserName); } else { System.out.println("Cache Hit! User Name: " + userName); } jedis.close(); ``` --- #### 2. Redis 分布式锁 分布式锁是一种协调多个节点间共享资源访问的技术手段,确保同一时间内只有一个进程能持有并对资源进行操作。以下是 Redis 实现分布式锁的一些常见方式及其适用场景: ##### 场景描述 - **防止重复下单**:在一个电商系统中,用户可能因网络延迟等原因多次提交订单请求。通过分布式锁可以有效避免这种情况的发生[^2]。 - **秒杀活动控制**:为了保障库存准确性,在高并发环境下对商品购买加是非常重要的措施之一。 ##### 示例代码(基于 SETNX) ```java Jedis jedis = new Jedis("localhost", 6379); String lockKey = "lock:product:123"; String uniqueValue = UUID.randomUUID().toString(); boolean isLocked = false; try { Long result = jedis.setnx(lockKey, uniqueValue); if (result != null && result.equals(1L)) { // 成功获得 isLocked = true; jedis.expire(lockKey, 10); // 设置过期时间为10秒以防死 // 执行业务逻辑... System.out.println("Lock acquired and processing..."); } else { System.out.println("Failed to acquire lock."); } } finally { if (isLocked && uniqueValue.equals(jedis.get(lockKey))) { jedis.del(lockKey); // 删除 } jedis.close(); } ``` --- #### 3. Redis 限流 限流是指限制单位时间内某项服务或接口所能接受的最大请求数量,主要用于保护后端服务器免受流量洪峰冲击。下面列举了几种常见的 Redis 限流策略及其实现方法: ##### 场景描述 - **IP 访问频率限制**:针对恶意爬虫或者异常高频次访问的情况实施防护机制[^4]。 - **API 请求速率管控**:合理分配 API 资源配额,保证服务质量的同时兼顾公平性原则。 ##### 示例代码(令牌桶算法) ```java Jedis jedis = new Jedis("localhost", 6379); String rateLimitKey = "rate_limit:user:100"; long currentTimeMillis = System.currentTimeMillis(); long lastRefillTime = jedis.exists(rateLimitKey) ? Long.parseLong(jedis.hget(rateLimitKey, "last_refill")) : currentTimeMillis; // 计算已过去的时间间隔 double elapsedSeconds = (currentTimeMillis - lastRefillTime) / 1000.0; int tokensAdded = (int)(elapsedSeconds * 10); // 每秒补充10个token int currentTokens = Math.min(Integer.parseInt(jedis.hget(rateLimitKey, "tokens")), 100); currentTokens += tokensAdded; if(currentTokens >= Integer.parseInt(jedis.hget(rateLimitKey,"max_tokens"))) { currentTokens=Integer.parseInt(jedis.hget(rateLimitKey,"max_tokens")); } if(currentTokens>0){ jedis.hmset(rateLimitKey, Map.of( "tokens", String.valueOf(--currentTokens), "last_refill", String.valueOf(currentTimeMillis)) ); }else{ throw new RuntimeException("Rate limit exceeded!"); } System.out.println("Request allowed with "+currentTokens+" remaining."); jedis.close(); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值