详解Redis,Redis缓存,Redis分布式锁(2)

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 详解Redis,Redis缓存,Redis分布式锁(2)

自定义Redis缓存实现

自定义缓存实现类

自定义MyBatis二级缓存


自定缓存类实现Cache接口

导入redis操作相关的工具(jar,JedisUtil,jedis.properties)

必须具备如下功能:

根据namepace划分缓存空间(id)


MyBatis二级缓存本质是一个Map结构


key :和执行的sql先关


value:查询结果相关


存放数据的功能: select语句(key)----查询结果(value)


获得数据的功能: 根据key


清空缓存的功能: clear

使用自定义的缓存

Session共享

为何要实现session共享?

nginx负载均衡,希望兼顾权重的按照硬件性能分配访问压力的优势,又想保证多个tomcat使用同一个session应该怎么解决?

  1. ip_hash
  2. session复制
  3. Redis

解决方案

使用redis管理负载均衡中多个tomcat的session.(Redis共享session)

如何实现Redis管理Session

配置步骤

  1. tomcat使用redis管理session的jar

将jar拷贝tomcat中lib

  1. 配置tomcat的session管理方式为RedisSessionManager
1. tomcat 配置文件context.xml
<!--注册session管理工具-->
<Manager className="session管理工具全类名"
         host="redis的ip地址"
         port="端口"
         maxInactiveInterval="session存活时间 秒 1800" 秒
         />
<!--将session管理工具使用在tomcat操作过程中-->
<Valve className="RedisSessionHandlerValve在tomcat中使用session管理工具"/>

重启两个tomcat

缓存问题

  1. 缓存穿透
  2. 缓存雪崩
User
根据主键查询 
key
1
2
3
4
5
6
7
8
9
1W  -id  缓存中都没有 
2000个查询  每秒 可以认为是安全的
缓存穿透

缓存击穿 大量不存在的key攻击

只需要极少的空间就可以判断一个元素是不是在一个集合之内,这正好是我们所需要的场景啊:判断key是否存在

解决方案

  1. 空值缓存 (非恶意攻击)
key  value
-1   null

布隆过滤器

可以判断key是否在数据库中存在

缺点:可能会判断出错 概率不高 但是会


缓存雪崩

微博

key = 鹿晗微博1  value = 相关信息 评论  追评 点赞 等
key = 鹿晗微博2  value = 相关信息 评论  追评 点赞 等
key = 鹿晗微博3  value = 相关信息 评论  追评 点赞 等
key = 鹿晗微博4  value = 相关信息 评论  追评 点赞 等
key = 鹿晗微博5  value = 相关信息 评论  追评 点赞 等
key = 吃瓜群众1 
key = 吃瓜群众2 
key = 吃瓜群众3 
key = 吃瓜群众4 
key = 吃瓜群众5
上千万key 这些key一定会设置失效 失效时间设置的不合理  同一时间大量key过期了(500W)  如果发生在平时 无所谓
不巧的是  上热搜了 突然间 大量的用户来访问 相关的信息

大量key同一时间失效 将导致不存在的数据每次请求都要到存储层去查询,失去了缓存保护后端存储的意义

大量流量 且数据失效 导致不存在的数据每次请求都要到存储层去查询 一模一样的SQL 数据库崩溃

  1. 合理的设置过期时间 单体架构
  2. 分布式锁
  3. 多级缓存

分布式的锁,谁获得了这把锁,谁就可以访问数据库

大型项目中

如果说用户查不到数据 降级服务

  1. 先等着 两三秒
  2. 能直接 返回固定数据
  3. 等等

7、Redis 分布式锁

什么是分布式锁

一种逻辑处理

Redis 分布式锁


分布式锁本质上要实现的目标就是在 Redis 里面占一个“茅坑”,当别的进程也要来占时,发现已经有人蹲在那里了,就只好放弃或者稍后再试。


占坑一般是使用 setnx(set if not exists) 指令,只允许被一个客户端占坑。先来先占, 用完了,再调用 del 指令释放茅坑。

// 这里的冒号:就是一个普通的字符,没特别含义,它可以是任意其它字符,不要误解
> setnx lock:codehole true
OK
... do something critical ...
> del lock:codehole
(integer) 1

但是有个问题,如果逻辑执行到中间出现异常了,可能会导致 del 指令没有被调用,这样就会陷入死锁,锁永远得不到释放。


于是我们在拿到锁之后,再给锁加上一个过期时间,比如 5s,这样即使中间出现异常也可以保证 5 秒之后锁会自动释放。

> setnx lock:codehole true
OK
> expire lock:codehole 5
... do something critical ...
> del lock:codehole
(integer) 1

但是以上逻辑还有问题。如果在 setnx 和 expire 之间服务器进程突然挂掉了,可能是因为机器掉电或者是被人为杀掉的,就会导致 expire 得不到执行,也会造成死锁。


这种问题的根源就在于 setnx 和 expire 是两条指令而不是原子指令。如果这两条指令可以一起执行就不会出现问题。也许你会想到用 Redis 事务来解决。但是这里不行,因为 expire 是依赖于 setnx 的执行结果的,如果 setnx 没抢到锁,expire 是不应该执行的。事务里没有 if-else 分支逻辑,事务的特点是一口气执行,要么全部执行要么一个都不执行。


为了解决这个疑难,Redis 开源社区涌现了一堆分布式锁的 library,专门用来解决这个问题。实现方法极为复杂,小白用户一般要费很大的精力才可以搞懂。如果你需要使用分布式锁,意味着你不能仅仅使用 Jedis 或者 redis-py 就行了,还得引入分布式锁的 library。


为了治理这个乱象,Redis 2.8 版本中作者加入了 set 指令的扩展参数,使得 setnx 和 expire 指令可以一起执行,彻底解决了分布式锁的乱象。从此以后所有的第三方分布式锁 library 可以休息了。

> set lock:codehole true ex 5 nx
OK
... do something critical ...
> del lock:codehole

上面这个指令就是 setnx 和 expire 组合在一起的原子指令,它就是分布式锁的奥义所在。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
11天前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
30 2
基于Redis的高可用分布式锁——RedLock
|
9天前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
23 0
|
4天前
|
缓存 NoSQL 关系型数据库
MySQL与Redis缓存一致性的实现与挑战
在现代软件开发中,MySQL作为关系型数据库管理系统,广泛应用于数据存储;而Redis则以其高性能的内存数据结构存储特性,常被用作缓存层来提升数据访问速度。然而,当MySQL与Redis结合使用时,确保两者之间的数据一致性成为了一个重要且复杂的挑战。本文将从技术角度分享MySQL与Redis缓存一致性的实现方法及其面临的挑战。
17 2
|
6天前
|
Java UED Maven
紧跟技术潮流:手把手教你构建响应式Vaadin应用,让用户体验无缝接轨!
【8月更文挑战第31天】本文从零开始,详细介绍如何使用强大的Java框架Vaadin构建流畅且响应式的Web应用程序。首先,确保安装JDK 1.8+、Maven 3.3.9+及IDE。接着,创建Maven项目并添加Vaadin依赖。然后,通过继承`UI`类创建主界面,并定义自定义主题与样式。利用Vaadin的响应式布局组件,如`HorizontalLayout`和`VerticalLayout`,实现多设备兼容性。
14 0
|
9天前
|
缓存 NoSQL Java
惊!Spring Boot遇上Redis,竟开启了一场缓存实战的革命!
【8月更文挑战第29天】在互联网时代,数据的高速读写至关重要。Spring Boot凭借简洁高效的特点广受开发者喜爱,而Redis作为高性能内存数据库,在缓存和消息队列领域表现出色。本文通过电商平台商品推荐系统的实战案例,详细介绍如何在Spring Boot项目中整合Redis,提升系统响应速度和用户体验。
36 0
|
13天前
|
缓存 NoSQL 网络安全
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
|
13天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
13天前
|
存储 缓存 NoSQL
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
|
13天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redis 连接失败
【Azure Redis 缓存】Redis 连接失败
|
13天前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Lettuce 连接到Azure Redis服务,出现15分钟Timeout问题
【Azure Redis 缓存】Lettuce 连接到Azure Redis服务,出现15分钟Timeout问题
【Azure Redis 缓存】Lettuce 连接到Azure Redis服务,出现15分钟Timeout问题
下一篇
DDNS