g# elasticsearch
搜索流程
- client发送请求到任意一个node,这node成为协调节点
- 协调节点将搜索请求转发所有的shard对应的primary shard或replica shard
- 每个shard将自己搜索结果的doc id返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果
- 最后由协调节点根据doc id,去各个节点拉取实际的document数据,返回给client
写数据
- 客户端选择一个node发送请求,这个node成为协调节点
- 协调节点对document进行路由,请请求转发对应的node(primary shard)
- 实际的node上的primary shard处理请求,然后将数据同步到replic node
- 协调节点发现primary和所有replica node都搞定之后,就返回响应结果给客户端
es原理图
- es是准实时的,数据写入1s后可搜索到
- es每隔5s写入日志文件,可能丢失5s数据
es在十亿级别的数据如何提高查询效率
- es的jvm不要分配太大,留足够的内存给filesystem cache,如果查询数据都在filesystem cache性能就能提高很多(如每次查询5~10s,放在filesystem cache就是50ms)。
- 只存要检索的数据到es中,使数据少,都能放到filesystem cache中。其它展示数据可以放到hbase中。
- 数据预热,做一个专门的缓存预热子系统,对热数据每隔一段时间访问一下,让数据进入filesystem cache中。这样别人访问,性能一定会好很多
- 冷热分离,将冷数据放到另一个索引中。这样可确保热数据在被预热之后,尽量都让他们在filesystem os cache里,不被冷数据刷掉
- 尽量不要让es做复杂的关联查询,尽量在document设计时,写入的时候就能完成
- es的分页越翻到后面越慢。解决方案:
- 不允许深度分页
- 使用scroll api或search_after,缺点是不能随意跳到任何一页
Redis
redis过期策略:定期删除+惰性删除
key过期不是立刻删除的,如果此时大量过期key堆积在内存里,导致redis内存耗尽,则走内存淘汰机制
redis内存淘汰默认是最近最少使用算法
缓存雪崩解决方案
产生原因redis挂了或热点数据大量同时过期,如果是后者需要通过让热点数据在不同时间段失效来解决。
事前:redis cluster保证高可用
事中:本地ehcache缓存+hystrix限流和降级,避免mysql被打死
事后:redis持久化,一旦重启能从磁盘上加载数据
缓存穿透
缓存穿透容易被人利用恶意攻击,黑客针对不存在的数据发起大量请求,导致请求都打在了mysql中,可写一个空值到缓存然后设置一个过期时间,可以让下次同一个key查询请求直接走缓存
缓存击穿
某个key访问非常频繁,当key失效时,大量请求走mysql。可基于redis或zookeeper实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求能直接走缓存。
MySQL
如何解决主从同步延时与数据丢失问题
如果从库还没有把主库数据同步过来,主库宕机了就会产生数据丢失,可通过半同步复制解决,即让主库接收到至少一个从库的ack之后才会认为写操作成功
主从数据延时问题,解决办法有:
- 并行复制,从库开启多个线程并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库级别的并行
- 分库,将一个主库拆分为多个主库,每个主库的写并发就减少了几倍,此时主从延迟可以忽略不计
- 写代码的同学,要注意,插入数据时立马查询可能查不到,如果写代码逻辑是先插入一条数据,再把它查出来,然后更新这条数据。可能会因无法立即查询出来而更新失败
- 如果确实要插入数据要立马能查询到,可对这个查询设置直连主库。不过,此时读写分离就失去意义了
如何设计一个高并发系统
可从以下6点讨论
- 系统拆分
- 缓存
- MQ
- 分表分库
- 读写分离
- elasticsearch
Dubbo
dubbo默认走dubbo协议,默认基于hessian作为序列化协议,除此之外还支持rmi协议、hessian协议、http协议、webservice协议