1)通用性:全量属性更好。数据库
2)占用空间:部分属性更好。数组
3)代码维护:表面上全量属性更好。缓存
定义:大量请求不命中。bash
1)业务代码自身问题。服务器
2)恶意攻击、爬虫等等。网络
1)业务的相应时间。函数
2)业务自己问题。性能
3)相关指标:总调用数、缓存层命中数、存储层命中数。优化
1)缓存空对象。ui
一、须要更多的键。
二、缓存层和存储层数据“短时间”不一致。
2)布隆过滤器拦截。
所谓的布隆过滤器是一个很长的二进制向量,存放0或者1。通过几回hash计算,获得5,9,2三个数字,那么存放结果以下图所示:
仅仅从布隆过滤器自己而言,根本没有存放完整的数据,只是运用一系列随机映射函数计算出位置,而后填充二进制向量。所以,可使用固定的计算方式 ,来判断一个数据是否存在。可是因为相似哈希冲突的缘由存在误判的可能性,也就是说,布隆过滤器只能判断数据不存在,而不能判断数据必定存在。
public class RedisTest {
static final int expectedInsertions = 100;//要插入多少数据
static final double fpp = 0.01;//指望的误判率
//bit数组长度
private static long numBits;
//hash函数数量
private static int numHashFunctions;
static {
numBits = optimalNumOfBits(expectedInsertions, fpp);
numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, numBits);
}
public static void main(String[] args) {
Jedis jedis = new Jedis("你的ip", 6379);
for (int i = 0; i < 100; i++) {
long[] indexs = getIndexs(String.valueOf(i));
for (long index : indexs) {
jedis.setbit("codebear:bloom", index, true);
}
}
for (int i = 0; i < 100; i++) {
long[] indexs = getIndexs(String.valueOf(i));
for (long index : indexs) {
Boolean isContain = jedis.getbit("codebear:bloom", index);
if (!isContain) {
System.out.println(i + "确定没有重复");
}
}
System.out.println(i + "可能重复");
}
}
/**
* 根据key获取bitmap下标
*/
private static long[] getIndexs(String key) {
long hash1 = hash(key);
long hash2 = hash1 >>> 16;
long[] result = new long[numHashFunctions];
for (int i = 0; i < numHashFunctions; i++) {
long combinedHash = hash1 + i * hash2;
if (combinedHash < 0) {
combinedHash = -combinedHash;
}
result[i] = combinedHash % numBits;
}
return result;
}
private static long hash(String key) {
Charset charset = Charset.forName("UTF-8");
return Hashing.murmur3_128().hashObject(key, Funnels.stringFunnel(charset)).asLong();
}
//计算hash函数个数
private static int optimalNumOfHashFunctions(long n, long m) {
return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
}
//计算bit数组长度
private static long optimalNumOfBits(long n, double p) {
if (p == 0) {
p = Double.MIN_VALUE;
}
return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
}
}
复制代码
定义:某一个时间段,缓存集中过时失效。
1)集中设置统一的过时时间,到了必定时间时,便所有怼到数据库上了。
2)服务器某个结点宕机或断网。
1)使用随机因子尽量分散过时时间。
2)使用集群高可用化。
问题描述:2010年,Facebook有了3000个Memcache节点,发现增长机器性能没能提高,反而降低。
1)更多的机器!=更高的性能。
2)批量接口需求(mget, mset等)。
3)数据增加与水平扩展等。
1)命令自己优化:例如慢查询keys、hgetall bigkey。
2)减小网络通讯次数。
3)下降接入成本:例如客户端长链接/链接池、NIO等。
问题描述:热点key+较长的重建时间
可能会存在多个线程共同执行查询数据源与重建缓存的操做。
1)减小重建缓存的次数。
2)数据尽量一致。
3)减小潜在风险。
在重建时开始加锁,完成重建后进行解锁。
代码:
优势:
1)思路简单。
2)保证一致性。
缺点:
1)代码复杂度增长。
2)存在死锁的风险。
1)缓存层面:没有设置过时时间。
2)功能层面:为每一个value添加逻辑过时时间,但发现超过逻辑过时后,会使用单独的线程去构建缓存。
代码:
优势:
基本杜绝热点key重建问题。
缺点:
1)不保证一致性。
2)逻辑过时时间增长维护成本和内存成本。