【此为"一森咖记"公众号——第86篇文章】
本文预计阅读15分钟
【引言】
当我们为一个并发量较大的应用做数据架构时,会考虑使用缓存,意欲达到三个目标:
1. 加快用户访问速度,提高业务用户体验;
2. 降低后端服务负载,保证系统平滑平稳;
3. 保证数据尽可能及时更新,最大程度保证数据一致性。
之前的两篇文章分别介绍了数据缓存层常用的两个产品redis和memcached,点击如下两篇文章:
今天对比分析下Redis和memcached。
【大纲】
1. Redis和memcached的区别
2. redis相比memcache的优势
3. redis常见性能问题和解决方案
4. 缓存使用时的常见现象
一、 Redis和memcached的区别
1. 数据类型
memcached所有的值均是简单的字符串,redis支持丰富数据类型,支持string,list,set,sorted set,hash;
2. 线程机制
Redis为单线程,Memcached为多线程工作,每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据时,Memcached性能要高于Redis;
3. 存储方式
redis和Memcached均是内存数据库,但redis可以数据持久化,Memcached不支持持久化。Redis并非所有的数据一直在内存,当物理内存用完时,Redis使用LRU算法将value交换到磁盘,memcached超过内存比例会抹掉前面的数据。故,memcached断电,重启系统后,数据不可恢复;redis数据丢失后可以通过RDB和AOF恢复。
4. 分布式存储
Memcached和Redis是基于服务器物理内存级的数据缓存,如需要处理的数据量超过单台机器的物理内存,就需构建分布式集群来扩展存储能力。
Memcached本身并不支持分布式,只能在客户端通过像一致性哈希这样的分布式算法
来实现Memcached的分布式存储,为客户端式分布式缓存;Redis更偏向于服务器端构建分布式缓存,没有采用一致性哈希做分布式。在Redis Cluster中,每个Master节点都有对应的两个冗余Slave节点。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。熟悉MySQL高可用架构MHA部署的亲,可以更容易理解。
5. 底层模型不同
Redis自己构建VM机制 ,而系统调用系统函数会浪费一定的时间去移动和请求。
6. value大小
redis最大可以达到1GB,而memcache只有1MB
小结:
1. redis支持master-slave复制模式;memcache可以使用一致性hash做分布式。
2. 如有持久化方面的需求或者对数据类型和处理有要求,应选择redis;
3. 如果是简单的key/value存储可以考虑memcached;
4. 内存管理机制,Memcached主要的cache机制是LRU算法+超时失效。Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。
二、 redis相比memcache的优势
1、 memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型;
2、redis的速度比memcached快很多;
3、redis可以持久化其数据。
市面上,目前使用redis较多,但须知redis有哪些性能问题。
三、 redis常见性能问题和解决方案
1.Master最好不要做任何持久化工作(RDB内存快照和AOF日志文件)
原因: 1) 如Master写RDB内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写RDB内存快照。2) Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
如RDB内存快照和AOF日志文件;
2.如果数据比较重要,Slave开启AOF备份数据,策略设置最好为每秒同步一次;
3.为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网;
4.避免在压力很大的主库上增加从库;
5.主从复制不要用图状结构,用串行链表结构,可方便解决单点故障问题,实现Slave对Master的替换。如果Master宕机,可立刻启用Slave1做Master。
四、 缓存使用时的常见现象
使用数据缓存会发生几种现象和解决方法:缓存雪崩、缓存击穿、缓存击穿、缓存预热。
4.1缓存穿透
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透,也是经常提的缓存命中率问题。
解决办法
1. 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
2. 如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,但它的过期时间会很短,最长不超过五分钟。这种办法最简单粗暴。
4.2缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
由于原有缓存失效(过期),新缓存未到期间。所有请求都去查询数据库,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
某个时期缓存集中过期时自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,数据库如能顶住压力,缓存的定期创建无非就是对数据库产生周期性压力;比较可怕的是而缓存服务节点宕机,对数据库服务器造成的压力是不可预知,很可能瞬间把数据库压垮。
解决办法
1)在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。如对某个key只允许一个线程查询数据和写缓存,其他线程等待。此方法只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完;加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,过来100个请求99个都在阻塞。同样会导致用户等待超时,此方法治标不治本。
2)可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存;
3)设置不同的key的过期时间,让缓存失效时间点尽量均匀. 如可以在原有的失效时间上增加一个随机值,如1-5分钟随机。缓存的过期时间的重复率就会降低,避免引发集体失效的事件;
4)做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期;此方法等同于方法3。
4.3缓存击穿
缓存击穿,是指一个key非常热点,,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞,引起数据库压力瞬间增大,造成过大压力。
缓存击穿和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
解决办法:
1)设置热点数据永远不过期,这种方案由于没有设置真正的过期时间,实际上已经不存在热点 key 产生的一系列危害,但会存在数据不一致,代码复杂度会增大。
加互斥锁,此方案思路简单,但存在一定隐患,如构建缓存过程出现问题或者时间较长,可能会存在死锁和线程池阻塞的风险;这种方法最大的优点是能较好的降低后端存储负载并在一致性上做的较好。
缓存预热
缓存预热就是系统上线后,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,再将数据缓存的问题。用户直接查询事先被预热的缓存数据。
解决方法:
1)直接写个缓存刷新页面,上线时手工操作下。
2)数据量不大,可以在应用启动时提前加载常用的热点数据。
3)定时刷新缓存
4.4缓存更新
通过expire来设置key的过期时间,Redis的6种数据淘汰策略:
1)noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
2)allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
3)volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
4)allkeys-random: 回收随机的键使得新添加的数据有空间存放。
5)volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
6)volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
除了上述缓存失效策略外,还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:
1)定时去清理过期的缓存;
2)当用户请求过来时,再行判断此请求所用缓存是否过期,过期的话就去库取新数并更新缓存。
方法1优点简单,缺点是维护大量缓存的key是繁琐;
方法2缺点是每次用户请求均要判断缓存是否失效,逻辑相对复杂;
上述两种客户化方法业务可根据具体业务场景来权衡使用。
4.5缓存降级
当访问量剧增、响应时间慢或不响应、非核心服务影响到核心流程的性能时,为保证核心业务服务可用,可对某些数据服务自动降级或人工降级。如电商系统无法降级的服务有加入购物车、订单结算;可降级的服务有某些商品的访问浏览。
【总结】
1. 如下两篇推文分别讲述了redis和memcached的两种缓存;
2. 今天文章内容主要介绍了两者的区别,并介绍了使用数据缓存时常见的缓存击穿、缓存穿透、缓存雪崩5种常见现象和处理方式;
3. 后续将持续进行试验进行论证。
To be continued.
【参考】
https://blog.csdn.net/m0_37501154/article/details/89916036
【参考】
https://www.cnblogs.com/lijiasnong/p/9963853.html
【参考】
https://blog.csdn.net/qq_36071795/article/details/83988177
以下为个人公众号“一森咖记”,欢迎关注。