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

原文地址:https://www.cnblogs.com/lcmlyj/p/10370058.html