redis--

目录

基础

中间件

数据库

数据库的分类

redis

1.支持几种数据类型?

2.如何保证redis中的数据都是热点数据?

3.最近最少使用算法LRU常用实现、优化方案

4.使用redis缓存数据,保证热点数据的缓存用法与原理

5.redis的几种部署方式

6.redis是什么

7.分布式:主从模式、读写分离

8.redis优点

9.redis和memcache相比,有哪些优势?

10.redis与memcache区别

11.redis 持久化

12.Redis快照

13.Redis为什么这么快

14.redis针对多路 I/O 复用模型简单探讨

15.redis的VM 机制

16.为什么redis 是单线程的?


 

逻辑思维训练500题(带答案)

笔试

  1. LeetCode

  2. 牛客网

  3. 剑指offer第二部 系列:

    剑指offer原书第二版的java实现
    剑指offer第二版面试题-Java描述-持续更新

 

基础

1.请你讲讲 Statement 和 PreparedStatement 的区别?哪个性能更好?

PreparedStatement代码可读性更好,防止SQL注入攻击

PreparedStatement的语句执行一次后,会被缓存(缓存针对整个DB,而不是一个Connection),下次调用相同的预编译语句就不用再次编译

2.讲解一下数据连接池的工作机制?

同时创建多个链接,等待使用,使用时候从连接池取出链接,不用创建。使用结束,链接释放回连接池

3.

中间件

数据库

数据库的分类

https://blog.csdn.net/qq_27565769/article/details/80731213

redis

http://www.runoob.com/redis/redis-tutorial.html

以下部分参考或摘抄于文章地址:

https://www.cnblogs.com/eoss/p/6202185.html

1.支持几种数据类型?

string(字符串) 简单的key-value类型,value其实不仅可以是String,也可以是数字。

list(列表)  

list就是链表,使用Lists结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。 
Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列。

抢票场景:将多个票循环leftpush放在池子中,抢票时候对key加锁,再进行rightPop操作。

消息队列系统
使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。 
比如:将Redis用作日志收集器 
实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。

hash(散列)   

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。 
存储部分变更的数据,如用户信息等。

sets (集合)  

set就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的set数据结构,可以存储一些集合性的数据。set中的元素是没有顺序的。

sorted set(有序集合)

和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,比如一个存储全班同学成绩的sorted set,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。可以用sorted set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

2.如何保证redis中的数据都是热点数据?

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

  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  6. no-enviction(驱逐):禁止驱逐数据

适用场景

    allkeys-lru: 如果我们的应用对缓存的访问符合幂律分布(也就是存在相对热点数据),或者我们不太清楚我们应用的缓存访问分布状况,我们可以选择allkeys-lru策略。
    allkeys-random: 如果我们的应用对于缓存key的访问概率相等,则可以使用这个策略。
    volatile-ttl: 这种策略使得我们可以向Redis提示哪些key更适合被eviction。

另外,volatile-lru策略和volatile-random策略适合我们将一个Redis实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个Redis实例来达到相同的效果,值得一提的是将key设置过期时间实际上会消耗更多的内存,因此我们建议使用allkeys-lru策略从而更有效率的使用内存。

3.最近最少使用算法LRU常用实现、优化方案

实现:最常见的是使用一个链表保存缓存数据

  1. 新数据插入到链表头部;
  2. 每当缓存命中(即缓存数据被访问),将数据移动到链表头部;
  3. 当链表满的时候将链表尾部的数据丢弃;

缺点:命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。

优化:将维护的链表改为一个双向链表(即每个节点都有个prev和next),另外需要再多维护一个map,将缓存对象的引用放入map中;

1、新数据插入链表头部,并且放入map中

2、每当需要使用缓存时,首先通过key到map中查找,命中缓存后将数据移动到链表头部(这个移动就非常好移动了,只需要把该节点的prev节点的next属性赋值为该节点的next节点,同时把该节点的next节点的prev属性赋值为该节点的prev节点,并且将该节点放入链表头部就可以了)。

3、当链表满的时候将链表尾部的数据丢弃,并且删除map中对应的数据。

效果:基于以上改变的LRU算法,完全去除了命中缓存需要遍历链表这个缺点,性能得到了大的提升。

4.使用redis缓存数据,保证热点数据的缓存用法与原理

注:只要限制了redis占用的内存,redis会根据自身数据淘汰策略,加载热数据到内存。

【用法】:通过redis本身的设置过期时间来实现缓存热点数据

1、缓存每命中一次,就重新给该数据设置过期时间

2、那么经常命中的缓存始终不会过期,不会被删除,而非热点数据过期时间一到那么就会被删除掉,保证了redis中始终存在的是热点数据。

【原理】

1、原理其实就是Java中延时阻塞队列DelayQueue的原理

2、当对redis中缓存数据设置过期时间,相当于将缓存数据放入redis中维护的延时阻塞队列DelayQueue。

3、DelayQueue会对放入的缓存数据根据过期时间进行排序,时间短的在前面,时间长的在队列后面。

4、会使用一个或者多个线程循环查询DelayQueue,一旦能从DelayQueue获取元素了就说明该缓存数据到期了,就可以取出来并且删除掉了。

5、当有多个线程都同时查询DelayQueue的时候,只有一个线程能够争取到头元素,其它线程将被阻塞。当头元素被取走以后,会唤醒所有阻塞线程,线程竞争头元素,竞争到头元素的线程会查询头元素的剩余delay时间,并且标记头元素已经被该线程占有,再根据delay时间wait自己,最后获取头元素后唤醒其它阻塞线程。

5.redis的几种部署方式

  • 单节点模式
  • 主从模式,配置一主二从模式
  • 哨兵模式

哨兵模式是主从模式的升级版,他会在后台有一个监控,监控当前的主机,巡逻主机下面的从机,如果某一时刻主机挂掉了,那么他会通过一种投票的机制从从机之中选举一台作为新的主机,并且,其余的从机将会连接到这个新的主机上面。

    配置一主二从三sentinel模式

6.redis是什么

redis是一个基于内存的高性能key-value数据库。(键值存储数据库、非关系型数据库)

7.分布式:主从模式、读写分离

redis支持主从的模式。

  原则:

Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。

典型的读写分离模型。利用master来插入数据,slave提供检索服务。有效减少单个机器的并发访问数量。

  读写分离模型:

通过增加Slave DB的数量,读的性能可以线性增长,为了避免Master DB的单点故障,集群一般都会采用两台Master DB 做双机热备,所以整个集群的读和写的可用性都非常高。

  缺陷:

不管是Master还是Slave,每个节点都必须保存完整的数据,如果在数据量很大的情况下,集群的扩展能力是受限于单个节点的存储能力,而且对于Write-intensive类型的应用,读写分离架构并不适合。

为了解决读写分离模型的缺陷,可以将数分片模型应用进来。可以将每个节点看成都是master,然后通过业务实现数据分片。结合两种模型,可以将每个master设计成由一个master和多个slave组成的模型。

8.redis优点

  a.单线程,利用redis队列技术并将访问变为串行访问,消除了传统数据库串行控制的开销

  b.redis具有快速和持久化的特征,速度快,因为数据存在内存中。

  c.分布式 读写分离模式

  d.支持丰富数据类型

  e.支持事务,操作都是原子性,所谓原子性就是对数据的更改要么全部执行,要不全部不执行。

  f.可用于缓存,消息,按key设置过期时间,过期后自动删除

9.redis和memcache相比,有哪些优势?

  a.memcache所有的值均是简单的字符串,redis支持更为丰富的数据类型

  b.redis速度比memcached快很多

  c.redis支持持久化

10.redismemcache区别

  a.存储方式 memcache存在内存中,redis存在硬盘中,保证数据持久化

  b.数据类型 memcache对数据类型支持相对简单,redis有复杂的数据类型

  c.使用底层模型不同:底层实现方式以及客户端之间通信的应用协议不一样

  d.redis最大可以达到1G而memcache只有1MB

11.redis 持久化

redis提供了不同级别的持久化方式,一种是RDB,一种AOF。可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

  RDB:在指定的时间间隔能对数据进行快照存储(隔一段时间,把内存里的数据转存在硬盘里的文件)

  优点:

  • RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如您可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题您也可以根据需求恢复到不同版本的数据集.
  • RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
  • RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
  • 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

  缺点:

  • 如果您希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合您.虽然您可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,您通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,您可能会丢失几分钟的数据.
  • RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是您可以调节重写日志文件的频率来提高数据集的耐久度.

  AOF:每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.

  优点:

  • 使用AOF 会让您的Redis更加耐久: 您可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,您最多丢失1秒的数据.
  • AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,您也也可使用redis-check-aof工具修复这些问题.
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果您不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

  缺点:

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
    根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

12.Redis快照

在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。您可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。您也可以通过调用 SAVE或者 BGSAVE , 手动让 Redis 进行数据集保存操作。

比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:save 60 1000

这种持久化方式被称为快照 snapshotting.

13.Redis为什么这么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

14.redis针对多路 I/O 复用模型简单探讨

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

15.redis的VM 机制

参考链接:https://www.cnblogs.com/xuegang/archive/2011/11/16/2250920.html

Redis处理的速度很快,因为它是基于内存的。在内存能够足够容纳数据的时候,所有的数据都存放在内存。这个时候不论是读取数据还是写入数据都是非常快的。但是如果数据量很大,大到内存已经无法全部容纳的时候,我想对存储有一定了解的人都在想,这个时候redis是怎么处理的呢?处理速度是否会直线下降?

幸亏,答案是否定的。Redis使用到了VM,在redis.conf设置vm-enabled yes 即开启VM功能。 通过VM功能可以实现冷热数据分离。使热数据仍在内存中,冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。

16.为什么redis 是单线程的?

可以简单说下上边redis这么快的原因。

Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了

高性能服务器不一定是多线程来实现的,多线程不一定比 单线程 效率高,主要看场景。

redis 核心就是数据全都在内存里,单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案
 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值