Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.
目录
概述
网络爬虫的是一个非常常见的需求。
需求:
200、Redis和 memecache 有什么区别?
1、Redis相比memecache,拥有更多的数据结构和支持更丰富的数据操作。
(1)Redis支持key-value,常用的数据类型主要有String、Hash、List、Set、Sorted Set。
(2)memecache只支持key-value。
2、内存使用率对比,Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memecache。
3、性能对比:Redis只使用单核,memecache使用多核。
4、Redis支持磁盘持久化,memecache不支持。
Redis可以将一些很久没用到的value通过swap方法交换到磁盘。
5、Redis支持分布式集群,memecache不支持。
201、Redis支持的 java 客户端都有哪些?
Redisson、Jedis、lettuce 等等,官方推荐使用 Redisson。
202、jedis 和 redisson 有哪些区别?
Jedis 和 Redisson 都是Java中对Redis操作的封装。Jedis 只是简单的封装了 Redis 的API库,可以看作是Redis客户端,它的方法和Redis 的命令很类似。Redisson 不仅封装了 redis ,还封装了对更多数据结构的支持,以及锁等功能,相比于Jedis 更加大。但Jedis相比于Redisson 更原生一些,更灵活。
203、什么是缓存穿透?怎么解决?
1、缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对用的value,就应该去后端系统查找(比如DB数据库)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert之后清理缓存。
对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。
3、缓存雪崩
当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。
4、如何解决?
对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。
当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其它线程等待;
做二级缓存;
不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀;
204、怎么保证缓存和数据库数据的一致性?
1、淘汰缓存
数据如果为较为复杂的数据时,进行缓存的更新操作就会变得异常复杂,因此一般推荐选择淘汰缓存,而不是更新缓存。
205、Redis,什么是缓存穿透?怎么解决?
2、选择先淘汰缓存,再更新数据库
假如先更新数据库,再淘汰缓存,如果淘汰缓存失败,那么后面的请求都会得到脏数据,直至缓存过期。
假如先淘汰缓存再更新数据库,如果更新数据库失败,只会产生一次缓存穿透,相比较而言,后者对业务则没有本质上的影响。
不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀;
这么做,可以将1秒内所造成的缓存脏数据,再次删除。这个时间设定可根据俄业务场景进行一个调节。
4、数据库读写分离的场景
依旧采用延时双删策略解决此问题。
206、Redis怎么实现分布式锁?
redis命令:set users 10 nx ex 12 原子性命令
//使用uuid,解决锁释放的问题
@GetMapping
public void testLock() throws InterruptedException {
String uuid = UUID.randomUUID().toString();
Boolean b_lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);
if(b_lock){
Object value = redisTemplate.opsForValue().get("num");
if(StringUtils.isEmpty(value)){
return;
}
int num = Integer.parseInt(value + "");
redisTemplate.opsForValue().set("num",++num);
Object lockUUID = redisTemplate.opsForValue().get("lock");
if(uuid.equals(lockUUID.toString())){
redisTemplate.delete("lock");
}
}else{
Thread.sleep(100);
testLock();
}
}
备注:可以通过lua脚本,保证分布式锁的原子性。
207、Redis分布式锁有什么缺陷?
Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。
Redis容易产生的几个问题:
锁未被释放
B锁被A锁释放了
数据库事务超时
锁过期了,业务还没执行完
Redis主从复制的问题
208、Redis如何做内存优化?
Redis如何做内存优化?
1、缩短键值的长度
缩短值的长度才是关键,如果值是一个大的业务对象,可以将对象序列化成二进制数组;
2.首先应该在业务上进行精简,去掉不必要的属性,避免存储一些没用的数据;
3.其次是序列化的工具选择上,应该选择更高效的序列化工具来降低字节数组大小;
4以JAVA为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如: protostuff,kryo等
2、共享对象池
对象共享池指Redis内部维护[0-9999]的整数对象池。
创建大量的整数类型redisObject存在内存开销,每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。
除了整数值对象,其他类型如list,hash,set,zset内部元素也可以使用整数对象池。因此开发中在满足需求的前提下,尽量使用整数对象以节省内存。
所以Redis内存维护一个[0-9999]的整数对象池,用于节约内存。
3、字符串优化
4、编码优化
5、控制key的数量
参考资料和推荐阅读
- https://blog.csdn.net/guorui_java/article/details/119299329
欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~