java面试(十六)
1、redis中的网络IO有了解过吗,它是单线程的还是多线程的,为什么要用单线程。
了解过。redis中是IO多路复用的。采用了select、poll、epoll方法,前两个方法是线程不安全的。select的官方文档指出:一个Sock(I/O Stream)插入到select中,如果其他的线程发现这个Sock是不可用的,要回收这个Sock,select方法是不支持的。如果强行关闭它,其结果是不确定的。
epoll是线程安全的,它不仅会通知Sock里是有数据的,而且会告知哪个Sock里有。而select只会通知Sock里有数据,而不会返回具体的Sock,需要自己一个一个的去找,如果有成千上万个Sock,那将是非常耗时的。
Redis是单线程的。原因如下:
- Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。
- 代码更清晰,处理逻辑更简单。
- 不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
- 不存在多进程或者多线程导致的切换而消耗CPU。
2、如果你要对班里的学生根据分数进行排名,你觉得用redis里的哪个数据结构比较好。zset的底层是用什么数据结构实现的。
zset。
有序集合对象的编码可以是ziplist
或者skiplist
。同时满足以下条件时使用ziplist编码:
- 元素数量小于128个
- 所有member的长度都小于64字节
以上两个条件的上限值可通过zset-max-ziplist-entries和zset-max-ziplist-value来修改。
ziplist
编码的有序集合使用紧挨在一起的压缩列表节点来保存,第一个节点保存member,第二个保存score。ziplist内的集合元素按score从小到大排序,score较小的排在表头位置。
skiplist
编码的有序集合底层是一个命名为zset
的结构体,而一个zset结构同时包含一个字典和一个跳跃表。跳跃表按score从小到大保存所有集合元素。而字典则保存着从member到score的映射,这样就可以用O(1)的复杂度来查找member对应的score值。虽然同时使用两种结构,但它们会通过指针来共享相同元素的member和score,因此不会浪费额外的内存。
求职面试题&解析