转载

个人整理 - Java后端面试题 - 缓存篇

★redis的主从复制怎么做的?

Redis主从复制可以根据是否是全量分为全量同步和增量同步。以下对其相应的同步过程及原理做下简要说明。
增量同步

Redis增量同步主要指Slave完成初始化后开始正常工作时,Master发生的写操作同步到Slave的过程。通常情况下,
Master每执行一个写命令就会向Slave发送相同的写命令,然后Slave接收并执行。
全量同步

Redis的全量同步过程主要分三个阶段:

同步快照阶段:Master创建并发送快照给Slave,Slave载入并解析快照。Master同时将此阶段所产生的新的写命令存储到缓冲区。
同步写缓冲阶段:Master向Slave同步存储在缓冲区的写操作命令。
同步增量阶段:Master向Slave同步写操作命令。

★redis为什么读写速率快性能好?

纯内存操作。
核心是基于非阻塞的 IO 多路复用机制。
C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。
单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。

redis为什么是单线程的?

  • 我们要去理解为什么多线程好,多线程好在IO慢的时候才能凸显出高性能,因为在一个线程等待IO的时候马上切换线程运行。
  • 而在Redis中数据都在内存当中,IO非常快,如果还是采用多线程的话,反而会浪费时间在线程的上下文切换。

缓存的优点?

  1. 减少了对数据库的读操作,数据库的压力降低
  2. 加快了响应速度

★aof与rdb的优点和区别?

持久化RDB(redis database)和AOF(append only file)的区别

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,  
写入成功后,再替换之前的文件,用二进制压缩存储。 RDB持久化保存键空间的所有键值对(包括过期字典中的数据),并以二进制
形式保存,符合rdb文件规范,根据不同数据类型会有不同处理。

AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细
的操作记录。AOF持久化保存redis服务器所执行的所有写命令来记录数据库状态,在写入之前命令存储在aof_buf缓冲区。

持久化RDB和AOF的优缺点:

RDB存在哪些优势呢?
(1) 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时
归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常
容易的进行恢复。
(2) 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
(3) 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化
的工作,这样就可以极大的避免服务进程执行IO操作了。
(4) 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

RDB又存在哪些劣势呢?

(1) 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现
宕机现象,此前没有来得及写入磁盘的数据都将丢失。
(2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,
甚至是1秒钟。

AOF的优势有哪些呢?
(1) 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3种同步策略,即每秒同步、每个命令同步和不同步。事实上,
每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每个命令
同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无
同步,由操作系统决定任何将缓冲区里面的命令写入磁盘里面,在这种模式写,服务器遭遇意外停机时,丢失命令的数据是不确定的
(2) 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的
内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-
check-aof工具来帮助我们解决数据一致性的问题。
(3) 如果日志过大,Redis可以自动启用rewrite机制。主要是为了解决aof文件不断增长减少重复键读写操作的日志, 通过定时触发,
重新根据实际内存键值情况写入新的aof文件, 再进新旧替换文件,实现aof文件最小化。
(4) AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

AOF的劣势有哪些呢?
(1) 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
(2) 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB
一样高效。

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来
换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境
其实更多都是二者结合使用的。

redis的List能用做什么场景?

1.消息队列。2.排行榜。3.最新列表。

用java自己实现一个LRU。

继承LinkHashMap并重写removeEldestEntry方法。

★为什么用缓存,用过哪些缓存,redis和memcache的区别

使用缓存,最主要的目的是提升系统的响应速度和对高负载的承受能力。

redis,memcached都有用过。

  1. 数据操作不同
  • 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能。Redis支持服务器端的数据操作相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,支持list、set、sorted set、hash等众多数据结构,还同时提供了持久化和复制等功能。
  • 而通常在Memcached里,使用者需要将数据拿到客户端来进行类似的修改再set回去,这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作, Redis会是更好的选择。
  1. 内存管理机制不同
  • 在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。
  • 而Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。
  • 从内存利用率来讲,使用简单的key-value存储的话,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。
  1. 性能不同
  • 由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis也在存储大数据的性能上进行了优化,但是比起Memcached,还是稍有逊色。
  1. 集群管理不同
  • Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。
  • Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。

redis的持久化方式,以及项目中用的哪种,为什么

  • RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

  • AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

  • 二者优缺点

  • RDB存在哪些优势呢?

  • 1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。

  • 2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。

  • 3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。

  • 4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

  • RDB又存在哪些劣势呢?

  • 1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

  • 2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

  • AOF的优势有哪些呢?

  • 1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。

  • 2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。

  • 3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

  • 4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

  • AOF的劣势有哪些呢?

  • 1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

  • 2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

  • 二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。

★redis集群的理解,怎么动态增加或者删除一个节点,而保证数据不丢失。(一致性哈希问题)

先添加删除节点,再移动槽位 reshard,利用一致性哈希的原理保证移动槽位的时候不影响其他节点。

★Redis的缓存失效策略

FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。

LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。

LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

缓存穿透的解决办法

导致缓存穿透的原因:

  1. 恶意攻击,猜测你的key命名方式,然后估计使用一个你缓存中不会有的key进行访问。
  2. 第一次数据访问,这时缓存中还没有数据,则并发场景下,所有的请求都会压到数据库。
  3. 数据库的数据也是空,这样即使访问了数据库,也是获取不到数据,那么缓存中肯定也没有对应的数据。这样也会导致穿透。
    解决缓存穿透:
  4. 再web服务器启动时,提前将有可能被频繁并发访问的数据写入缓存。—这样就规避大量的请求在第3步出现排队阻塞。
  5. 规范key的命名,并且统一缓存查询和写入的入口。这样,在入口处,对key的规范进行检测。–这样保存恶意的key被拦截。
  6. Synchronized双重检测机制,这时我们就需要使用同步(Synchronized)机制,在同步代码块前查询一下缓存是否存在对应的key,然后同步代码块里面再次查询缓存里是否有要查询的key。 这样“双重检测”的目的,还是避免并发场景下导致的没有意义的数据库的访问(也是一种严格避免穿透的方案)。这一步会导致排队,但是第一步中我们说过,为了避免大量的排队,可以提前将可以预知的大量请求提前写入缓存。
  7. 不管数据库中是否有数据,都在缓存中保存对应的key,值为空就行。–这样是为了避免数据库中没有这个数据,导致的平凡穿透缓存对数据库进行访问。
  8. 第4步中的空值如果太多,也会导致内存耗尽。导致不必要的内存消耗。这样就要定期的清理空值的key。避免内存被恶意占满。导致正常的功能不能缓存数据。

★redis集群,高可用,原理

https://www.cnblogs.com/telwanggs/p/10856157.html

mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

即redis的缓存每命中一次,就给命中的缓存增加一定ttl(过期时间)(根据具体情况来设定, 比如10分钟).

一段时间后, 热数据的ttl都会较大, 不会自动失效, 而冷数据基本上过了设定的ttl就马上失效了.

用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次

使用userId为key

ttl为一小时的数字值表示登录次数

超过5次即限制

★如何做到缓存数据一致性。

设置过期时间 加 双删

如何防止缓存穿透、雪崩、击穿。

一、缓存穿透

概念:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解决方案:

  1. 接口校验请求参数的有效性,如校验id是否合法
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒。

二、缓存雪崩

概念:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。侧重很多的缓存数据都失效了。

解决方案:

  1. 设置不同的缓存到期时间,如热门数据有效期长一点,冷门数据有效期短一点。
  2. 针对长期有效,数据变化基本不变的数据进行永久性缓存。
  3. 缓存服务集群部署

三、缓存击穿

概念:

指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

解决方案:

  1. 热点数据实现缓存永久有效
  2. 采用互斥锁来缓存数据
  3. 缓存击穿的重点就是,同一时间点上,大量请求没有在缓存中命中数据,而对数据库服务产生巨大的压力,所以我们可以在请求数据库之前加上一个锁,持有锁的线程才能去请求数据库,并缓存到缓存数据库,其他的线程等待,最后从缓存获获取数据。

redis的list结构相关的操作。

list是双向链表。列表常用来作为异步队列使用

通过使用rpush、rpop、lpush、lpop四条指令,在链表的表头和表尾追加或移除元素,可以将链表作为队列或堆栈使用;

★redis2和redis3的区别,redis3内部通讯机制。

  • 哨兵的作用就是监控Redis系统的运行状况。它的功能包括以下两个。
  • 监控主数据库和从数据库是否正常运行。
  • 主数据库出现故障时自动将从数据库转换为主数据库。
  • sentinel发现master挂了后,就会从slave中重新选举一个master。
  • 哨兵模式强调高可用
  • Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
    自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
  • 客户端中不会记录redis的地址(某个IP),而是记录sentinel的地址,这样我们可以直接从sentinel获取的redis地址,因为sentinel会对所有的master、slave进行监控,它是知道到底谁才是真正的master的,例如我们故障转移,这时候对于sentinel来说,master是变了的,然后通知客户端。而客户端根本不用关心到底谁才是真正的master,只关心sentinel告知的master。
  • 集群
  • 即使使用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,就是分布式存储。即每台redis存储不同的内容,共有16384个slot。每个redis分得一些slot,hash_slot = crc16(key) mod 16384 找到对应slot,键是可用键,如果有{}则取{}内的作为可用键,否则整个键是可用键
  • 集群至少需要3主3从,且每个实例使用不同的配置文件,主从不用配置,集群会自己选。
  • cluster是为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器。
  • 集群模式提高并发量。

redis和memcached 的内存管理的区别。

  • 在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。
  • Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。

★Redis的并发竞争问题如何解决,了解Redis事务的CAS操作吗。

  1. 使用incr
  2. 使用watch
  3. 分布式锁

Redis的选举算法和流程是怎样的。

监视这个挂了的主节点的所有Sentinel都有被选举为领头的资格
每进行一次选举,不论是否成功,配置纪元+1,配置纪元就是个计数器
每个Sentinel在每个配置纪元中有且仅有一次选举机会,一旦选好了该节点认为的主节点,在这个纪元内,不可以再更改
每个发现服务器挂了的Sentinel都会配置纪元+1并投自己一票,接着发消息要求其他Sentinel设置自己为领头人1,每个Sentinel都想成为领头的
每个Sentinel会将最先发来请求领头的节点设为自己的领头节点并发送回复,谁先来我选谁
当源Sentinel收到回复,并且回复中的配置纪元和自己的一致且领头Id是自己的Sentinel Id时,表明目标Sentinel已经将自己设为领头
在一个配置纪元内,当某个Sentinel收到半数以上的同意回复时,它就是领头的了
如果在给定时间内,没有被成功选举的Sentinel,那么过段时间发起新的选举
选举领头Sentinel的过程和规则大概就如上所述,需要注意的是只有集群出现节点挂了才需要选举出领头Sentinel,平时每个Sentinel还是平等身份~
这里的选举其实是raft算法的一个应用.

★redis的集群怎么同步的数据的(Reids的主从复制机制原理)。

  1. redis的复制功能是支持多个数据库之间的数据同步。一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。
  2. 通过redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力。主数据库主要进行写操作,而从数据库负责读操作。
  3. 当一个从数据库启动时,会向主数据库发送sync命令,
  4. 主数据库接收到sync命令后会开始在后台保存快照(执行rdb操作),并将保存期间接收到的命令缓存起来
  5. 当快照完成后,redis会将快照文件和所有缓存的命令发送给从数据库。
  6. 从数据库收到后,会载入快照文件并执行收到的缓存的命令。

redis优化详解

https://blog.csdn.net/qq_39399966/article/details/101211939

https://blog.csdn.net/achuo/article/details/80600170

★Redis的线程模型是什么。

  • Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
  • 尽管多个文件事件可能会并发地出现,但I/O多路复用程序总是会将所有产生事件的套接字都推到一个队列里面,然后通过这个队列,以有序(sequentially)、同步(synchronously)、每次一个套接字的方式向文件事件分派器传送套接字:当上一个套接字产生的事件被处理完毕之后(该套接字为事件所关联的事件处理器执行完毕), I/O多路复用程序才会继续向文件事件分派器传送下一个套接字。

集中式缓存和分布式缓存?

集中式:容量,并发瓶颈,但一致性有保证。

分布式:提升容量,并发能力,但会有一致性问题。

elasticsearch 索引数据多了怎么办,如何调优,部署。

Elasticsearch在部署时,对Linux的设置有哪些优化方法?

elasticsearch是如何实现master选举的。

详细描述一下Elasticsearch搜索的过程。

redis和memcache的区别

  • redis使用单线程模型,数据顺序提交,redis支持主从模式,mencache只支持一致性hash做分布式;redis支持数据落地,rdb定时快照和aof实时记录操作命令的日志备份,memcache不支持;redis数据类型丰富,有string,hash,set,list, sort set,而memcache只支持简单数据类型;memcache使用cas乐观锁做一致性。

  • jedis操作Hash:hmset, hmget, hdel, hkeys

  • jedis操作List: lpush,lrange按照范围取出,rpush, del, sort等keyjedis操作Set:sadd,srem移除noname,smembers, sismember, scard等。summary.note

  • 使用场景例如

  • Hash:存储读取更新用户多个属性

  • List:微博TimeLine,消息列表

  • Set:共同好友,二度好友,用唯一性可以统计网站所有独立IP,好友推荐根据tag求交集,大于threshold就可以推荐。

  • sortset:set增加1个权重score参数

  • 其他场景:A订阅发布系统,redis对某个key消息发布及订阅,当1个key消息发布后,所有订阅它的客户端都会收到相应消息,例如实时消息系统,即时聊天,群聊等。

  • 事务-常用EX,EC提交执行的命令,在server不出问题,可以保证一连串的命令是顺序执行额;提供1个watch功能,对1个key作watch,然后再执行transation。

redis过期淘汰策略

  • redis内存数据上升到一定大小会执行数据淘汰策略,redis提供了6种数据淘汰策略。

  • LRU:从已设置过期时间的数据集合中挑选最近最少使用的数据淘汰

  • random:从已设置过期时间的数据中挑选任意数据淘汰

  • ttl:从已设置过期时间的数据集合中挑选将要过期的数据淘汰。

  • notenvision:禁止驱逐数据

  • 如mysql中有2千万数据,redis只存储20万的热门数据。LRU或者TTL都满足热点数据读取较多,不太可能超时特点。

  • redis特点:速度块,O(1),丰富的数据类型,支持事物原子性,可用于缓存,比memecache速度块,可以持久化数据。

  • 常见问题和解决:Master最好不做持久化如RDB快照和AOF日志文件;如果数据比较重要,某分slave开启AOF备份数据,策略为每秒1次,为了主从复制速度及稳定,MS主从在同一局域网内;主从复制不要用图状结构,用单向链表更为稳定 M-S-S-S-S。。。。;redis过期采用懒汉+定期,懒汉即get/set时候检查key是否过期,过期则删除key,定期遍历每个DB,检查制定个数个key;结合服务器性能调节并发情况。

  • 过期淘汰,数据写入redis会附带1个有效时间,这个有效时间内该数据被认为是正确的并不关心真实情况,例如对支付等业务采用版本号实现,redis中每一份数据都维持1个版本号,DB中也维持1份,只有当redis的与DB中的版本一致时,才会认为redis为有效的,不过仍然每次都要访问DB,只需要查询version版本字段即可。

如何将数据分布在redis第几个库?

答:redis 本身支持16个数据库,通过 数据库id 设置,默认为0。

例如jedis客户端设置。一:JedisPool(org.apache.commons.pool.impl.GenericObjectPool.Config poolConfig, String host, int port, int timeout, String password, int database);

第一种通过指定构造函数database字段选择库,不设置则默认0库。二:jedis.select(index);调用jedis的select方法指定。

Elasticsearch分片使用优化?

(1)拆分集群

对于存在明显分界线的业务,可以按照业务、地域使用不同集群,这种拆分集群的思路是非常靠谱的。对于我们的场景,已经按照地域拆分了集群,且同一地域的子业务间分界线不明显,拆分过多的集群维护成本较高。

(2)调整滚动周期

根据保留时长调整index滚动周期是最简单有效的思路。例如保留3天的数据按天滚动,保留31天的数据按周滚动,保留一年的数据按月滚动。合理的滚动周期,可以在存储成本增加不大的情况下,大幅降低分片数量。

对于我们的场景,大部分数据保留31天,在按周滚动的情况下,集群的总分片数可以下降到6.5w~个。

(3)合理设置分片数和副本数

除个别子业务压力较高外,大部分业务压力较小,合理设置单Index的分片数效果也不错。我们的经验是单个分片的大小在10GB~30GB之间比较合适,对于压力非常小的业务可以直接分配1个分片。其他用户可结合具体场景考虑,同时注意单分片的记录条数不要超过上限2,147,483,519。

在平衡我们的业务场景对数据可靠性的要求 及 不同副本数对存储成本的开销 两个因素之后,我们选择使用一主一从的副本策略。

目前我们集群单Index的平均分配数为3,集群的总分片数下降到3w~个。

(4)分片分配流程优化

默认情况下,ES在分配分片时会考虑分片relocation对磁盘空间的影响。在分片数较少时,这个优化处理的副作用不明显。但随着单机分片数量的上升,这个优化处理涉及的多层循环嵌套过程耗时愈发明显。可通过cluster.routing.allocation.disk.include_relocations: false关闭此功能,这对磁盘均衡程度影响不明显。

(5)预创建Index

对于单集群3w分片的场景,集中在每周某天0点创建Index,对集群的压力还是较大,且存储空间存在波动。考虑到集群的持续扩展能力和可靠性,我们采用预创建方式提前创建分片,并把按Index的创建时间均匀打散到每周的每一天。

(6)持续调整分片数

对于集群分片的调整,通常不是一蹴而就的。随着业务的发展,不断新增的子业务 或 原有子业务规模发生突变,都需要持续调整分片数量。

默认情况下,新增的子业务会有默认的分片数量,如果不足,会在测试阶段及上线初期及时发现。随着业务发展,系统会考虑Index近期的数据量、写入速度、集群规模等因素,动态调整分片数量。

ElasticSearch如何解决深度分页的问题?

使用scroll(有状态)和search after(无状态)的游标方式。

lucence倒排索引

  • 三个文件:字典文件,频率文件,位置文件。词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。

  • field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。

  • 关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。

  • 假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。

  • 对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。对数字的压缩,数字只保存与上一个值的差值。

原文  http://vc2x.com/articles/2020/03/12/1584005499997.html
正文到此结束
Loading...