Redis相关总结

redis 相关知识的再梳理总结。

redis是什么
  简单说,Redis 是一种高性能的KEY-VALUE结构的内存数据库。
   1、解决高并发场景(性能高10W左右的读写速度)
   2、解决高性能

redis在什么场景下需要使用
    缓存、秒杀、计数器、排行榜、热点、分布式锁、分布式ID、消息系统等相关场景

redis都需要了解哪些知识
    redis 安装:
    1、Downloads - Redis 官网下载地址
    2、下载完成后,make && make install  编译安装
    3、启动:redis-cil、redis-server、redis-sentinel(哨兵)
    4、vim redis.conf,修改守护线程 (daemonize)属性 为 true 这样保障可以在后台运行
       注:守护线程---特殊线程区别独立于业务线程,一般是用来做日志记录,防止业务线程死锁等场景。
    5、其他的可以百度查一下,比如如何开启自启动(如何配置)
    redis 使用:
      可视化:可以安装 Redis Desktop Manager 通过输入 ip、端口、账号、密码登录,redis默认分16个存储数据库,我们可以选择0-16个中的任意一个。
      客户端:如果从客户端访问,可以百度参考(各类命令,实际应用中暂时还没有用到相关内容)
   redis 数据存储格式类型:
    唯一的一点,无论是哪种格式类型,redis的存储方式 都是(key,value )键值对
    1、String 
       就是普通的存储格式,字符串,比如 userId:1 userName:张三,存储信息就是(userId:1,张三)     

示例:
    //省略Jedis相关
   //添加 一条数据
   jedis.set("userId:1","张三");
   //获取 一条数据
   jedis.get("userId:1");
   //删除 一条数据
   jedis.del("userId:1");

     2、List
       字符串列表, 比如班级:3班,成员:['张三','李四','王五','王五'],(class:3,['张三','李四','王五','王五'])

 // 使用 lpush 方法将元素添加到 List 的左侧  
 jedis.lpush("mylist", "李四");  
 jedis.lpush("mylist", "王五");  

 // 使用 rpush 方法将元素添加到 List 的右侧  
 jedis.rpush("mylist", "李四");  
 jedis.rpush("mylist", "王五");  

      3、set
       无需集合,比如班级:3班,成员:['张三','李四','王五','王五'],(class:3,['李四','张三','王五']),注意了,这个是无序的,不重复。

 // 添加元素到Set  
    jedis.sadd("myset", "element1");  
    jedis.sadd("myset", "element2");  
    jedis.sadd("myset", "element3");  


      4、hash
       Hash 这个个人理解,存储的key是一个字符串,Value就是一个Hash(也是字符串),在Java示例代码可以看下区别(我们用jedis)
       示例:
        Hash

//省略Jedis相关
//添加 一条数据
String userHashKey = "userId:1"
jedis.hset(userHashKey,"age","12");
jedis.hset(userHashKey,"name","张三");
//获取   一条数据
jedis.hget(userHashKey,"age");   
jedis.hget(userHashKey,"name");   
//删除某一个属性
jedis.hdel(userHashKey, "age");
//删除
jedis.del(userHashKey);
//获取   全部值
Map<String, String> userInfo = jedis.hgetAll(userHashKey,"age");   

      5、ZSET
            是一种有序的结构,但是插入的时候,会有一个 score的参数

//示例:
  jedis.zadd(zsetKey,1,"张一")
  jedis.zadd(zsetKey,3,"张三")
  jedis.zadd(zsetKey,2,"张二")
//输出全部
Set<Tuple> studentsWithScores = jedis.zrangeWithScores(zsetKey, 0, -1);
输出结果:1,2,3
//指定范围
Set<String> studentsInRange = jedis.zrangeByScore(zsetKey, 1, 2);
输出结果:1,2        

Redis 持久化:
        因为redis 是内存数据库,基于内存来运行的,当我们电脑宕机,重启等情况下数据就会出现丢失,所以我们也要关注Redis持久化,现实中,很大多数企业都会购买云RDS产品,一般不需要我们来进行维护和管理,但是我们也要了解知晓相关的知识,有可能只有ECS产品,我们要自己搭建(没有运维)的情况下,只能自行就行管理咯。
       那持久化,对于redis来说,就是要把内存中的数据存储到磁盘中。
       简单来说就是说,Redis 运行的时候----》持久化机制-----》数据持久化到磁盘
        Redis 挂掉的时候----》是否有持久化---》有----启动的时候从磁盘把数据加载到内存中
                                                                          否---》完蛋,全都没了
        所以在多数情况下,我们使用redis 的场景需要多多考虑容灾情况,或者业务场景。比如短信验证码(有效期)这类的,存储用户信息这类的场景,是否可以使用,为什么?
        做持久化,绕不开两个内容,RDB/AOP,一句话简单说,一个是做备份,一个备份操作日志。
        RDB
        RDB相当于,一个存档数据,存档数据那就要考虑,什么时候备份,所以就会引出,save配置的概念,比如说3600秒保存一次,300秒一次,在config配置中,参数为 save  秒 次数,意思是说,多少秒,有多少key发生变化,我们就备份一次。
        AOF
        AOF相当于,操作日志记录,全日志记录,你每次操作都会被记录下来,那这个就很好理解,恢复的时候,直接重新执行一遍就OK,那相对的,记录就会很大。
        所以RDB和AOF,各有优缺,RDB,无法保障数据丢失问题,AOF无法保障存储大小问题,恢复起来,RDB就很简单,我们可以理解成,直接把备份文件copy回去,AOF就是一行一行重新执行一遍,所以AOF就能保障数据丢失问题。 

Redis 事务:

        redis 的事务开启很简单,通过MULTI 就可以开启事务,但是事务跟我们java WEB开发中的事务有一些区别,无法进行回滚操作,即执行到哪一步就停在哪一步,redis 是顺序执行命令的,所以会导致数据在执行完毕之前可能导致出现脏数据的可能性,这一点我们要在开发过程中考虑清楚具体的业务情况来使用。

        在spring 中,我们一般使用jedis来调用redis(springboot2.X以上开始使用lettuce),操作redis 一般我们会使用redistemplate,提供的api来操作redis

//示例1:不带序列化
redisTemplate.execute((RedisCallback<Long>) connection -> {
    connection.set(key, value);
    connection.expire(key, time);
    LOGGER.debug("put key [{}] ttl [{}]s", key, time);
    return 1L;
});

//示例2:带序列化
redisTemplate.execute((RedisCallback<Long>) connection -> {
    RedisSerializer<String> serializer = getRedisSerializer();
    byte[] keys = serializer.serialize(key);
    byte[] values = serializer.serialize(value);
    connection.set(keys, values);
    connection.expire(keys, time);
    LOGGER.debug("put key [{}] ttl [{}]s", key, time);
    return 1L;
});

示例3:查询 key类似的值(在0-》2*n 时间快过期的keys)

final List<String> keysList = new ArrayList<>();
redisTemplate.execute((RedisCallback<List<String>>) connection -> {
    Set<String> keys = redisTemplate.keys(key + "*");
    for (String key1 : keys) {
        Long ttl = connection.ttl(key1.getBytes(DEFAULT_CHARSET));
        if (0 <= ttl && ttl <= 2 * time) {
            keysList.add(key1);
        }
    }
    return keysList;
});
return keysList;

Redis 订阅与发布:

        简单来说,Redis服务端(A)发送消息---BCD客户端订阅消息(监听器),完成整个闭环。

        示例:构建一个发布端

@Configuration class  
public RedisConfig {  
    @Bean  
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,  
                                              MessageListenerAdapter listenerAdapter) {  
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();  
        container.setConnectionFactory(connectionFactory);  
        container.addMessageListener(listenerAdapter, new PatternTopic("chat"));  
        return container;  
    }  
    @Bean  
    MessageListenerAdapter listenerAdapter(RedisSubscriber redisSubscriber) {  
        return new MessageListenerAdapter(redisSubscriber, "receiveMessage");  
    }  
    @Component  
    public static class RedisSubscriber {  
        public void receiveMessage(String message) {  
            System.out.println("Received <" + message + ">");  
        }  
    }  
}

        示例:构建一个接收端

@Service  
public class RedisPublisherService {  
    private final RedisTemplate<String, String> redisTemplate;  
    @Autowired  
    public RedisPublisherService(RedisTemplate<String, String> redisTemplate) {  
        this.redisTemplate = redisTemplate;  
    } 
    public void publishMessage(String message) {  
        redisTemplate.convertAndSend("chat", message);  
    }  
}

Redis 锁:

        redis分布式锁,这个是一个取巧的操作,redis 是单线程的,所以我们可以在我们业务开始的时候设置一个我们自己初始化的一个值到redis中,完成加锁操作,在业务结束的时候,删除掉这个值,完成解锁操作,若我们重新进入当前业务,首先判断我们设置的值是否存在,存在表示锁定状态,否则表示已经解锁可以继续操作。

Redis 验证码:

        设置一个有效期的reids值,在当前有效期内都有效的话,表示验证码有效,否则,重新发送验证码

        key: capcat:phone:13211111111,     value : 123456         timeout:60s

 示例代码:

public class test(){
  
  String final static LOGIN_CODE = "captcha:phone:";
  
  public void setCaptcha(String key,String value){
    redisTemplate.execute((RedisCallback<Long>) connection -> {
        RedisSerializer<String> serializer = getRedisSerializer();
        byte[] keys = serializer.serialize(key);
        byte[] values = serializer.serialize(value);
        connection.set(keys, values);
        connection.expire(keys, time);
        LOGGER.debug("put key [{}] ttl [{}]s", key, time);
        return 1L;
    });
  }
  public void getCaptcha(key){
      String resultStr = redisTemplate.execute((RedisCallback<String>) connection -> {
        RedisSerializer<String> serializer = getRedisSerializer();
        byte[] keys = serializer.serialize(key);
        byte[] values = connection.get(keys);
        return serializer.deserialize(values);
      });
      LOGGER.debug("get key [{}]", key);
      return resultStr;
  }


  public void testCaptcha(){
    String phone  = '13211111111'
    String key = LOGIN_CODE + phone;
    int captchaCode= (int) ((Math.random() * 9 + 1) * 100000);
    setCaptcha(key,captchaCode);
    String redisResultCode= getCaptcha(key);
  }        
}


  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis相关的面试题涵盖了以下几个方面: 1. Redis的基本概念和特性:面试官可能会问到你对Redis的理解和熟悉程度。你可以回答Redis是一个开源的内存键值存储系统,具有高性能和持久化能力。它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合等。 2. Redis的数据持久化方式:Redis提供了两种方式来将数据持久化到磁盘上,分别是RDB(Redis Database)和AOF(Append Only File)。RDB是一种快照方式,可以将数据以二进制形式保存到硬盘上,而AOF则是将每个写操作追加到文件末尾。你可以解释一下这两种方式的优缺点,并说明在不同场景下应该选择哪种方式。 3. Redis的线程模型:在Redis 6.0之前,Redis是单线程的。而在Redis 6.0之后开始支持多线程。Redis内部使用基于epoll的多路复用来处理网络IO,而执行命令的核心模块仍然是单线程的。你可以简要介绍一下Redis的线程模型以及引入多线程的原因。 4. Redis的扩展模块:Redis支持通过扩展模块来增加额外的功能。例如,BloomFilter、RedisSearch和Redis-ML等扩展模块可以用于实现不同的功能需求。你可以提到一些常用的Redis扩展模块,并解释一下它们的作用和用途。 总结起来,面试中关于Redis的问题主要包括对Redis的基本概念和特性的理解、数据持久化方式、线程模型以及扩展模块的使用等方面。通过对这些问题的了解和回答,可以展示出你对Redis的熟悉程度和实际应用能力。同时,你还可以结合自己的经验和实际项目,给出一些实际的应用场景和解决方案,从而更好地回答面试官的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [面试 Redis 没底?这 40 道面试题让你不再慌(附答案)](https://blog.csdn.net/xmt1139057136/article/details/115423283)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [redis面试题总结(附答案)](https://blog.csdn.net/guorui_java/article/details/117194603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值