Redis的删除策略,删除我是认真的

  1. 定时删除,每一个key都设置过期时间,每个key都用一个线程跟踪,当这个key过了过期时间,该线程就将这个key删除;但是当key的数量很大时,就会有很多线程,CPU的占用量会非常大
public class DeletePolicy1 {
	
	// 模拟redis
	private static Map<String,String> redis = new HashMap<>();
	
	public static void set(String key, String value, Long timeout) {
		redis.put(key, value);
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				long currentTimeMillis = System.currentTimeMillis() + timeout;
				while(true) {
					if(System.currentTimeMillis() > currentTimeMillis) {
						redis.remove(key);
					}
				}
				
			}
		}).start();
	}
	
	public static String get(String key) {
		return redis.get(key);
	}
	
	public static void main(String[] args) {
		set("young","xian",5000L);
		int i = 1;
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			String string = get("young");
			
			System.out.println("第" + i + "秒得到的值为:" + string);
			i++;
		}
	}
}
  1. 惰性删除,redis服务器不会主动删除数据,当访问这个key时,redis服务器会先判断这个key有没有过期,如果过期了则删除这个key,并且返回null。缺点是内存占用量大
public class DeletePolicy2 {
	
	// 模拟redis
	private static Map<String,String> redis = new HashMap<>();
	
	private static Map<String,Long> deleteMap = new HashMap<>();
	
	
	public static void set(String key, String value, Long timeout) {
		redis.put(key, value);
		long currentTimeMillis = System.currentTimeMillis() + timeout;
		deleteMap.put(key, currentTimeMillis);
	}
	
	public static String get(String key) {
		if(deleteMap.containsKey(key)) {
			if(System.currentTimeMillis() > deleteMap.get(key)) {
				redis.remove(key);
				deleteMap.remove(key);
				return null;
			}
		}
		
		return redis.get(key);
	}
	
	public static void main(String[] args) {
		set("young","xian",5000L);
		int i = 1;
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			String string = get("young");
			
			System.out.println("第" + i + "秒得到的值为:" + string);
			i++;
		}
	}
}
  1. 定期删除,redis服务器会开启一个线程定期去扫描过期的key,如果扫描到了,就将这个key删除。(可能一些key过期了,但是还是没有扫描到,那么用户依然还可以访问这个key。在内存和CPU上做了一个平衡,但是删除得不及时,实时性差)
public class DeletePolicy {
	
	// 模拟redis
	private static Map<String,String> redis = new HashMap<>();
	
	// 用于存储所有的key的有效时间
	private static Map<String,Long> dieNews = new HashMap<>();
	
	private static Object lock = new Object();
	
	static {
		new Thread(new Runnable() {
		// 只有一个线程,节约cpu的资源,但是若定期检查的时间太长,则会导致实时性差
			@Override
			public void run() {
				
				while(true) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					Set<String> deletes = new HashSet<>(); // 用于记录需要删除的消息的key
					if(dieNews.isEmpty()) {
						synchronized (lock) {
							try {
								System.out.println("不存在过期的key,休眠一会儿");
								lock.wait();
								System.out.println("检查线程启动...");
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					
					dieNews.forEach((k,v)->{
						if(System.currentTimeMillis() > dieNews.get(k)) {
							deletes.add(k); 
						}
					});
					for (String key : deletes) {
						dieNews.remove(key);
						redis.remove(key);
					}
				}
			}
		}).start();
	}
	
	public static void set(String key, String value,Long timeout) {
		redis.put(key, value);
		dieNews.put(key, System.currentTimeMillis() + timeout);
		synchronized (lock) {
			lock.notify();
		}
	}
	
	public static String get(String key) {
		return redis.get(key);
	}
	
	public static void main(String[] args) {
		set("young","xian",5000L);
		int i = 1;
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			String string = get("young");
			
			System.out.println("第" + i + "秒得到的值为:" + string);
			i++;
			if(i == 8) {
				set("young","muxian",5000L);
			}
		}
	}
	
}
  1. 惰性删除+定期删除
public class DeletePolicy3 {
	
	// 模拟redis
	private static Map<String,String> redis = new HashMap<>();
	
	// 用于存储所有的key的有效时间
	private static Map<String,Long> dieNews = new HashMap<>();
	
	private static Object lock = new Object();
	
	static {
		new Thread(new Runnable() {
			@Override
			public void run() {
				
				while(true) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					Set<String> deletes = new HashSet<>(); // 用于记录需要删除的消息的key
					if(dieNews.isEmpty()) {
						synchronized (lock) {
							try {
								System.out.println("不存在过期的key,休眠一会儿");
								lock.wait();
								System.out.println("检查线程启动...");
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					
					dieNews.forEach((k,v)->{
						if(System.currentTimeMillis() > dieNews.get(k)) {
							deletes.add(k); 
						}
					});
					for (String key : deletes) {
						dieNews.remove(key);
						redis.remove(key);
					}
				}
			}
		}).start();
	}
	
	public static void set(String key, String value,Long timeout) {
		redis.put(key, value);
		dieNews.put(key, System.currentTimeMillis() + timeout);
		synchronized (lock) {
			lock.notify();
		}
	}
	
	public static String get(String key) {
		// 加上惰性删除来保证过期删除的实时性
		if(dieNews.containsKey(key)) {
			Long time = dieNews.get(key);
			if(System.currentTimeMillis() > time) {
				dieNews.remove(key);
				redis.remove(key);
				return null;
			}
		}
		return redis.get(key);
	}
	
	public static void main(String[] args) {
		set("young","xian",5000L);
		int i = 1;
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			String string = get("young");
			
			System.out.println("第" + i + "秒得到的值为:" + string);
			i++;
			if(i == 8) {
				set("young","muxian",5000L);
			}
		}
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值