• Redis特点为什么快、数据类型、配置、持久化等


    一、Redis简介

    redis是一个NoSQL,也就是非关系型数据库,以key-value的形式保存数据,它是基于内存保存数据的,所以存取数据的速度较SQL而言快很多,并且它是单线程的。

    问:为什么Redis快?

    1.单线程,减少上下文切换;2.操作内存;3.复用IO,非阻塞;4.特定的存储类型

    复用IO

      首先说说传统IO,传统IO同步阻塞,用户A和服务器产生连接传输时,如果此时用户B需要和服务器连接,那么用户B的操作会被阻塞住,这就是一个同步阻塞的模型,一个线程处理一个流。缺点就是效率低。如果使用多线程的话也有线程切换和维护的开销。

      所以,可以使用一个线程维护多个IO,可以采取轮训的方式,但是呢,一直轮训的话对CPU资源也是一种浪费,于是,就有了复用IO,并且有三种方式实现。

      复用IO select、poll:select和poll在轮训时,会先去判断流有没有传输数据,如果没有则阻塞住,有就读取数据,阻塞就节约了CPU资源,但是呢还是会去对所有维护的流进行轮询,所以就有了事件驱动的方式epoll。另外,这两种方式线程不安全

      复用IO epoll:epoll受IO事件驱动,当有IO发生时,会直接开始这些IO操作,而不会去轮训所有的流再判断是否有数据。epoll线程安全

    二、Redis的value数据类型

    1.string:一个key对应字符串类型,使用jedis: jedis.set(key, value); 

    2.list:一个key对应一个字符串的集合,链表,使用jedis: jedis.lpush(key, value1, value2...); 

    3.hash:一个key对应字典散列,一个key可以对应多个field-value,这多个field-value组合在一起就类似一个对象。

    比如:一个key叫“student”,使用jedis

    public void hset() {
        //写法一
        jedis.hset("student", "name", "xiaoming");
        //写法二
        Map<String, String> student = new HashMap<>();
        student.put("name", "xiaoming");
        jedis.hset("student", student);
    }

    4.set:一个key对应一个set集合,使用jedis: jedis.sadd(key, value1, value2...); 

    5.zset:一个key对应一个zset集合,使用jedis:

    public void hset() {
        //写法一
        jedis.zadd("student", 10.0, "Math");
        //写法二
        Map<String, Double> student = new HashMap<>();
        student.put("English", 20.0);
        student.put("Physics", 30.0);
        jedis.zadd("student", student);
    }

    三、Redis的配置

    1.配置RDB与AOF模式实现数据持久化:

      (1)RDB快照:在redis.conf里配置

        ①save 900 1:900秒内有1个key改变则同步;

        ②save 300 10:如上类推;

        ③save 60 10000:如上类推;

      特点:通过IO同步数据,同步的时候慢,恢复的时候快;

      (2)AOF模式,append-only-file:在redis.conf里配置

        ①appendfsync always:每当key改版就同步;

        ②appendfsync everysec:每秒同步;

        ③appendfsync no:只有内存满了不能再保存时同步;

      特点:同步的是指令,在恢复的时候没有RDB快;

    持久化机制
      某一时刻写入到磁盘
    RDB(默认)
      原理:单独创建(fork)一模一样的子进程来进行持久化,先将数据写入到一个临时文件,最终生成dump.rdb文件
      问:rdb文件位置:redis.conf里的 dir ./就是dump.rdb文件存放的位置
      问:为什么要fork子进程:主进程不进行IO,确保了Redis主进程的高性能
      问:什么时候进行持久化:
      执行shutdown命令式,如果没有配置AOF,进行bgsave;
      配置redis.conf中的 save配置,进行bgsave,属于定时;
      执行命令:save(主进程进行持久化),bgsave(后台持久化,子进程持久化)
      问:RDB的缺点:宕机时,没法进行备份
    AOF(Append only file)
      原理:将redis的操作日志以追加的方式写入文件,读操作时不会记录的
      问:如何触发AOF:通过配置
        no 频率很低
        always 频率高,每次修改都记录,数据安全,但是效率低,开销大
        everysec 一秒一次,快,可能丢失1秒内的数据(最好用这个)
      问:AOF的好处:解决了RDB可能会宕机而丢失持久化数据的问题
      问:AOF会fork子进程吗:不会,但是重写会fork子进程
      问:AOF的备份文件中的命令是什么意思(jedis给redis发送的命令也是如此):
        *2 表示命令有2个字符串
        *3 表示命令有3个字符串
        $6 表示命令的长度是6
        SELECT 0 选择redis的数据库,第0号
      问:AOF重写机制:(redis优化关键)
      起因:set del命令会一直累加,而不会抵消,会一直占用存储。所以需要重写机制,来为appendonly.aof文件优化

      **!!! redis.conf配置文件中:auto-aof-rewrite-min-size 64Mb (默认)

        第一次触发是64Mb,下次触发根据配置:auto-aof-rewrite-percentage 100 (默认百分之百),下次触发的阈值就是第一次触发之后的大小的两倍
    混合持久化(redis4.0特性,AOF使用RDB特性)
      配置:aof-use-rdb-preamble yes 默认是no
      优点:AOF机制将命令转化为二进制数据的方式保存在.aof文件中,节省空间
      问:什么时候触发:重写时触发

    2.配置主从复制:在redis.conf里配置

      slaveof xxx.xxx.xxx.xxx:port

      bind 0.0.0.0

    3.配置哨兵模式:主服务器宕机,重新选取主服务器

      参考:https://www.cnblogs.com/kerwinC/p/6069864.html

    4.过期策略:

      (1)定期删除:定时遍历判断是否过期并进行删除;

      (2)惰性删除:key改变时判断是否过期,随后进行删除;

      第一个占用时间,第二个占用空间,一般会结合起来用。

    四、Redis的应用场景

    1.分布式锁(string):利用setnx(key, value)的set if not exist特性,如果key存在则不做任何操作,并返回1,如果key不存在,则添加一个值为value的key到redis中;

    2.计数器(string):一个帖子被浏览的数量, key(帖子id)-value(数量) ;

    3.消息队列(list):list的可以边进边出的特性;

    4.微博/Twitter的用户消息列表(list): key(用户id)-value(信息的集合) 

    5.微博的点赞、签到(set): key(某微博的like)-value(like微博的用户的集合) 

    6.可能认识的人模型(set): key(某用户id)-value(某用户关注的人的集合) ,利用用户之间关注的人的集合的交集和差集筛选出可能认识的人;

    7.电商商品标签筛选(set): key(商品标签)-value(拥有此商品标签的商品集合) ,选择不同的商品标签,筛选出交集的商品;

    8.用户积分排行榜(zset): key(某排行榜)-value(用户-分数的映射集合) ,根据分数进行排序。

    五、缓存雪崩、缓存击穿

    1.缓存雪崩:

      当缓存崩掉时,请求全部到了数据库,这时可能会导致数据库假死,甚至崩溃。

    解决:

      (1)Redis配置集群和哨兵模式保持高可用;

      (2)本地ehcache也进行缓存,或者使用hystrix熔断机制来限流/降级;

      (3)雪崩之后,使用持久化恢复数据;

    2.缓存击穿:

      当大量查询不存在的key的请求时,请求直接落到数据库上,也可能导致假死、崩溃。

    解决:

      (1)把不存在的key也放进redis中,比如id值为负的key,从-9999到-1对应空的value。

    六、redis缓存过期策略

    1.缓存过期策略:设置expire过期时间

    2.三种策略:

      主动删除:一直判断key有无过期,一旦过期,立马删除。优点:不占空间,key过期时效性好,缺点:很吃性能

      惰性删除:下次get时判断有无过期,过期则删除。优点:性能好,缺点:占空间

      定期删除:周期判断有无key过期。优缺点介于主动删除和惰性删除之间

    七、redis缓存淘汰策略

    1.什么情况下会发生缓存淘汰

      在redis达到了最大的存储内存时,需要对缓存进行清除而让新的数据被set进去,最大存储内存通过 maxmemory 配置。

    2.缓存淘汰的6种策略(policies)

      neoviction:不淘汰任何已存在的缓存,返回报错信息

      allkeys-random:在所有的key中随机删除

      allkeys-lru:在所有的key中,根据最少使用算法,对最少使用的key进行删除

      volatile-random:在设置了expire过期时间的key中,进行随机删除

      volatile-lru:在设置了expire过期时间的key中,根据最少使用算法,对最少使用的key进行删除

      volatile-ttl:在设置了expire过期时间的key中,对即将过期的key进行删除

    3.缓存淘汰的优缺点

       针对不同的情况使用不同的淘汰策略,对于有热点数据和非热点数据类型的缓存时,用lru是最好的。另外设置expire会消耗服务器CPU,所以可以通过设置allkeys-lru,不设置expire的方式来优化redis的效率。

    4.近似LRU算法

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

      所以Redis3.0之后,优化了其LRU算法,通过可以配置样本 maxmemory-samples 的方式提升算法精度,相反的,会更加消耗服务器的CPU。一般设置到10时就非常接近真实的LRU的算法的精度了。

    八、redis常用命令

    info [selection]

    https://www.runoob.com/redis/server-info.html

    九、SpringBoot整合Redis、哨兵

    集群:https://www.cnblogs.com/HendSame-JMZ/p/7722104.html

    哨兵:https://www.cnblogs.com/fan-gx/p/11463400.html

  • 相关阅读:
    jQuery实现radio第一次点击选中第二次点击取消功能(转)
    好用的文件下载类
    Windows获取远程Linux局域网内的mysql连接
    linux通过端口号查找程序执行路径
    linux几个命令
    java判断是移动端还是pc端
    jsp传给java属性,java生成json串,方便以后取出来
    如何在线程中获取spring 管理的bean
    [DeploymentService:290066]Error occurred while downloading files from admin server for deployment request "0". Underlying error is: "null"
    double,失去精度
  • 原文地址:https://www.cnblogs.com/lcmlyj/p/10370058.html
Copyright © 2020-2023  润新知