缓存都有哪些?
缓存的类型分为:本地缓存、分布式缓存和多级缓存。
本地缓存:
本地缓存就是在进程的内存中进行缓存,比如我们的 JVM 堆中,可以用LRUMap来实现,也可以使用Ehcache这样的工具来实现。
本地缓存是内存访问,没有远程交互开销,性能最好,但是受限于单机容量,一般缓存较小且无法扩展。
分布式缓存:
分布式缓存可以很好得解决这个问题。
分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。缺点就是需要进行远程请求,性能不如本地缓存。
多级缓存:
为了平衡这种情况,实际业务中一般采用多级缓存,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。这也是最常用的缓存方案,单靠单一的缓存方案往往难以撑住很多高并发的场景。
Redis简介?
Remote Dictionary Server,本质上是一个Key-Value类型的内存数据库。因而读写速度快,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。广泛应用于缓存方向、分布式锁。Linux版本相当稳定,且用户量大,无需开发windows版本,反而会带来兼容性等问题。
支持保存多种数据结构,单个value的最大限制是1GB。因此Redis可以用来实现很多有用的功能。比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
为什么要用Redis?为什么要用缓存?
因为高性能和高并发。从缓存中读取的性能绝对优于硬盘;直接操作缓存能承受的请求也是远远大于直接访问数据库的。
为什么要用Redis而不是map/guava做缓存?
map/guava实现的是本地缓存,轻量且快速,生命周期随JVM销毁而结束,多实例时,每个实例都要保存一份,不具有一致性。
Redis是分布式缓存,多实例情况下,各实例共用一份缓存数据,具有一致性。缺点是需要保持它的高可用。
缓存常见问题?
缓存更新方式
这是决定在使用缓存时就该考虑的问题。缓存的数据在数据源发生变更时需要对缓存进行更新,数据源可能是 DB,也可能是远程服务。更新的方式可以是主动更新、失效更新异步更新。
数据源是 DB 时,可以在更新完 DB 后就直接更新缓存。
数据源是其他远程服务时,可能无法及时主动感知数据变更,这种情况下一般会选择对缓存数据设置失效期,也就是数据不一致的最大容忍时间。key 不存在或失效时先请求数据源获取最新数据,然后再次缓存,并更新失效期。
但这样做有个问题,如果依赖的远程服务在更新时出现异常,则会导致数据不可用。改进的办法是异步更新,就是当失效时先不清除数据,继续使用旧的数据,然后由异步线程去执行更新任务。避免了失效瞬间的空窗期。或定时对数据进行分批更新。实际使用时可以根据业务场景选择更新方式。
数据不一致
只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 Redis 因为网络原因请求超时;或者是异步更新失败导致。
解决的办法:如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。
缓存雪崩、缓存穿透、缓存击穿问题及解决方案?
缓存穿透
一些恶意的请求会故意频繁查询不存在的key,查缓存不命中,然后穿透DB查询依然不命中。
1. 对查询结果为空的情况也进行缓存,防止相同 ID 再次访问 DB,缓存时间设置短一点。
2. 使用 BloomFilter 过滤器。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。
缓存击穿
缓存击穿,就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。
1. 可以使用互斥锁更新(代码在后面),保证同一个进程中针对同一个数据不会并发请求到 DB,减小 DB 压力。
2. 使用随机退避方式,失效时随机sleep一个很短的时间,再次查询,如果失败再执行更新。
3. 针对多个热点 key 同时失效的问题,可以在缓存时使用固定时间加上一个小的随机数,避免大量热点 key 同一时刻失效。
缓存雪崩
如果缓存集中在一段时间内失效(缓存服务器重启、挂了),发生大量的缓存穿透,所有的查询都落在数据库上,即为缓存雪崩。
1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2. 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
3. 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
一般避免以上情况发生我们从三个时间段去分析下:
事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免** MySQL** 被打死。
事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
限流组件,可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求,走降级!可以返回一些默认的值,或者友情提示,或者空白的值。好处如下:
数据库绝对不会死, 只要数据库不死,就是说,对用户来说,3/5 的请求都是可以被处理的。只要有 3/5 的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。
Redis怎么设置过期时间?怎么设置永久有效?
expire和persist命令。
key的失效机制?
Redis 的 key 可以设置过期时间,过期后 Redis 采用主动和被动结合的失效机对这批key进行删除,定期+惰性+内存淘汰。
定期删除:Redis 默认每隔100ms随机抽取一些设置了过期时间的key,检查过期与否,过期就删除。
惰性删除:和 MC 一样在再次访问时触发被动删除。
Redis淘汰策略有哪些?Redis内存淘汰机制?
redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选出最近最少使用的数据淘汰。
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
allkeys-lru:从数据集中(server.db[i].dict)挑选出最近最少使用的数据淘汰。
allkeys-random:从数据集中任意选择数据淘汰。
no-enviction:禁止驱逐数据。
LRU数据淘汰机制是这样的:在数据集中随机挑选几个键值对,去除其中最近最少使用的键值对淘汰。所以Redis并不是保证取得所有数据集中最少最少使用的键值对,而只是在随机挑选的几个键值对中。
TTL数据淘汰机制:从过期时间redisDB.expires表中随机挑选几个键值对,取出其中最快过期的键值对淘汰。所以Redis并不保证取得所有过期时间表中最快过期的键值对,而是随机挑选的几个键值对中。
Redis如何做内存优化?
缩减键值对象长度:简化键名;使用高效的序列化工具来序列化值对象,还可以使用压缩工具压缩。
共享对象池:Redis内部维护[0-9999]的整数对象池,尽量使用整数对象可节省内存。
尽可能使用散列表(hash数据结构),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面;减少key的数量。
Redis常见性能问题有哪些?该如何解决?
1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。
2).Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
4).Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内
Redis事务?
Redis通过MULTI、EXEC、DISCARD、WATCH等命令来实现事务。
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
但 Redis 提供的不是严格的事务,Redis 只保证串行执行命令,并且能保证全部执行,但是执行命令失败时并不会回滚,而是会继续执行下去。
Redis怎么实现分布锁?
单进程时,即所有线程都在同一个JVM进程里时,JAVA语言提供的锁机制可以起到共享资源同步的作用;分布式环境下,就必须借助分布式锁。分布式有多种解决方案。
Redis持久化机制?Redis持久化有几种方式?
持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
Redis提供了两种持久化方式:RDB(默认)和AOF,AOF文件比RDB更新频率高,优先使用AOF还原数据;AOF比RDB更安全更大;RDB性能比AOF好;如果两个都配了优先加载AOF。
RDB:
RDB(Redis DataBase),对Redis中的数据执行周期性的持久化。可以用来创建主从结构,或原地以备重启。通过创建快照获取内存中数据在某时间点上的副本。
AOF:
AOF(Append-only file),对每条写入命令做日志。相较而言实时性更好。主流的方案。appendonly yes。
每次数据有修改就写入;每秒钟同步一次;让操作系统决定合适同步
每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
Redis和Memcached的区别?
(1) Redis支持更为丰富的数据类型;MC所有的值均是简单的字符串,key 不能超过 250 个字节;value 不能超过 1M 字节;key 的最大失效时间是 30 天。
(2) Redis可以持久化其数据;M把数据都放在内存中。所以 Redis 不仅仅可以用作缓存,也可以用作 NoSQL 数据库。
(3) Redis原生支持集群模式;MC没有原生的
(4) Redis 采用单线程模式处理请求, I/O 多路复用;MC 处理请求时使用多线程异步 IO 的方式,可以合理利用 CPU 多核的优势,性能非常优秀。
Redis应用场景?Redis有哪些适合的场景?
缓存:合理利用缓存,可以提升网站访问速度,降低数据库压力。
计数器:Redis提供的incr命令实现计数器功能,内存操作,性能好。如商品浏览量。
排行榜:Redis提供的有序集合数据类型能够实现各种排行榜。
最新列表:Redis提供的列表lpush、ltrim可以限制列表最左和数量,直接就是最新列表。
消息系统:Redis提供了发布/订阅及阻塞队列功能,可实现一个简单的消息队列系统。
分布式会话:搭建以Redis的内存数据库为中心的session服务。应用不多时使用容器自带的session复制即可。
分布式锁:Redis提供的setnx功能可编写分布式锁,解决对同一资源的并发访问,如减库存、秒杀。并发量不大的话可使用数据库的乐观、悲观锁实现;高并发的场景中数据库锁不理想,影响数据库性能。
社交网络:Redis提供的哈希、集合等数据类型可方便实现点赞、踩、关注、背关、共同好友等社交网站基本功能。因为社交网站的大流量,适不适合用数据库存储这类数据的。
Redis支持的数据类型及使用场景?
String(set,get,decr,incr,mget,等)【二进制安全的】常规计数:微博数,粉丝数。单键最大能存储512M。
List(lpush,rpush,lpop,rpop,lrem,lrange,等)【双向链表】微博关注列表,粉丝列表,消息队列。
Set(sadd,spop,smembers,sunion,等)【哈希表实现】无重复数据列表:共同关注,共同粉丝。
Sorted Set(zadd,zrange,zrem,zcard,等)【哈希表实现】在线用户列表,弹幕消息,礼物排行榜。
Hash(hget,hset,hmset,hgetall,等)【键值对集合】存储对象(没嵌套对象的对象):用户信息,商品信息等。
使用多线程可以提高性能,但每个线程的效率严重下降了,程序的逻辑也会复杂化。Redis支持的数据类型多样,对应的操作也多样,如果多线程可能需要加很多的锁,开销代价很大,所以权衡下采用单线程。
一个是因为采用了非阻塞的异步事件处理机制;
另一个是缓存数据都是内存操作IO时间不会太长,单线程可避免线程上下文切换产生的代价。
如何解决Redis的并发竞争Key问题?
Redis 的并发竞争 Key :多个系统同时对一个 key 进行操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同!
分布式锁(zookeeper 和 redis 都可以实现分布式锁)。(如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能)基于zookeeper临时有序节点可以实现的分布式锁。
大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。
在实践中,当然是从以可靠性为主。所以首推Zookeeper。
Redis支持的Java客户端都有哪些?
Jedis 和 Redisson 都是Java中对Redis操作的封装。Jedis 只是简单的封装了 Redis 的API库,可以看作是Redis客户端,它的方法和Redis 的命令很类似。Jedis相比于Redisson 更原生一些,更灵活。
Redisson 不仅封装了 redis ,还封装了对更多数据结构的支持,以及锁等功能,相比于Jedis 更加大。Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redis和Redisson有什么关系?
Redisson是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象(Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。
Redis 有哪些架构模式?讲讲各自的特点?
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
1.监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
2.提醒(Notification):当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
3.自动故障迁移(Automatic failover):当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。
Twemproxy 是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器;Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。
从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
Redis集群的主从复制模型是怎样的?
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.
怎么测试Redis的连通性?
ping
Redis集群之间是如何复制的?
异步复制
Redis集群最大节点个数是多少?
16384个。
标签:AOF,缓存,Redis,内存,数据,分布式 From: https://www.cnblogs.com/plusjerry/p/16995441.html