使用MemCached作为缓存系统时,常遇到Key Value的大小长度超出限制的问题。Key要求小于250个字符,Value要求小于1MB。按照MemCached官方的说法,出于缓存的效率性能考虑,如果超过了限制一般需要考虑是否系统的设计出了问题。
Key长度超过250字符时,首先应该想到的是能够尽量缩短key的长度,比如将子Key字符串组合改为位运算整合后的32位整数。最后实在没办法可以尝试Hash函数缩短key。但由于Hash函数是多对一的映射,免不了会出现碰撞的问题。不管是采用CRC32算法还是MD5甚至SHA算法,只是碰撞概率大小的问题。
为解决Hash函数的碰撞问题,可以将原始Key加Value包装为新的Value存入MemCached。
class CacheWrapper {
String originalKey = null;
String value;
}
- 存入缓存时,如果original key长度没有超过250,CacheWrapper中的字段origianlKey不设值,直接使用(originalKey, CacheWrapper)存入MemCached。如果长度超过250,设置CacheWrapper中的字段origianlKey,使用(Hash(originalKey), CacheWrapper)存入MemCached。
- 从缓存中取数据时,如果命中并且original key长度没有超过250, 直接从缓存对象CacheWrapper中取值就可。如果original key 长度超过250,这时需要使用Hash(originalKey)从缓存中获取CacheWrapper对象。如果命中,还需要比较CacheWrapper中的originalKey是否为预期值。如果original key为预期值说明没有出现Hash碰撞,真实的命中了缓存,如果不为预期值,说明该次缓存没有命中。
该方法使用了附加的originalkey字段存入缓存,取缓存时使用double check检查是否存在Hash碰撞。可以看由于Hash碰撞,会出现取到无效的缓存数据的可能,但考虑到一般的Hash函数的碰撞概率还是比较低的,所以该情况的还是比较难出现。