zoukankan      html  css  js  c++  java
  • Redis_初识

    一、简介

    Redis(Remote Dictionary Server)本质上是一个Key-Value类型的内存数据库,整个数据库统统加载在内存当中进行操作,定期通过异步操作吧数据库flush到硬盘上进行保存。

    二、Redis 使用场景

    1. 会话缓存

    最常使用的一种Redis场景,用redis缓存会话比其他存储(Memcached)的优势在于:Redis提供持久化。

    1. 全页缓存(FPC)

    除基本的会话token外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大的改进,类似PHP本地FPC。

    1. 队列

    Redis 在内存存储引擎领域的一大优点就是提供list和Set操作,这使得Redis能作为一个很好的消息队列平台来使用。

    1. 排行榜、计数器

    Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。

    1. 发布、订阅

    最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!

    三、Redis 相关问题

    1. Redis支持哪几种数据类型

    • String、List、Set、Sorted Set、hashes

    2. Redis主要消耗的资源

    • 内存

    3. redis 有哪几种淘汰策略

    将Redis用作缓存时,如果内存空间用满,就会自动驱逐老的数据库。

    驱逐策略

    • no_eviction:不删除策略,达到最大内存限制时,如果需要更多内存,直接返回错误信息。
    • allkeys-lru:所有Key通用;优先删除最近最少使用的key。
    • volatile-lru:只限制于设置了expire的部分;优先删除最近最少使用的key.
    • allkeys-random:所有key通用;随机删除一部分 key。
    • volatile-random:回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
    • volatile-ttl: 只限于设置了 expire 的部分; 优先删除剩余时间(time to live,TTL) 短的key。

    驱逐的内部实现

    1. 驱逐的过程

    • 客户端执行一个命令,导致Redis中的数据增加,占用更多的内存。
    • redis检查内存使用量,如果超出maxmemory限制,根据策略清除部分 key。
    • 继续执行下一条命令,以此内推。
    • 在这个过程中,内存使用量会不断地达到limit值,然后超过,然后删除部分key,使用量又下降到limit值之下。
    • 如果某个命令导致大量内存占用(比如通过新key保存一个很大的set),在一段时间内,可能内存的使用量会明显超过 maxmemory 限制。

    2. LRU算法

    Redis使用的并不是完全LRU算法。自动驱逐的Key,并不一定是最满足LRU特征的那个,而是通过近似LRU算法,抽取少量的Key样本,然后删除其中访问时间最古老的那个key。

    驱逐算法,从Redis 3.0 开始得到了巨大的优化,使用Pool(池子)来作为候选,这大大提升了算法效率,也更接近于真实的LRU算法。

    在Redis的LRU算法中,可以通过设置样本(Sample)的数量来调优算法精度。通过以下指令配置:

    maxmemory-samples 5
    

    4. 字符串类型的值能存储最大容量是多少?

    512M

    5. 为什么Redis需要吧所有数据放到内存中?

    Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。

    • 所以redis具有快速和数据持久化的特征。如果不将数据放到内存中,磁盘I/O速度为严重影响Redis的性能。
    • 在内存越来越便宜的今天,redis将会越来越受欢迎。

    6. Redis集群方案应该怎么做?都有哪些方案?

    1. codis
      目前用的最多的集群方案,基本和twemproxy一致 的效果,蛋挞支持在节点数量改变情况下,就节点数据可恢复到新Hash节点。

    2.redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。

    7. Redis集群方案什么情况下会导致整个集群不可用?

    有A、B、C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会缺少5501-11000这个范围的槽而不可用。

    8. MySQL里有2000W数据,Redis中只存20W的数据,如何保证Redis中的数据都是热点数据?

    redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。

    9. Jedis与Redisson对比有什么优缺点?

    Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;

    Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

    10.Redis如何设置密码及验证密码?

    设置密码:config set requirepass 123456
    授权密码:auth 123456

    11.Redis哈希槽的概念?

    Redis集群没有使用一致性Hash,而是引入Hash槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

    附:java使用Redis demo

    获取Redis连接

    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    /**
     * @author Winstone
     * @date 2019/12/20 - 1:26 下午
     */
    public class RedisUtil {
    
        //服务器IP地址
        private static String ADDR = "127.0.0.1";
        //端口
        private static int PORT = 6379;
        //密码
        private static String AUTH;
        //连接实例的最大连接数
        private static int MAX_ACTIVE = 1024;
        //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
        private static int MAX_IDLE = 200;
        //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
        private static int MAX_WAIT = 10000;
        //连接超时的时间  
        private static int TIMEOUT = 10000;
        // 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
        private static boolean TEST_ON_BORROW = true;
    
        private static JedisPool jedisPool = null;
        //数据库模式是16个数据库 0~15
        public static final int DEFAULT_DATABASE = 0;
        /**
         * 初始化Redis连接池
         */
    
        static {
    
            try {
    
                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxTotal(MAX_ACTIVE);
                config.setMaxIdle(MAX_IDLE);
                config.setMaxWaitMillis(MAX_WAIT);
                config.setTestOnBorrow(TEST_ON_BORROW);
                jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT,AUTH,DEFAULT_DATABASE);
    
            } catch (Exception e) {
    
                e.printStackTrace();
            }
    
        }
    
        /**
         * 获取Jedis实例
         */
    
        public synchronized static Jedis getJedis() {
    
            try {
    
                if (jedisPool != null) {
                    Jedis resource = jedisPool.getResource();
                    System.out.println("redis--服务正在运行: "+resource.ping());
                    return resource;
                } else {
                    return null;
                }
    
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
    
        }
    
        /***
         *
         * 释放资源
         */
    
        public static void returnResource(final Jedis jedis) {
            if(jedis != null) {
                jedisPool.returnResource(jedis);
            }
    
        }
    }
    

    Redis操作

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @author Winstone
     * @date 2019/12/20 - 12:15 上午
     */
    public class RedisOptions {
        private final static Jedis conn = RedisConnection.getRedisConnection();
    
        // 字符串操作
        public  boolean set(String key, String value) {
            try {
                conn.set(key, value);
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    
        public  String get(String key) {
            try {
                return conn.get(key);
            } catch (Exception e) {
                return null;
            }
        }
        
        //队列操作
        public  boolean setList(String name, String[] list) {
            if (list.length != 0) {
                for (String str : list) {
                    conn.lpush(name, str);
                }
                return true;
            } else {
                return false;
            }
        }
        public  boolean setList(String name, List<String> list) {
            if (list.size() != 0) {
                for (String str : list) {
                    conn.lpush(name, str);
                }
                return true;
            } else {
                return false;
            }
        }
    
        public List<String> getList(String name){
            long length = conn.llen(name);
            List<String> list = new ArrayList<String>();
            if (length>0){
                 list = conn.lrange(name,0,length-1);
            }
            return list;
        }
    
    
        //集合操作
        public boolean setSet(String name, Set<String> set){
            if (!set.isEmpty()){
                for (String str:set){
                    conn.sadd(name,str);
                }
                return true;
            }
            return false;
        }
    }
    
    
  • 相关阅读:
    20160130.CCPP体系详解(0009天)
    20160129.CCPP体系详解(0008天)
    20160128.CCPP体系详解(0007天)
    20160127.CCPP体系详解(0006天)
    20160126.CCPP体系详解(0005天)
    程序员_你的“强迫症”有哪些?
    天天写业务代码_如何成为技术大牛?
    阿里云全球首批MVP李文毅专访-一个“改邪归正”的90后
    【毕业季】穿越回毕业前一年_这次你会怎么选
    恢复Hyper-V虚拟机丢失的数据文件过程
  • 原文地址:https://www.cnblogs.com/winstonehome/p/12081567.html
Copyright © 2011-2022 走看看