超级详细的易懂的Redis缓存用法,快来看看吧

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 说明:使用缓存的目的主要就是为了降低用户访问无论设备的频次,从缓存服务器中直接获取数据,快速的响应用户,提高整体的查询速度,用户体验更好

1.Redis缓存机制的介绍

说明:使用缓存的目的主要就是为了降低用户访问无论设备的频次,从缓存服务器中直接获取数据,快速的响应用户,提高整体的查询速度,用户体验更好


如何实现:


缓存机制采用的是K-V的数据存储结构,K必须唯一

使用C语言进行开发

缓存的运行环境是内存

内存断电及擦除,为了保证数据的安全性,实现持久化(写入磁盘)操作

内存中数据不能存的问题利用内存优化的算法(LRU)进行解决

2.Redis介绍

Redis是一个开源(DBS许可)的,内存中的数据结构存储系统,他可以用作数据库,缓存和消息中间件,他支持多种类型的数据结构,如字符串(String),散列表(hashes),列表(lists),集合(sets),有序集合(sorted sets)与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。


Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability).

速度快:

tomcat: 150-220/秒

nginx: 3-5万/秒

redis: 写 8.6万/秒 读 11.2万/秒 ~ 平均10万次/秒


3.Redis常规命令

要求:进入redis根目录中执行.

特点:redis每次启动时都会读取配置文件. 如果需要准备多台redis则需要准备多个配置文件


1.启动命令:redis-server redis.conf

redis没有开启后台运行效果


029622241618b14676b6a23f3aa46ee1_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDAxMDAy,size_16,color_FFFFFF,t_70.png


2.开启后台运行:redis-server redis.conf

872a87ba07cb7dfcd83b744753942db5_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDAxMDAy,size_16,color_FFFFFF,t_70.png


3.检索Redis服务:ps -ef | grep redis

8c5d6f75a25501535d26cdc8dd7a1fd4_20200901195408167.png


4.进入Redis客户端:redis-cli -p 端口号

9dc692785a08b6761100e6f944bd9d24_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDAxMDAy,size_16,color_FFFFFF,t_70.png


5.关闭Redis

方式一:redis-cli -p 6379 shutdown


方式二:

c4c7926a6a3b5ddd9285801b8d484bce_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDAxMDAy,size_16,color_FFFFFF,t_70.png



4.Redis入门案例

4.1添加jar包


<!--spring整合redis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>

4.2编辑测试API

package com.jt.test;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
//@SpringBootTest //需要依赖spring容器,从容器中动态的获取对象
public class TestRedis {
    /**
     * 完成Redis入门案例测试
     * 报错说明:
     *      1.检查Linux防火墙
     *      2.检查Redis3项配置
     *      3.重启redis.
     */
    @Test
    public void test01(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        //1.向redis中保存数据
        jedis.set("2004", "哈哈哈 今天下雨了 不负众望");
        //2.从redis中获取数据
        String value = jedis.get("2004");
        System.out.println(value);
    }
    @Test
    public void test02(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        //1.判断redis中是否存在key
        if(jedis.exists("2004")){
            //2.如果存在则设定超时时间
            jedis.expire("2004", 100);
            //3.线程暂停2秒
            try {
                Thread.sleep(2000);
                //4.获取剩余的存活时间
                Long time = jedis.ttl("2004");
                System.out.println("还能活:"+time);
                //5.撤销删除操作
                jedis.persist("2004");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 需求说明:
     *  1.redis.set操作,后面的操作会将之前的value覆盖
     *  要求:如果key已经存在,则不允许赋值.
     *  注意环境: 检查redis中是否有改数据.
     *  */
    @Test
    public void test03() {
        //A  潘石屹    B 马云
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.flushAll();   //清空redis缓存
        //如果key存在则不执行赋值操作.
        jedis.setnx("boss", "潘石屹");
        jedis.setnx("boss", "马云");
        System.out.println(jedis.get("boss"));
    }
    /**
     * 为数据添加超时时间.保证原子性操作
     * 原子性: 一起完成一起回滚
     * 锁机制: 保证原子性   死锁!!!!
     * 小结: setnx 如果key存在则不赋值
     *       setex  保证原子性操作,并且添加超时时间.
     * * */
    @Test
    public void test04() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.setex("aaa", 20, "xxxxx"); //满足原子性需求.
    }
    /**
     * 需求:
     *  1.要求赋值操作时,如果数据已经存在则不允许赋值.
     *  2.同时要求添加超时时间 并且满足原子性要求.
     *   private static final String XX = "xx";   只有key存在时,才能赋值
     *   private static final String NX = "nx";   只有key不存在时,赋值
     *   private static final String PX = "px";   毫秒
     *   private static final String EX = "ex";   秒
     */
    @Test
    public void test05() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        SetParams setParams = new SetParams();
        setParams.nx().ex(20);
        jedis.set("AAA", "CCCCC", setParams); //原子性要求
        System.out.println(jedis.get("AAA"));
    }
   /*测试hash数据类型*/
    @Test
    public void testHash() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.hset("person", "name", "tomcat");
        jedis.hset("person", "age", "100");
        Map<String,String> map = jedis.hgetAll("person");
        System.out.println(map);
    }
  @Test
    public void testList() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.lpush("list", "1","2","3","4");
        String value = jedis.rpop("list");
        System.out.println(value);
    }
   /**
     * 实现Redis 事务控制
     */
    @Test
    public void testMulti() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        Transaction transaction = jedis.multi();
        try {
            transaction.set("AAA", "XXX");
            transaction.set("BBB", "XXX");
            transaction.exec(); //提交事务
        }catch (Exception exception){
            exception.printStackTrace();
            transaction.discard();//回滚事务
        }
    }
}


5.Springboot整合Redis

5.1编辑配置文件

redis.host=192.168.126.129
redis.port=6379

5.2编辑配置类

package com.jt.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;
@Configuration  //标识我是配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
    @Value("${redis.host}")
    private String  host;
    @Value("${redis.port}")
    private Integer port;
    @Bean
    public Jedis jedis(){
        //数据写死?????????
        return new Jedis(host,port);
    }
}

5.3编辑测试类


@SpringBootTest //需要依赖spring容器,从容器中动态的获取对象
public class TestRedis {
    @Autowired
    private Jedis jedis;
    /**
     * 完成Redis入门案例测试
     * 报错说明:
     *      1.检查Linux防火墙
     *      2.检查Redis3项配置
     *      3.重启redis.
     */
    @Test
    public void test01(){
        //Jedis jedis = new Jedis("192.168.126.129",6379);
        //1.向redis中保存数据
        jedis.set("2004", "哈哈哈 今天下雨了 不负众望");
        //2.从redis中获取数据
        String value = jedis.get("2004");
        System.out.println(value);
    }
}


6.数据如何保存到Redis

6.1 业务说明


说明:由于redis中一般使用String数据类型保存业务数据.但是代码中java对象Redis没办法直接保存,所以需要中间的转化的过程.使用JSON方式进行数据中转.

List java对象 --------- JSON ------------ Redis中 使用String数据类型保存.


6.2ObjectMapper API介绍


package com.jt.test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.pojo.ItemDesc;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TestObjectMapper {
    private static final ObjectMapper MAPPER = new ObjectMapper();
    @Test
    public void test01(){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("测试JSON转化").setCreated(new Date())
                .setUpdated(itemDesc.getCreated());
        try {
            //1.将java对象转化为JSON
            String json = MAPPER.writeValueAsString(itemDesc);
            System.out.println(json);
            //2.将JSON转化为对象 利用反射机制实例化对象 利用get/set方法为对象赋值
            ItemDesc itemDesc2 = MAPPER.readValue(json, ItemDesc.class);
            System.out.println(itemDesc2.toString()); //只输出当前对象的数据
            //3.将集合信息转化为JSON  List
            List<ItemDesc> list = new ArrayList<>();
            list.add(itemDesc);
            String listJSON = MAPPER.writeValueAsString(list);
            System.out.println(listJSON);
            //将json转化为List集合
            List<ItemDesc> list2 = MAPPER.readValue(listJSON,list.getClass());
            System.out.println(list2);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}


6.3编辑工具API


说明::改工具API主要负责将用户参数转化为JSON,或者将JSON串转化为对象. 简化客户端调用

package com.jt.unit;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ObjectMapperUtil {
    //1.创建工具API对象
    private static final ObjectMapper MAPPER = new ObjectMapper();
    //2.封装API 将对象转化为JSON
    public static String toJSON(Object object){
        if(object == null){
            throw new RuntimeException("传入对象不能为null");
        }
        try {
            String json = MAPPER.writeValueAsString(object);
            return json;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
    /**
     * 3.将JSON串转化为对象  用户传递什么类型,则返回什么对象
     *                      user.class        User对象
     *
     */
    public static <T> T toObject(String json,Class<T> target){
        //1.校验参数是否有效
        if(json == null || "".equals(json) || target == null){
            //参数有误.
            throw new RuntimeException("参数不能为null");
        }
        //2.执行业务处理
        try {
            T t = MAPPER.readValue(json, target);
            return t;
        } catch (JsonProcessingException e) {
            //将报错信息通知其他人
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}

6.4编辑工具API测试

//工具API测试
    @Test
    public void test02(){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("测试JSON转化").setCreated(new Date())
                .setUpdated(itemDesc.getCreated());
        String json = ObjectMapperUtil.toJSON(itemDesc);
        ItemDesc itemDesc2 = ObjectMapperUtil.toObject(json, ItemDesc.class);
        System.out.println(itemDesc2);
    }


相关实践学习
基于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
相关文章
|
13天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
15天前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
|
7天前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
23 5
|
23天前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
125 22
|
22天前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
121 7
|
26天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
62 10
|
26天前
|
缓存 监控 NoSQL
Redis 缓存穿透的检测方法与分析
【10月更文挑战第23天】通过以上对 Redis 缓存穿透检测方法的深入探讨,我们对如何及时发现和处理这一问题有了更全面的认识。在实际应用中,我们需要综合运用多种检测手段,并结合业务场景和实际情况进行分析,以确保能够准确、及时地检测到缓存穿透现象,并采取有效的措施加以解决。同时,要不断优化和改进检测方法,提高检测的准确性和效率,为系统的稳定运行提供有力保障。
48 5
|
26天前
|
缓存 监控 NoSQL
Redis 缓存穿透及其应对策略
【10月更文挑战第23天】通过以上对 Redis 缓存穿透的详细阐述,我们对这一问题有了更深入的理解。在实际应用中,我们需要根据具体情况综合运用多种方法来解决缓存穿透问题,以保障系统的稳定运行和高效性能。同时,要不断关注技术的发展和变化,及时调整策略,以应对不断出现的新挑战。
42 4
|
存储 缓存 NoSQL
Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存|学习笔记
快速学习 Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存
Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存|学习笔记
|
缓存 NoSQL 安全
6.0Spring Boot 2.0实战 Redis 分布式缓存6.0|学习笔记
快速学习6.0Spring Boot 2.0实战 Redis 分布式缓存6.0。
331 0
6.0Spring Boot 2.0实战 Redis 分布式缓存6.0|学习笔记
下一篇
无影云桌面