2、为啥在项目里要用缓存呢?
用缓存,主要用途,高性能和高并发
高性能:
场景举例:假如有这么一个操作,用户发起请求,操作数据库,查出结果,耗时600ms,然后这个结果,在一段时间内都不会改变,或者说改变了也不用立即向用户反馈,那么这个时候就可以用缓存了,把查出来的结果直接放到缓存里,下次再有人来请求,就直接在缓存里通过key value键值对给到用户,性能提高!
简单的说就是,把一个复杂耗时的操作的结果,后面不怎么需要改变的结果,但是有很多的读取操作,就可以使用缓存,后面读取的时候直接从缓存中读就可以了。
高并发:因为数据库不支持高并发,像mysql最高也就支持到2000,然后我们把数据放到缓存中去,轻轻松松的十几万的并发,是mysql的几十倍。
3 、使用缓存有什么缺点?
1)缓存与数据库双写不一致
2)缓存雪崩
3)缓存穿透
4)缓存并发竞争
4、redis和memcached有什么区别?
redis:线程模型是单线程NIO异步的工作模型。
-
数据结构 :redis拥有更多的数据结构和更多的数据结构,很多复杂的操作跟高效
2.集群redis官方就是支持redis cluster集群模式,而menacahe不支持,需要依赖客户端。
5、redis都有哪些数据类型?
String
用来抢购,用来限制库存数量做一个计数器,就可以用string类型
分布式锁
string类型的setnx的作用是“当key不存在时,设值并返回1,当key已经存在时,不设值并返回0”,“判断key是否存在”和“设值”两个操作是原子性地执行的,因此可以用string类型作为分布式锁,返回1表示获得锁,返回0表示没有获得锁。
list
是一个有序列表,
可以用来做简单的点对点消息队列,和可以用来做粉丝列表,评论列表,
还可以通过lrange命令,就是从某个元素开始读取多少个元素,可以基于list实现分页查询,这个很棒的一个功能,基于redis实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走
set
无序集合,自动去重
可以用于去重,将需要去重的数据放进去。自动去重,
如果需要对一些数据进行进行快速的全局去重,可以使用jvm的hashSet进行去重,但是如果是在多台机器上的话就需要用redis的set进行去重,
也可以基于set对数据进行交集,并集,差集操作。比如,微博里的粉丝可以做一个交集,就可以查看两个人的共同好友
黑名单/白名单
sorted set
可以去重,有序。
可以用来做排行榜,比如商品的销量排行 收藏排行等
hash
这个是类似map的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象没嵌套其他的对象)给缓存在redis里,然后每次读写缓存的时候,可以就操作hash里的某个字段。 比如项目中可以哟来做购物车用户id为key 商品id为field,商品数量为value;
结构:
key=150
value={
“id”: 150,
“name”: “zhangsan”,
“age”: 20
}
6、redis的过期策略都有哪些?
设置过期时间定期删除和惰性删除最后走内存淘汰机制
7、内存淘汰机制都有哪些?
1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给干掉啊
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
8、手写一下LRU代码实现?
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
// 这里就是传递进来最多能缓存多少数据
public LRUCache(int cacheSize) {
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true); // 这块就是设置一个hashmap的初始大小,同时最后一个true指的是让linkedhashmap按照访问顺序来进行排序,最近访问的放在头,最老访问的就在尾
CACHE_SIZE = cacheSize;
}
9、如何保证redis的高并发以及高可用?
redis单机的瓶颈 能够承受的QPS大概就是在1万到几万
使用redis replication 主从实现读写分离支撑10万+的高并发,将架构做成主从架构,一主多从,主负责写,将数据同步到从节点上,从节点负责读,所有的读取请求都走从节点,这个架构支持水平扩容,只需要再在增加从节点就OK
10、redis replication的核心机制
(1)redis采用异步方式复制数据到slave节点,不过redis 2.8开始,slave node会周期性地确认自己每次复制的数据量 (2)一个master node是可以配置多个slave node的 (3)slave node也可以连接其他的slave node (4)slave node做复制的时候,是不会block master node的正常工作的 (5)slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了 (6)slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量slave,高可用性,有很大的关系
11、master持久化对于主从架构的安全保障的意义
如果采用了主从架构,那么建议必须开启master node的持久化!
不建议用slave node作为master node的数据热备,因为那样的话,如果你关掉master的持久化,可能在master宕机重启的时候数据是空的,然后可能一经过复制,salve node数据也丢了
master -> RDB和AOF都关闭了 -> 全部在内存中
master宕机,重启,是没有本地数据可以恢复的,然后就会直接认为自己的数据是空的
master就会将空的数据集同步到slave上去,所有slave的数据全部清空
100%的数据丢失
master节点,必须要使用持久化机制
第二个,master的各种备份方案,要不要做,万一说本地的所有文件丢失了; 从备份中挑选一份rdb去恢复master; 这样才能确保master启动的时候,是有数据的
即使采用了后续讲解的高可用机制,slave node可以自动接管master node,但是也可能sentinal还没有检测到master failure,master node就自动重启了,还是可能导致上面的所有slave node数据清空故障
12、主从架构的核心原理
当启动一个slave node的时候,它会发送一个PSYNC命令给master node
如果这时slave node重新连接master node,那么master node仅仅会复制给slave部分缺少的数据; 否则如果是slave node第一次连接master node,那么会触发一次full resynchronization
开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。
slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。
2、主从复制的断点续传
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份
master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制
但是如果没有找到对应的offset,那么就会执行一次resynchronization
3、无磁盘化复制
master在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘了
repl-diskless-sync repl-diskless-sync-delay,等待一定时长再开始复制,因为要等更多slave重新连接过来
4、过期key处理
slave不会过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave。
主备切换。或者叫故障转移,需要我们在主从架构中加入entinal node(哨兵)负责监控master node 和slave node的进程是否正常工作。 一旦检查到master挂掉之后,就会发送消息通知到管理员,同时将其中一个salve升级为master 提供写和同步的功能,因为salve上的数据和master上的数据是一样的。最后通知client客户端新的master地址
哨兵作为维护主从架构的高可用,其自身是一个分布式的,并且至少需要3个哨兵实例来保证自己的健壮性