聊聊 Redis 使用场景
缓存
会话缓存
时效性
访问频率
计数器
社交列表
记录用户判定信息
交集、并集和差集
热门列表与排行榜
最新动态
消息队列
Redis 内存淘汰机制
Redis 内存淘汰指的是用户存储的一些键被可以被 Redis 主动地从实例中删除,从而产生读 miss 的情况,那么 Redis 为什么要有这种功能?这就是我们需要探究的设计初衷。Redis 最常见的两种应用场景为缓存和持久存储,首先要明确的一个问题是内存淘汰策略更适合于那种场景?是持久存储还是缓存?
假设我们有一个 Redis 服务器,服务器物理内存大小为 1G 的,我们需要存在 Redis 中的数据量很小,这看起来似乎足够用很长时间了,随着业务量的增长,我们放在 Redis 里面的数据越来越多了,数据量大小似乎超过了 1G,但是应用还可以正常运行,这是因为操作系统的可见内存并不受物理内存限制,而是虚拟内存,物理内存不够用没关系,操作系统会从硬盘上划出一片空间用于构建虚拟内存,比如32位的操作系统的可见内存大小为 2^32,而用户空间的可见内存要小于 2^32 很多,大概是 3G 左右。好了,我们庆幸操作系统为我们做了这些,但是我们需要知道这背后的代价是不菲的,不合理的使用内存有可能发生频繁的 swap,频繁 swap 的代价是惨痛的。所以回过头来看,作为有追求的程序员,我们还是要 ...
Redis 内部结构
Redis 内部使用一个 redisObject 对象来表示所有的 key 和 value。
type :代表一个 value 对象具体是何种数据类型。
encoding :是不同数据类型在 redis 内部的存储方式,比如:type=string 代表 value 存储的是一个普通字符串,那么对应的 encoding 可以是 raw 或者是 int,如果是 int 则代表实际 redis 内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:”123” “456”这样的字符串。
vm 字段:只有打开了 Redis 的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。 Redis 使用 redisObject 来表示所有的 key/value 数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给 Redis 不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用。
Redis 有哪些类型
在 Redis 中有五种数据类型
String:字符串
Hash:字典
List:列表
Set:集合
Sorted Set:有序集合
聊聊 ElasticSearch 使用场景
全文搜索,这个是用的最多的。加上分词插件、拼音插件什么的可以做成强大的全文搜索引擎。
数据库,挺奇葩的用法,因为 ES 存数相同数据,更费空间,不过确实不错,因为他的强大统计分析汇总能力,再加上分布式 P2P 扩展能力,现在硬件又那么便宜,所以就有人拿来当数据库了。
在线统计分析引擎,日志系统,LogStash,不用解释了吧; 可以实时动态分析数据,很是爽。
倒排索引
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。有两种不同的反向索引形式:
一条记录的水平反向索引(或者反向档案索引)包含每个引用单词的文档的列表。
一个单词的水平反向索引(或者完全反向索引)又包含每个单词在一个文档中的位置。
JDK8 新特性
Java 基础 - JDK8 新特性概述以下列出两点重要特性:
Lambda表达式(匿名函数)
Stream多线程并行数据处理(重要)
新特性
接口的默认方法只需要使用default关键字即可,这个特性又叫扩展方法
Lambda表达式
Functional接口函数式接口是指仅仅只包含一个抽象方法的接口,每一个该类型的Lambda表达式都会被匹配到这个抽象方法。你只需要给你的接口添加@FunctionalInterface注解。
使用::双冒号关键字来传递方法(静态方法和非静态方法)
Predicate接口和Lambda表达式
Function接口
Function有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法。
compose方法表示在某个方法之前执行
andThen方法表示在某个方法之后执行
注意:compose和andThen方法调用之后都会把对象自己本身返回,这可以 方便链式编程
Supplier接口,返回一个任意泛型的值,和Function接口不同的是该接口 没有任何参数
Consumer接口,接收一个任意泛型的值,和Function接口不同的是该 ...
双亲委派模型
类加载器加载类的开放性类加载器(ClassLoader) 是Java语言的一项创新,也是Java语言流行的一个重要原因,在类加载的第一阶段“加载”过程中需要通过一个类的全限定名来回去定义此类的二进制字节流,完成这个动作的代码块就是 类加载器,这一动作是放在Java虚拟机外部去实现的,以便让应用程序自己去决定如何获取所需的类。
虚拟机规范并没有指明二进制字节流要从一个Class文件获取,或者说根本没有指明从哪里获取、怎样获取。这种开放使得Java在很多领域得到充分运用,例如:
从ZIP包中读取,这很常见,成为JAR,EAR,WAR格式的基础
从网络中获取,最典型的运用就是Applet
运用时计算生成,最典型的是动态代理技术,在java.lang.reflect.Proxy中,就是用了ProxyGrenerator.generateProxyClass 来为特定接口生成形式为“*$Proxy”的代理类的二进制字节流
有其它文件生成,最典型的JSP应用,由JSP文件生成对应的Class类
类加载器与类的唯一性类加载器虽然只用于实现类的加载动作,但是对于任意一个类,都需要由它的类加载器和这 ...
死信、延迟、重试队列
死信队列DLQ(Deal Letter Queue),死信队列。当一个消息在队列中变成死信之后,他能被重新发送到 DLQ 中,与 DLQ 绑定到队列就是死信队列。
什么情况下需要死信队列
消息被拒绝
消息过期
队列达到最大长度
生产者生产一条消息,存储到普通队列中;设置队列的过期时间为 10 秒,在 10 秒内没有消费者消费消息,那么判定消息过期;此时如果设置了死信队列,过期消息被丢给死信队列交换机,然后被存储在死信队列中。
延迟队列顾名思义就是延迟执行消息,比如我们可以增加一个队列并设置其超时时间为 10 秒并且不设置任何消费者,等到消息超时,我们可以将消息放入死信队列,让消费者监听这个死信队列就达到了延迟队列的效果。
重试队列重试的消息在延迟的某个时间点(业务可设置)后,再次投递给消费者。而如果一直这样重复消费都持续失败到一定次数,就会投递到死信队列,最后需要进行人工干预。
Zookeeper-假死闹裂
该问题就是服务集群因为网络震荡导致的多主多从问题,解决方案就是设置服务切换的超时时间,但也同时会导致无法达到高可用的要求。
注:该问题没什么卵用,就是为了告诉大家有 “假死脑裂” 这个词,避免面试时尴尬 ╮( ̄▽ ̄)╭