这绝对是一份价值不菲的memcache使用总结

简介: 这绝对是一份价值不菲的memcache使用总结

在互联网应用场景的网络架构中基本上用到了memcache,因此memcache作为分布式缓存之一使用是比较广泛的,本文是阿青多年使用memcache的总结,绝对价值不菲,值得一看(以下mc是memcache的简称)。


一.MC适用场景

业务上对数据的要求满足如下方面的场景才适用。


l数据变化不频繁但访问频繁


无用户关联性


有访问通用性


数据安全要求低


数据一致性要求低


无持久化要求


例如秒杀、抢购、抽奖活动的商品或礼品库存计数递减的场景,此场景对数据的可靠一致性要求很高,放在mc不可靠,很有可能被置换出去。


二.缓存key设置

1.key值最大长度250个字符,尽可能设置短些,不能设置太长,如果太大浪费内存。


2.key值不能有空格和控制字符等特殊符号,如\n \r,最好不要使用中文,如使用了中文要key作MD5。


3.key值需按业务逻辑设置足够短后再MD5,不过key转MD5后需要实现获取key的功能,以便于清理mc或排查故障时需要拿到key。


4.按业务逻辑来设置key,合理设置缓存key的粒度,以便提高命中率,比如产品终端页面的某个豆腐块是根据产品小类或品牌等出数据的,应用小类id或品牌id为基础设置key,而不是无脑地使用产品id为基础设置key。


三.缓存value值设置

1. value过期时间默认最大30天,如设置过期时间大于30天,值会设置不进缓存。


2. value最大能存储1MB,如果数据大于1MB可以考虑压缩或拆分到多个key中,在应用于页面级的缓存时要特别注意。


3.value最好转为string来保存。


4.不要多重嵌套mc缓存。


四.缓存过期时间设置

(一)失效时间设置的方法


有两种:


1.相对时间:多长时间,给出过期的时间长度


如:memcache.set(key,value,new Date(5000))设置为5秒过期


2.绝对时间:到期时间,给出过期的最后期限


如:memcache.set(key,value,new Date(System.currentTimeMillis()+5000))设置为5秒过期


当部署应用的服务器系统时间跟mc服务端的时间有差距时,使用绝对时间就有问题了,所以建议大家设置mc缓存过期时间时都用相对时间。看下面mc服务端源码就明了。


服务端的处理


时间处理源代码【memcached.c】如下:


#define REALTIME_MAXDELTA 60*60*24*30 //定义30天的秒数


static rel_time_t realtime(const time_t exptime) {

if (exptime == 0) return 0;


if (exptime > REALTIME_MAXDELTA) { //超过30天,是绝对时间


if (exptime <= process_started) //小于进程启动日期


return (rel_time_t)1; //


return (rel_time_t)(exptime - process_started); //返回进程启动之后的时间差


} else { //不超过30天,是相对时间


return (rel_time_t)(exptime + current_time); // exptime + (tvsec - process_started)


}


}


相对时间的返回的值是:服务器当前时间之后的exptime - process_started秒


绝对时间的返回的值是:服务器当前时间之后的(exptime -服务端当前时间) - process_started秒


可以看到,如果Client和Server时间不一致,根据经验mc服务端跑着跑着其服务端时间通常会比系统时间慢 当然偶尔也会快,如使用绝对时间会有问题,如mc时间比系统时间慢时对一些过期时间有严格要求的就不会按时过期了,如果快了那缓存几乎很快都过期,之前摄影部落某台mc就是出现这种情况,在访问量大些时由于一大部分缓存集体失效导致数据库负载高。


所以综上所述使用相对时间是比较安全可靠的做法。


(二)缓存时长的设置策略


缓存失效时间设置加个随机数来控制,把失效时间打散,尽可能避免访问高峰期缓存集体过期而雪崩,比如某个页面块的缓存时间设置4小时*随机数,即是这个页面块每份缓存过期时间不一样。


获取随机数的参考代码:


//随机算法把缓存过期时间打散


privatefloatgetRandomFloat(){

floatrandomFloat = 0;


while(true){

randomFloat =newDouble(Math.random()).floatValue();


if(randomFloat>0){

if(randomFloat<0.5){

randomFloat = randomFloat*2;


}


break;


}


}


returnrandomFloat;


}


五.一些重要的参数设置

首先保证同一应用各台服务器上的mc配置文件一致。


其他一些需要注意注意的参数:


memcached.failover=false


设置容错开关,设置为true,当前socket不可用时,程序会自动查找可用连接并返回,否则返回NULL。默认为true,最好设置为false,跟failback设置为true搭配使用,这样当某台mc宕机或其他问题时让该台的请求直接落到到数据库,当恢复后重新使用,这样就不影响整个mc集群的缓存key的重新分配,引发集群短期的动荡。


memcached.failback=true


设置连接失败恢复开关,设置为true,当宕机的服务器启动或中断的网络连接后,这个socket连接还可继续使用,否则将不再使用,默认是true,最好设置为true。


六.一些排查故障的方法

1.用命令查看分析mc的内存使用、命中率和mc时间情况


一般运维同事都有安装部署xmem和xmcstat命令。


如:xmem 192.168.123.123 11211


分析各台mc的Usage和HitRate的值,如果Usage值80%以上时有效期内缓存的置换率会比较高,所以缓存命中率相对会低些,这时留意加资源。


如发现某台HitRate的值比其他的要低,该台mc很有可能有问题。


xmcstat --i="192.168.123.123:11211"


重点留意MC时间和服务器系统时间这两个时间,如果mc时间比服务器时间快很多,如果我们设置缓存过期时间是绝对时间的,那肯定会降低缓存的命中率,所以设置缓存过期时间要用相对时间。


2.如发现一些mc值没过期的情况下灵异消失,一般是某台mc有问题或内存使用80%以上时被置换出去了。排查某台mc有问题可以telnet上去每台mc手动get某个key来看看,当然要先要知道该key是hash到那台mc。

————————————————

文/老猿,写代码写诗写职场的程序猿大叔,倾力原创简单实用的硬干货,转载此文请联系老猿。



相关文章
|
5月前
|
存储 NoSQL Redis
保障数据安全,提升性能:探秘Redis AOF持久化机制在在线购物网站的应用
保障数据安全,提升性能:探秘Redis AOF持久化机制在在线购物网站的应用
|
NoSQL 算法 网络安全
一份完整的阿里云 Redis 开发规范,值得收藏!
一份完整的阿里云 Redis 开发规范,值得收藏!
1876 0
|
2月前
|
存储 NoSQL Java
Redis助力高并发网站:在线用户统计不再是难题!
小米带你了解如何使用Redis高效统计网站的在线与并发用户数。通过维护用户的活跃时间,利用Redis有序集合(Sorted Set)特性,可实时更新在线用户列表并统计数量。具体实现包括记录用户上线时间、定期清理离线用户及统计特定时间窗口内的活跃用户数。这种方法适用于高并发场景,保证统计结果的实时性和准确性。跟着小米一起探索Redis的强大功能吧!
77 2
|
5月前
|
消息中间件 存储 缓存
|
5月前
|
存储 缓存 Dragonfly
微软开抢年收入上亿美元的 Redis 饭碗?开源性能遥遥领先的 Garnet:无需修改,Redis 客户端可直接接入
微软开源了高性能缓存系统Garnet,旨在挑战 Redis 和 Dragonfly。Garnet 基于 .NET8,提供高吞吐量、低延迟和跨平台支持。它支持 RESP 协议,允许大部分 Redis 客户端无缝迁移。Garnet 的特性包括多连接批量处理以提升扩展性和吞吐量,以及更好的延迟稳定性。适合于需要高性能缓存层来降低成本和提高应用性能的场景。Garnet 的集群模式允许动态键迁移和分片管理,且支持 TLS 和自定义扩展。其网络层设计减少了线程切换开销,存储层则具备丰富的 API 和事务支持。在基准测试中,Garnet 在吞吐量和延迟上优于 Redis 和 KeyDB,展现出优秀的扩展性。
464 0
微软开抢年收入上亿美元的 Redis 饭碗?开源性能遥遥领先的 Garnet:无需修改,Redis 客户端可直接接入
|
5月前
|
缓存 NoSQL 关系型数据库
MySQL与Redis的默契协作:解析数据一致性难题与解决方案
MySQL与Redis的默契协作:解析数据一致性难题与解决方案
305 0
MySQL与Redis的默契协作:解析数据一致性难题与解决方案
|
5月前
|
存储 缓存 NoSQL
内存淘金术:Redis 内存满了怎么办?
内存淘金术:Redis 内存满了怎么办?
72 1
|
5月前
|
存储 JSON NoSQL
Redis 内存优化神技,小内存保存大数据
Redis 内存优化神技,小内存保存大数据
82 0
|
存储 NoSQL 编译器
学习分享(第 2 期):从源码层面看 Redis 节省内存的设计
学习分享(第 2 期):从源码层面看 Redis 节省内存的设计
全面分析战!Redis持久化策略,这么一理顺,才知很简单
通常情况下redis的数据全部存储在内存中,数据库一旦故障发生重启数据会全部丢失,即使是在redis cluster或者redis sentinel模式下主从同步数据的恢复仍然需要一段时间。