1.缓存(redis)
1.1本地缓存
本地缓存就是在进程的内存中进行缓存,比如我们的JVM堆中,可以LRUMap来实现,也可以使用Ehcache这样的工具来实现;本地缓存是内存访问,没有远程交互开销,性能最好,但受限于单机容量,一般缓存较小,且无法扩展。
1.2分布式缓存
分布式缓存可以很好的解决本地缓存的哪些问题,分布式缓存一般具有很好的水平扩展能力,对较大数据量的场景也能应付,缺点就是需要远程请求,性能不如本地缓存。
1.3多级缓存
实际业务中一般采用多级缓存,本地缓存只保存访问频率最高的那部分热点数据,其他的热点数据放在分布式缓存中
2.淘汰策略
不管是本地缓存还是分布式缓存,为了保证较高性能,都使用内存来保存数据,由于成本和内存限制,当存储的数据超过缓存容时,需要对缓存数据进行剔除,一般的剔除策略有FIFO淘汰最早的数据,LRU剔除最近最少使用的,和LFU剔除最近使用频率最低的数据几种策略。
LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
3.redis
3.1redis特点:
- 与mc不同的是,Redis采用的是单线程模式处理请求。这样做的原因有两个:一个是因为采用了非阻塞的异步事件处理机制;另一个是缓存数据都是内存操作IO时间不会太长,单线程可以避免线程上线文切换产生的代价
- Redis支持持久化,所以Redis不仅仅可以用作缓存,也可以用作NoSql数据库。
- 相较于mc,Redis有一个非常大的优势,就是除K-V之外,还支持多种数据格式,例如list,set,sorted set ,hash等
- Redis提供主从同步机制,以及集群部署能力,能够提供高可用服务。
3.2redis持久化
作用:可以有效防止在redis宕机后,缓存失效问题
Redis提供了RDB和AOF两种持久化方式;
- RDB是把内存中的数据集以快照的形式写入磁盘,d对应产生的数据文件为.rdb格式文件。通过定义配置文件中save的参数来定义快照周期。实际操作时使用forK子进程执行,采用二进制压缩存储。
优点:
1.只有一个rdb文件,方便持久化
2.容灾性好,一个文件可以保存到安全的磁盘
3.性能最大化,fork子进程来完成写操作,主进程继续处理命令,所以IO最大化,使用单独子进程进行持久化,主进程不会进行任何IO操作,保证redis的高新能
缺点:
1.数据安全性低,rde是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失,所以这种方式更适合数据要求不严谨的时候
- AOF是将redis执行的每次写命令记录到单独的日志文件中,当重启redis会重新将持久化的日志文件数据恢复。
优点:数据安全
缺点:
1.AOF文件比RDE文件大,且恢复速度慢
2数据集大的时候比rdb启动效率低.
3.3redis高可用
redis支持主从同步,提供Cluster集群部署模式,通过Sentine l哨兵来监控redis主服务器的状态。当主挂掉时,在节点中根据一定策略选出新主,并调整其他从slaveod到新主
选主的策略简单来说有三个:
- slave的priority(优先级)设置的越低,优先级越高;
- 同等情况下,slave复制的数据越多优先级越高
- 相同条件下runid越小越容易选中
3.4redis失效机制
redis的key可以设置过期时间,过期后的redis采用主动和被动结合的失效机制,一个是和MC一样,在访问时触发被动删除,另一个是定期的主动删除。
3.5redis的过期时间和永久永久有效应该怎么设置?
expire和persist命令设置
3.6redis的淘汰策略
redis提供了6中淘汰策略,一类是只针对设置了失效期的key做LRU,最小生存时间和随机剔除;另一类是针对所以key做LRU,当然也可以不剔除,容量满时间再存储对象会返回异常,但是已存在的key可以继续读取
3.7缓存常见问题
3.8缓存雪崩
在一个较短时间内,缓存中较多的Key集中过期或者缓存挂了,导致数据库服务端崩溃。
解决方案:
在批量往redis存数据的时候,把每个key的失效时间都加一个随机值就好了,这样就可以保证数据不会同一时间大面积失效。如果redis是集群部署,将热点数据均匀的分布在不同的redis库中也能避免全部失效。或者设置热点数据永不过期,有更新操作就更新缓存就好了。
3.8缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求;我们数据库的id都是从1开始自增上去的,如果发起为id为-1的数据或者id为特别大的不存在的数据,这时的用户可能为攻击者,攻击者会导致数据建库压力过大,严重的会击垮数据库。
解决:
1.在接口层增加校验,比如用户权限,参数做校验,不合法的参数字节return;
2.从缓存中取不到的数据在数据库也没有取到,这时可以将对应key的value对写为null,缓存有效时间可以设置为很短,比如30S
3.布隆过滤器,原理:利用高效的数据结构和算法快速判断你这个key是否在数据库中存在,不存在return就好了,存在就去查DB刷新KV再return
3.9缓存击穿
跟缓存雪崩较像,缓存雪崩是大面积的key失效,打崩了DB,而击穿不同的是指一个key非常热点,在不停的扛着大并发,当这个key失效的一瞬间,持续的大并发就击穿了缓存,直接请求数据库。u
4.Memcache
4.1Memcache特点
- mc处理请求时使用多线程异步IO的方式,可以合理利用CPU多核的优势,性能非常优秀。
- mc功能简单,使用内存存储数据,只支持K-V结构,不提供持久化和主从同步功能
- mc对缓存数据可设置失效期,过期后数据会被清除
- 失效的策略采用延迟失效,就是当再次使用数据时检查是否失效
- 当容量存满时,会对缓存中的数据进行剔除,剔除时除了会对过期的Key进行清理,还会按LRU策略对数据进行剔除。
另外mc还有一些限制 - key不能超过250个字节
- value不能超过1M字节
- key的最大失效时间是30天
5.redis实现分布式缓存
5.1什么是分布式锁?
当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问
5.2分布式锁实现
分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息。搭建一个redis服务器,用redis服务器来存储锁信息。
要实现的时候注意以下几点
1.锁信息必须是会过期超时的,不能让一个线程长期占有一个锁而导致死锁
2.同一时刻只能有一个线程获取到锁。