五、Java应⽤连接Redis

5.1 设置redis允许远程连接

Java应⽤连接Redis,⾸先要将我们的Redis设置允许远程连接

  • 修改redis-6379.conf

    ## 关闭保护模式
    protected-mode no
    ## 将bind注释掉(如果不注释,默认为 bind 127.0.0.1 只能本机访问)
    # bind 127.0.0.1
    ## 密码可以设置(也可以不设置)
    # requirepass 123456
    
  • 重启redis

    redis-server redis-6379.conf
    
  • 在宝塔面板放行 6379端口

5.1 在普通Maven⼯程连接Redis

使⽤jedis客户端连接

5.1.1 添加Jedis依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.3</version></dependency>

5.1.2 使⽤案例

public static void main(String[] args) {Product product = new Product("101", "aaaa", 2.5);//1.连接redisJedis jedis = new Jedis("ajie.jimo.fun", 6379);//2.操作String s = jedis.set(product.getProductId(), newGson().toJson(product));System.out.println(s);//3.关闭连接jedis.close();
}

5.1.3 redis远程可视化客户端

Redis desktop manager

5.2 在SpringBoot⼯程连接Redis

Spring Data Redis依赖中,提供了⽤于连接redis的客户端:

  • RedisTemplate
  • StringRedisTemplate

5.2.1 创建springBoot应⽤

5.2.2 配置redis

application.yml⽂件配置redis的连接信息

spring:redis:host: ajie.jimo.funport: 6379database: 0password: 8023zsj

5.2.3 使⽤redis客户端连接redis

直接在service中注⼊ RedisTemplate 或者 StringRedisTemplate ,就可以使⽤此对象完成redis操作

5.3 Spring Data Redis

5.3.1 不同数据结构的添加操作

//1.string
//添加数据 set key value
stringRedisTemplate.boundValueOps(product.getProductId()).set(jsonstr);
//2.hash
stringRedisTemplate.boundHashOps("products").put(product.getProductId(),jsonstr);
//3.list
stringRedisTemplate.boundListOps("list").leftPush("ccc");
//4.set
stringRedisTemplate.boundSetOps("s1").add("v2");
//5.zset
stringRedisTemplate.boundZSetOps("z1").add("v1",1.2);

5.3.2 string类型的操作⽅法

//添加数据 set key value
stringRedisTemplate.boundValueOps(product.getProductId()).set(
jsonstr);
//添加数据时指定过期时间 setex key 300 value
stringRedisTemplate.boundValueOps("103").set(jsonstr,300);
//设置指定key的过期时间 expire key 20
stringRedisTemplate.boundValueOps("103").expire(20, TimeUnit.SECONDS);
//添加数据 setnx key value
Boolean absent =stringRedisTemplate.boundValueOps("103").setIfAbsent(jsonstr);

5.3.3 不同数据类型的取值操作

//string
String o = stringRedisTemplate.boundValueOps("103").get();
//hash
Object v = stringRedisTemplate.boundHashOps("products").get("101");
//list
String s1 = stringRedisTemplate.boundListOps("list").leftPop();
String s2 = stringRedisTemplate.boundListOps("list").rightPop();
String s3 = stringRedisTemplate.boundListOps("list").index(1);
//set
Set<String> vs = stringRedisTemplate.boundSetOps("s1").members();
//zset
Set<String> vs2 = stringRedisTemplate.boundZSetOps("z1").range(0, 5);

六、使⽤redis缓存数据库数据

6.1 redis作为缓存的使⽤流程

6.2 在使⽤redis缓存商品详情(锋迷商城)

6.2.1 在service⼦⼯程添加Spring data redis依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

6.2.2 在application.yml配置redis数据源

spring:datasource:druid:driver-class-name: com.mysql.jdbc.Driver## 如果后端项⽬服务器和数据库服务器不在同⼀台主机,则需要修改localhost为数据库服务器ip地址url: jdbc:mysql://localhost:3306/fmmall?characterEncoding=utf-8username: rootpassword: admin123redis:port: 6379host: 47.96.11.185database: 0password: 123456

6.3.3 在ProductServiceImpl中修改业务代码

七、使用Redis做缓存使用存在的问题

使用redis作为缓存在高并发场景下有可能出现缓存击穿,缓存穿透,缓存雪崩

7.1 缓存击穿

大量的并发访问同时访问同一个redis中不存在的数据,就会导致大量请求绕过redis同时并访问数据库,对数据库造成高并发的压力

  • 使用双重检测锁解决缓存击穿

      private ObjectMapper objectMapper = new ObjectMapper();private Logger logger = LoggerFactory.getLogger(IndexImgServiceImpl.class);@Override
    public ResultVO listIndexImgs() {//双重检测锁 防止缓存击穿List<IndexImg> indexImgs = null;try {//string 结构缓存轮播图信息String imgsStr = stringRedisTemplate.boundValueOps("indexImgs").get();if (imgsStr != null) {//如果redis中有轮播图信息JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, IndexImg.class);indexImgs = objectMapper.readValue(imgsStr, javaType);} else {//1000个请求都会进入else   (service在 Spring 容器中是单例的  会共用一个service实例)synchronized (this) {//第二次查询redisString s = stringRedisTemplate.boundValueOps("indexImgs").get();if (s == null) {//只有第一次请求redis s 才为空//如果redis没中有轮播图信息 从数据库查询indexImgs = indexImgMapper.listIndexImgs();logger.info("查询数据库");//存入redisstringRedisTemplate.boundValueOps("indexImgs").set(objectMapper.writeValueAsString(indexImgs));//设置过期时间stringRedisTemplate.boundValueOps("indexImgs").expire(1, TimeUnit.DAYS); } else {JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, IndexImg.class);indexImgs = objectMapper.readValue(s, javaType);}}}} catch (JsonProcessingException e) {e.printStackTrace();}//返回数据if (indexImgs == null) {return new ResultVO(ResStatus.NO, "fail", null);} else {return new ResultVO(ResStatus.OK, "success", indexImgs);}
    }
    

7.2 缓存穿透

大量请求一个数据库不存在的数据,首先在redsi中无法查询,最终所有的请求都会访问数据库,同样会导致数据库承担巨大的访问压力。

  • 解决⽅案:当从数据库查询到⼀个null时,写⼀个⾮空的数据到redis,并设置过期时间

7.3 缓存雪崩

缓存雪崩:缓存大量的数据集中过期,导致请求这些数据的大量并发请求同属访问数据库

解决方案:

  • 将缓存中的数据设置成不同的过期时间
  • 在访问洪峰到达前缓存热点,过期时间设置成流量最低的时段

7.4 Jmeter测试

Jmeter是基于Java开发的⼀个测试⼯具,因此需要先安装JDK

7.4.1 创建测试计划

7.4.2 创建线程组

7.4.3 设置HTTP请求

⼋、Redis⾼级应⽤

使⽤redis作为缓存数据库使⽤⽬的是为了提升数据加载速度、降低对数据库的访问压⼒,我们需要保证redis的可⽤性。

  • 主从配置
  • 哨兵模式
  • 集群配置

8.1 主从配置

主从配置:在多个redis实例建⽴起主从关系,当 主redis 中的数据发⽣变化, 从redis中的数据也会同步变化。

  • 通过主从配置可以实现redis数据的备份( 从redis 就是对 主redis 的备份),保证数据的安全性;
  • 通过主从配置可以实现redis的读写分离

主从配置示例

## 在redis-5.0.5⽬录下创建 msconf ⽂件夹
mkdir msconf
## 拷⻉redis.conf⽂件 到 msconf⽂件夹 ---> redis-master.conf
cat redis.conf | grep -v "#" | grep -v "^$" > msconf/redis-master.conf
## 修改 redis-master.conf 端⼝及远程访问设置
vim redis-master.conf

## 将 redis-master.conf 拷⻉两份分别为:redis-slave1.conf redisslave2.conf
sed 's/6380/6381/g' redis-master.conf > redisslave1.conf
sed 's/6380/6382/g' redis-master.conf > redisslave2.conf
## 修改redis-slave1.conf redis-slave2.conf,设置“跟从”---127.0.0.1 6380
vim redis-slave1.conf
vim redis-slave2.conf

## 启动三个redis实例
redis-server redis-master.conf &
redis-server redis-slave1.conf &
redis-server redis-slave2.conf &

8.2 哨兵模式

哨兵模式:⽤于监听主库,当确认主库宕机之后,从备库(从库)中选举⼀个转备为主

哨兵模式配置

##⾸先实现三个redis实例之间的主从配置(如上)
## 创建并启动三个哨兵
## 拷⻉sentinel.conf⽂件三份:sentinel-26380.conf sentinel-26382.conf
sentinel-26382.conf
## 创建sentinelconf⽬录
mkdir sentinelconf
## 拷⻉sentinel.conf⽂件到 sentinelconf⽬录:sentinel-26380.conf
cat sentinel.conf | grep -v "#" | grep -v "^$" > sentinelconf/sentinel-26380.conf
cd sentinelconf/
vim sentinel-26380.conf
port 26380
daemonize no
pidfile "/var/run/redis-sentinel-26380.pid"
logfile ""
dir "/tmp"
sentinel deny-scripts-reconfig yes
# 此处配置默认的主库的ip 和端⼝ 最后的数字是哨兵数量的⼀半多⼀个
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
protected-mode no
sed 's/26380/26381/g' sentinel-26380.conf > sentinel-26381.conf
sed 's/26380/26382/g' sentinel-26380.conf > sentinel-26382.conf

8.3 集群配置

**⾼可⽤:**保证redis⼀直处于可⽤状态,即时出现了故障也有备⽤⽅案保证可⽤性

**⾼并发:**⼀个redis实例已经可以⽀持多达11w并发读操作或者8.1w并发写操作;但是如果对于有更⾼并发需求的应⽤来说,我们可以通过 读写分离 、 集群配置 来解决⾼并发问题

Redis集群

  • Redis集群中每个节点是对等的,⽆中⼼结构
  • 数据按照slots分布式存储在不同的redis节点上,节点中的数据可共享,可以动态调整数据的分布
  • 可扩展性强,可以动态增删节点,最多可扩展⾄1000+节点
  • 集群每个节点通过主备(哨兵模式)可以保证其⾼可⽤性

8.3.1 集群搭建

[root@theo ~]# cd /usr/local/redis-5.0.5
[root@theo redis-5.0.5]# mkdir cluster-conf
[root@theo redis-5.0.5]# cat redis.conf | grep -v "#"|grep -v "^$" >
cluster-conf/redis-7001.conf
[root@theo redis-5.0.5]# cd cluster-conf/
[root@theo cluster-conf]# ls
redis-7001.conf
[root@theo cluster-conf]# vim redis-7001.conf

  • 拷⻉6个⽂件,端⼝分别为 7001-7006

    [root@theo cluster-conf]# sed 's/7001/7002/g' redis-7001.conf > redis-7002.conf
    [root@theo cluster-conf]# sed 's/7001/7003/g' redis-7001.conf > redis-7003.conf
    [root@theo cluster-conf]# sed 's/7001/7004/g' redis-7001.conf > redis-7004.conf
    [root@theo cluster-conf]# sed 's/7001/7005/g' redis-7001.conf > redis-7005.conf
    [root@theo cluster-conf]# sed 's/7001/7006/g' redis-7001.conf > redis-7006.conf
    
  • 启动6个redis实例

    [root@theo cluster-conf]# redis-server redis-7001.conf &
    [root@theo cluster-conf]# redis-server redis-7002.conf &
    [root@theo cluster-conf]# redis-server redis-7003.conf &
    [root@theo cluster-conf]# redis-server redis-7004.conf &
    [root@theo cluster-conf]# redis-server redis-7005.conf &
    [root@theo cluster-conf]# redis-server redis-7006.conf &
    
  • 查看6个实例是否启动

    ps -ef|grep redis
    
  • 启动集群

     redis-cli --cluster create 47.96.11.185:700147.96.11.185:7002 47.96.11.185:7003 47.96.11.185:7004 47.96.11.185:700547.96.11.185:7006 --cluster-replicas 1
    

  • 连接集群:

     redis-cli -p 7001 -c
    

8.3.2 集群管理

  • 如果集群启动失败:等待节点加⼊ (出现很多点点点)

    • 云服务器检查安全组是否放⾏redis实例端⼝,以及+10000的端⼝
    • Linux防⽕墙是否放⾏redis服务(关闭防⽕墙)
    • Linux状态(top)---- 更换云主机操作系统
    • redis配置⽂件错误
  • 创建集群:

    edis-cli --cluster create
    47.96.11.185:7001 47.96.11.185:7002 47.96.11.185:7003
    47.96.11.185:7004 47.96.11.185:7005 47.96.11.185:7006 --clusterreplicas 1
    
  • 查看集群状态

     redis-cli --cluster info 47.96.11.185:7001
    
  • 平衡节点的数据槽数

     redis-cli --cluster rebalance47.96.11.185:7001
    
  • 迁移节点槽

  • 删除节点

    [root@theo cluster-conf]# redis-cli --cluster del-node
    47.96.11.185:7001 4678478aa66b6d37b23944cf7db0ac07298538a4
    >>> Removing node 4678478aa66b6d37b23944cf7db0ac07298538a4 from
    cluster 47.96.11.185:7001
    >>> Sending CLUSTER FORGET messages to the cluster...
    >>> SHUTDOWN the node.
    [root@theo cluster-conf]# redis-cli --cluster info 47.96.11.185:7002
    47.96.11.185:7002 (e26eaf2a...) -> 1 keys | 8192 slots | 2 slaves.
    47.96.11.185:7003 (5752eb20...) -> 2 keys | 8192 slots | 1 slaves.
    [OK] 3 keys in 2 masters.
    0.00 keys per slot on average.
    
  • 添加节点

     redis-cli --cluster add-node 47.96.11.185:7007 47.96.11.185:7002
    

8.3.3 SpringBoot应⽤连接集群

  • 添加依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  • 配置集群节点

    spring:redis:cluster:nodes: 47.96.11.185:7001,47.96.11.185:7002,47.96.11.185:7003max-redirects: 3
    
  • 操作集群

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = RedisDemo3Application.class)
    class RedisDemo3ApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid contextLoads() {//stringRedisTemplate.boundValueOps("key1").set("value1");String s = stringRedisTemplate.boundValueOps("key1").get();System.out.println(s);}
    }

九、Redis淘汰策略

Redis是基于内存结构进⾏数据缓存的,当内存资源消耗完毕,想要有新的数据缓存进来,必然要从Redis的内存结构中释放⼀些数据。如何进⾏数据的释放呢?----Redis的淘汰策略

Redis提供的8中淘汰策略

理解两个算法名词

LRU 最久最近未使⽤

LFU 最近最少使⽤

# volatile-lru -> 从设置了过期时间的数据中淘汰最久未使⽤的数据.
# allkeys-lru -> 从所有数据中淘汰最久未使⽤的数据.
# volatile-lfu -> 从设置了过期时间的数据中淘汰使⽤最少的数据.
# allkeys-lfu -> 从所有数据中淘汰使⽤最少的数据.
# volatile-random -> 从设置了过期时间的数据中随机淘汰⼀批数据.
# allkeys-random -> 从所有数据中随机淘汰⼀批数据.
# volatile-ttl -> 淘汰过期时间最短的数据.
# noeviction -> 不淘汰任何数据,当内存不够时直接抛出异常.

⼗、Redis⾼频⾯试题

  1. 在项⽬中redis的使⽤场景

⽤于缓存⾸⻚数据

  1. Redis的持久化策略

  2. Redis⽀持的数据类型

  3. 如何保证redis的⾼可⽤

    • Redis⽀持持久化,同时开启rdb 和 aof ,以保证数据的安全性(还是存在数据丢失⻛险的)
    • Redis⽀持主从配置,我们可通配置哨兵,实现主备配置,保证可⽤性
    • Redis也⽀持集群,通过集群配置可以保证redis的⾼并发
  4. 你刚才提到了redis集群,请问如何解决redis集群的脑裂问题?

  5. redis中的数据可以设置过期时间,当数据过期之后有些key并没有及时清除,请问如何处理?

redis的高级应用相关推荐

  1. Redis进阶实践之五Redis的高级特性

    一.引言 上一篇文章写了Redis的特征,使用场景,同时也介绍了Redis的基本数据类型,redis的数据类型是操作redis的基础,这个必须好好的掌握.今天我们开始介绍一些Redis的高级特性,虽然 ...

  2. 黑马Redis笔记高级篇 | 多级缓存

    黑马Redis笔记高级篇 | 多级缓存(黑马教程云服务器踩坑记录) 1.JVM进程缓存(tomcat服务内部) 1.1 导入商品案例 1.2 初识Caffeine 1.3 实现进程缓存 2.Lua语法 ...

  3. 06_NoSQL数据库之Redis数据库:Redis的高级应用之登录授权和主从复制

     Redis高级实用特征 安全性(登录授权和登录后使用auth授权) 设置客户端连接后进行任何其他指定前需要使用的密码. 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户 ...

  4. Redis基础高级学习笔记

    笔记 https://github.com/7117/note/tree/master/Redis https://blog.csdn.net/m0_46130323/category_9645862 ...

  5. redis php高级使用_项目中应用Redis+Php的场景

    前言 一些案例中有的同学说为什么不可以用string类型,string类型完全可以实现呀 我建议你看下我的专栏文章<Redis高级用法>,里面介绍了用hash类型的好处 商品维度计数 对商 ...

  6. Redis的高级特性

    目录 高级数据类型 支持事务 支持Lua脚本 支持pipeline 管道|流水线 支持发布/订阅 可实现异步队列 | 消息队列 高级数据类型 1.Bitmap 位图 按 bit 位存储信息,常用于实现 ...

  7. redis必杀高级:性能测试

    题记: Redis 性能测试是通过同时执行多个命令实现的. 语法:redis 性能测试的基本命令如下: redis-benchmark [option] [option value] 例如: 同时执行 ...

  8. 分布式锁的应用场景_分布式缓存技术Redis:高级应用(主从、事务与锁、持久化)...

    安全性设置 设置客户端操作秘密 redis安装好后,默认情况下登陆客户端和使用命令操作时不需要密码的.某些情况下,为了安全起见,我们可以设置在客户端连接后进行任何操作之前都要进行密码验证.修改redi ...

  9. Redis的高级特性哨兵

    一.哨兵介绍 Redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入.哨兵的核心功能是主节点的自动故障转移.下面是Redis官方文档对于哨兵功能的描述: 监控(Monitor ...

  10. 07_NoSQL数据库之Redis数据库:Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存

     事务处理 Redis对事务的支持目前还比较简单.Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令.当一个client在一个连接中发出mul ...

最新文章

  1. python语言是什么时候诞生的_python诞生于什么时候
  2. GRE难句典型结构2
  3. linux查看证书位数,查看Linux系统是32位还是64位(getconf WORD_BIT误区)
  4. C++ using的三种使用策略以及具体的用法
  5. Android 使用webview遇到的问题及解决办法
  6. android四大组件小整
  7. java设计app_一个APP的诞生——从零开始设计你的手机应用
  8. C语言记录元音字母的位置,求元音字母
  9. spark入门(1)
  10. nc加载不了java,用友NC系统使用过程中常见问题和解决方法
  11. 抓包工具Fiddler下载安装
  12. ESP32 驱动WS2812B 灯条
  13. 抖音怎么开直播?抖音开播流程介绍
  14. MacOS编译LibreCAD
  15. C++中的字符串的定义方式
  16. ESPHome 和 Home Assistant点灯握手
  17. 罗丹明RB/四甲基罗丹明标记软骨素chondroitin, Rhodamine B/TRITC labeled;Rhodamine B/TRITC-chondroitin
  18. 获取微信用户信息java开发_Java微信公众平台开发(十二)--微信用户信息的获取
  19. IBM system x5服务器利用webBios 配置磁盘阵列RAID
  20. 【渝粤题库】广东开放大学 大学英语1 形成性考核

热门文章

  1. 会计英文(中英文对照)
  2. CSS 滚动快照 Scroll Snap
  3. 2008-09赛季NBA直播表(cctv5 广东体育)
  4. 我的2016:做精彩的自己
  5. 华为手机备忘录怎样设置每个月12号短信提醒要做的事
  6. 地图和地理空间革命:地理学大规模开放在线课堂(MOOC)
  7. [WINDOWS]多个文本文件内容合并到一个文本文件中
  8. 手机端Alook浏览器手动抓取京东Cookie教程
  9. ERR wrong number of arguments for ‘srem‘ command
  10. Docker Compose方式安装GitLab