上善若水,夫唯不爭,故無尤

18676780050@163.com


  • Home

  • Tags

  • Categories

  • Archives

乱弹缓存

Posted on 2018-06-14 | In java基础

缓存崩溃

  1. 描述

    由于缓存层承载过多请求,有效的保护了存储层。但是因为缓存层由于某些原因整体不能提供服务,于是所有请求都会重新回源到存储层,存储层因调用量剧增,直接崩溃。

  2. 解决方法
    • 高可用(主备or主从架构)
    • 限流、降级

缓存穿透

  1. 描述

    缓存穿透将导致不存在的数据每次请求都要落到存储层查询,失去了保护存储层的意义。

  2. 解决方法
    • 空对象,缓存有意义的值。
    • 分散Key失效时间,缓存超时时间分散。

缓存热点

  1. 描述

    某些key是热点key,访问频率非常高。甚至服务启动就会访问频率极高。

  2. 解决方法
    • 提前预热。

缓存经验之谈

  1. 设计好的缓存数据模型,能简单模型就简单模型
  2. 能本地缓存的就本地缓存
  3. 尽量设置缓存的超时时间
  4. 尽量分散缓存的超时时间,加随机数,避免缓存穿透
  5. 要做缓存开关,流控,降级等措施,原则:不要因为缓存穿透、崩溃等问题,把整个系统搞崩了
  6. 热点数据尽量提前预热

缓存封装

  1. Cache get组件封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

/**
* Get value of specify key
*
* @param key K
* @param expireSeconds K expire seconds
* @param cacheLoader Sor loader
* @return Value
*/
public <V> V get(final String key, final int expireSeconds, TypeReference<V> clazz, CacheLoader<V> cacheLoader) {

// remote cache switch control
if (!cacheSwitch.isRemoteCacheEnabled()) {
return cacheLoader.load();
}

// load data from cache
String value = redisOperator.get(key);
if (null != value) {
logger.debug("Hit cache key:{},value:{}", key, value);
return CacheValueParser.parseObject(value, clazz);
}

// processing cache snow-slip
Lock lock = striped.get(key);
try {
lock.lock(); // lock

value = redisOperator.get(key);
if (null != value) {
logger.debug("Hit cache key:{},value:{}", key, value);
return CacheValueParser.parseObject(value, clazz);
}

// load data from SOR
V data = cacheLoader.load();

final String remoteVal;
final int expireSec;
if (null == data) { // processing cache breakdown
remoteVal = JSON.toJSONString(NULL_STRING);
expireSec = 0 == expireSeconds ? 0 : expireSeconds / 2 + 1;
} else {
remoteVal = JSON.toJSONString(data);
expireSec = expireSeconds;
}

// write cache( sync or async is a problem )
asyncCacheExecutor.submit(new Runnable() {
@Override
public void run() {
try {
redisOperator.put(key, remoteVal, expireSec);
} catch (Exception ex) { // log , send warning mail
logger.error("Write cache key:" + key + " fail .", ex);
}
}
});

return data;
} finally {
lock.unlock();
}
}
  1. 客户端调用
1
2
3
4
5
6
7
List<LocalDeviceFeaturesVo> value = simpleCache.get(CacheKeys.CONF_LOCAL_FEATURES, 60 * 60, new TypeReference<List<LocalDeviceFeaturesVo>>() {},
new CacheLoader<List<LocalDeviceFeaturesVo>>() {
@Override
public List<LocalDeviceFeaturesVo> load() {
return fdpDao.getLocalDeviceFeatures();
}
});

数据分析平台架构

Posted on 2018-06-14 | In 项目

架构图

Alt icon

流程图

Alt icon

dubbo常见问题

Posted on 2018-06-14 | In java基础

常见问题

  1. 什么是dubbo?
    1
    2
    3
    4
    5
    分布式服务治理(SOA)框架
    功能
    远程通信:NIO框架支持
    集群容错:多协议、软负载、failover、地址路由
    自动发现:注册中心

Alt dubbo-arch

  1. dubbo运行时,突然所有的zookeeper全部宕机,dubbo是否还会继续提供服务?

    1
    2
    3
    可以,dubbo启动成功后会在本地生成一个cache文件。
    注册中心集群节点对等,一半以上活着,集群就可以用。即使全挂掉,缓存文件还存在,就不会影响已有的业务调用。
    服务提供者集群节点对等,任何一台挂了,集群仍可用。所有提供者都挂了,消费者无法使用,无限重连等待服务提供者恢复。
  2. dubbo测试和生产共用一套zookeeer,怎么保证消费不冲突?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    过滤器(白名单),自己写 , 实现filter接口
    服务分组
    <!--服务-->
    <dubbo:service group="feedback" interface="com.xxx.IndexService" />
    <dubbo:service group="member" interface="com.xxx.IndexService" />
    <!--引用-->
    <dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" />
    <dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" />
    版本控制(多版本)
    <dubbo:service interface="com.foo.BarService" version="1.0.0" />
  3. dubbo连接注册中心和直连的区别?

    1
    2
    3
    4
    5
    开发、测试的时候,为了简单快速调试,绕过注册中心,直接指定服务提供者,点对点直连。
    如果是线上需求需要点对点,可在<dubbo:reference>中配置url指向提供者,将绕过注册中心,多个地址用分号隔开
    <dubbo:reference id="xxxService"interface="com.alibaba.xxx.XxxService"url="dubbo://localhost:20890"/>
    在JVM启动参数中加入-D参数映射服务地址
    java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
  4. dubbo如何实现软负载均衡?

    1
    2
    注册中心,动态的注册和发现服务,使服务的位置透明,注册中心返回服务提供者地址给消费者,如有变更,注册中心将推送变更数据给消费者。只充当目录服务。
    消费者通过注册中心,获取服务提供者地址列表,基于客户端的负载均衡算法,选一台服务提供者进行调用,调用失败,再选另一台。
  5. dubbo 负载均衡算法有哪些?

    1
    2
    3
    4
    RoundRobin LoadBalance (轮询算法)
    ConsistentHash LoadBalance(一致性Hash),相同的参数请求总是请求同一个提供者
    Random LoadBalance(随机)
    LeastActionLoadBalance(最少活跃)
  6. dubbo 安全机制如何解决?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。
    全局
    <dubbo:provider interface="" token="true">UUID生成随机令牌
    <dubbo:provider interface="" token="123456">固定token令牌,相当于密码。
    服务级别
    <dubbo:service interface=" " token="true">随机令牌
    <dubbo:service interface=" " token="123456">固定密码令牌
    协议级别
    <dubbo:protocol name="dubbo" token="true">
    <dubbo:protocol name="dubbo" token="123456">
    dubbo服务黑白名单,来控制服务所允许的调用方。
  7. zookeeer 是干什么的?

    1
    分布式应用程序协调服务,为分布式应用提供一致性服务的软件,包括:配置维护、域名服务、分布式同步、组服务等。

面试宝典

Posted on 2018-06-14 | In interview

Core Java

  1. 整数数组按绝对值排序

    1
    Arrays.sort(T[] a, Comparator<? super T> c)
  2. ConcurrentHashMap 的数据结构

    1
    Segment 分段锁,减少锁粒度
  3. 非阻塞IO和异步IO的区别

    1
    2


  4. 内存管理机制,如何回收过期对象,判断依据,内存溢出场景,如何排查等(P7需要很清楚的知道jvm的内存结构,回收过程,及虚拟机相关的回收算法及设计初衷)

    1
    2


  5. equals和==的区别

    1
    2
        基本类型都是用 == 做计较的,引用类型,== 判断的是地址是否一致.
    equals可以被重写,equals更偏向的是内存地址所持有的值是不是相同。
  6. final和finally

    1
    2
    3
    4
    5
    final修饰的是一个基本类型,就表示这个变量被赋予的值是不可变的,它是个常量。
    final修饰的是一个对象,就表示这个变量被赋予的引用是不可变的,这里这个不可改变的只是这个变量所保存的引用,并不是这个引用所指向的对象。
    在final修饰方法时,方法是不可以被该类的子类所继承的。
    在final修饰类时,被修饰的类是不可以被继承的。
    finally—再异常处理时提供,finally块来执行任何清除操作,是异常处理语句结构的一部分,表示总是执行。
  7. 常用的集合类有哪些?区别是什么?hashmap和hashtable的区别。哪些是线程安全的哪些不是?

    1
    2
    ArrayList、LinkedList、HashSet、TreeSet、ConcurrentHashMap、Collections、
    Lists、Arrays
  8. Object中的常见的方法

    1
    clone、hashcode、notify、wait、toString
  9. java中的异常体系,异常出现的情况如:ClassNotFound、空指针等

    1
    2
    3
    4
    Throwable,是所有异常或错误的超类,它有两个子类:Error和Exception,分别表示错误和异常。
    Error,一般是指java虚拟机相关的问题,如系统崩溃、虚拟机出错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常应用程序无法处理这些错误,因此应用程序不应该捕获Error对象,也无须在其throws子句中声明该方法抛出任何Error或其子类。
    RuntimeException,及其子类,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
    非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如 IOException、SQLException等以及用户自定义的Exception异常。必须捕获处理,或者直接跑出去,否则编译就会报错。
  10. JVM的内存模型是怎么样的?应用突然变得很慢,如何定位?

    1
    [https://www.jianshu.com/p/c9ac99b87d56](https://www.jianshu.com/p/c9ac99b87d56)
  11. Java的异常类层次结构

    1
    2


  12. 对JDK8的新特性有什么了解

    1
    流式编程、函数式编程
  13. Java的类加载器的机制((P7除了知道机制外,需要能够说明,利用classloader特性的一些场景应用 )

    1
    2


  14. 原子类的实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    1. 悲观的解决方案(阻塞同步)
    synchronized(this){
    num++;
    }

    2. 乐观的解决方案(非阻塞同步),compareAndSet
    /**
    * Atomically increments by one the current value.
    *
    * @return the updated value
    */
    public final int incrementAndGet() {
    for (;;) {
    int current = get();
    int next = current + 1;
    if (compareAndSet(current, next))
    return next;
    }
    }
  15. Error、Exception和RuntimeException的区别,作用又是什么

    1
    2


  16. IO和NIO本质不同在实际项目使用场景及如何使用

    1
    2


  17. sleep() 和 wait() 有什么区别

    1
    2
    3
    sleep没有释放锁,wait释放了锁,使得其他线程可以进入同步块。
    sleep可以在任何地方使用,而wait只能在同步块,同步控制方法内使用。
    sleep是Thread类上的静态方法,wait是Object类。

数据库&事务

  1. 什么样的场景会产生数据库死锁,如何解决

    1
    2


  2. SQL如何优化

    1
    2


  3. oracle或者mysql分页的实现思路

    1
    2


  4. SQL怎么判断字段是否为空

    1
    2


  5. 唯一索引能否插入空

    1
    2


  6. 数据库索引的算法原理

    1
    2


  7. 乐观锁,悲观锁

    1
    2


WEB (P6 必问)

  1. post/get的区别是什么

    1
    2
    3
    4
    POST比GET更安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
    GET参数通过URL传递,POST放在Request body中。
    GET请求只能进行url编码,而POST支持多种编码方式。
    因URL的长度限制,GET方式传输的数据大小有所限制,传送的数据量不超过2KB。
  2. cookie/session有什么区别

    1
    2
    3
    4
    5
    6
    cookie是一种在客户端记录用户信息的技术,因为http协议是无状态的,为了解决这个问题而产生了cookie。记录用户名等一些应用
    session是一种在服务端记录用户信息的技术,一般session用来在服务器端共享数据
    cookie是由服务器端创建发送回浏览器端的,并且每次请求服务器都会将cookie带过去,以便服务器知道该用户是哪一个。
    session的工作原理就是依靠cookie来做支撑,第一次使用request.getSession()时session被创建,
    并且会为该session创建一个独一无二的sessionid存放到cookie中,然后发送会浏览器端,浏览器端每次请求时,
    都会带着这个sessionid,服务器就会认识该sessionid,知道了sessionid就找得到哪个session。
  3. web集群中登录态如何共享

    1
    2
    nginx 一致性hash ip 策略 可以规避session共享问题。
    redis、memcache存储session,达到共享目的。
  4. xss、csrf等如何防范

    1
    2


  5. sql注入如何防范

    1
    2


  6. 浏览器缓存策略

    1
    2


  7. Ajax如何解决跨域问题

    1
    2


常用框架(P6 必问)

  1. spring AOP/IOC的理解,大致原理,类内部调用是否会触发aop的逻辑?为什么?

    1
    2


  2. Spring的事物传播属性 或 数据库的事物隔离级别,实现原理

    1
    2


  3. velocity如何避免引用空属性的报错

    1
    2


  4. spring的单例或者原型如何配置?还用过其他什么scope?

    1
    2


  5. log4j或者logback的日志记录文件在哪里?(开放式问题,怎么确定日志打到哪里了)

    1
    2


工具

  1. maven中如何排除包冲突

    1
    2


  2. svn合并代码怎么做

    1
    2


分布式

  1. 如何实现分布式锁

    1
    2


  2. 分布式Session如何实现

    1
    2


  3. 如何消除分布式事物

    1
    2


  4. MetaQ,Zookeeper 的原理和适用场景,(P7需要对业界的同类产品有一定的了解,知道各自的优缺点 )

    1
    2


  5. Redis 3.0的分布式集群架构,(P7需要对业界的同类产品有一定的了解,知道各自的优缺点 )

    1
    2


高并发

  1. 原子计数器AtomicInteger的技术实现

    1
    2


  2. volatile的内存模型

    1
    2


  3. 接口服务如何防止重复调用?

    1
    2
    可以幂等消费规避。
    redis存最近的序列化串,检验是否存在,存在则证明重复调用。
  4. 自己使用过多线程的场景是什么?线程安全如何保证?java的并发框架是否用过,线程池是否用过,RejectedExecutionHandler是否知道?

    1
    2


设计

  1. 对常用设计模式的了解,在项目中的实际应用

    1
    2


  2. 排序算法描述

    1
    2


  3. 在项目中是否采用分层的结构,是怎样划分的,各层之间采用了哪些相关技术

    1
    2


场景问题

  1. 对所做的系统的业务描述。能够描述清楚业务的核心逻辑和模型抽象,技术问题解决有正确思路(P6要求)。对其中的技术选型,技术方案有周全考虑,并且独立完成一个较复杂系统的设计和实现。(p7要求)
  2. 自己平时会学习些什么技术,学习程度如何
  3. 做项目过程中遇到什么技术难点;(p6和P7通过问题的技术难度、技术范围来区分)
  4. 怎么看待加班
  5. 线上问题分析处理是否有经验如何解决的

P7除了要抽查上面的技术问题外,建议选择询问以下问题:

  1. 描述一个独立设计的较复杂系统的设计思路和实现,能够清晰表达系统中的关键概念模型,行业内的对标产品及相关技术的熟悉程度;
  2. 对其中的技术方案有周全考虑,技术方案完整无明显漏洞;
  3. 实际项目设计中的延展性,对业务未来发展有一定考虑;
  4. 实际项目设计中如何保持优雅,方便运维和发展;
  5. 独立设计系统中的技术选型的比较, 熟悉的技术领域最佳实践 ;
  6. 开发设计中,采取了什么样的技术手段,提高开发的效率;
  7. 如果要设计一个搜索引擎,像google那样只有两个页面,要求性能最大化,web方面应该如何设计?(不需要考虑搜索的逻辑)
  8. 项目中用到点的技术细节挖掘;主要考察他对技术细节深度理解。如对MetaQ原理的理解,同类产品的比较。

算法和数据结构的描述;展示他对各数据结构的理解,不同场景下如何设计合理的数据

  1. 结构和算法,如何权衡时间与空间的取舍;
  2. trouble shooting 的最佳实践 。 这里根据不同的trouble情况会涉及到jvm内存,数据库 ,操作系统等相关的知识点 。
  3. 目前团队的瓶颈和困难分析 。
  4. 碰到过的最棘手技术问题或最复杂的业务场景的设计

总结

技术一面和二面的侧重点:
一面重点(从前到后)
技术能力,实际动手能力;
技术思路;
沟通表达能力;
学习能力;

项目(配置中心)总结

Posted on 2018-06-13 | In 项目

项目背景

  1. 功能描述

    • 音视频新特性(网络特性、本地特性)统一管理控制

      1
      2
      根据客户端(PC、Android、IOS)的特质(属性,比如CPU、GPU、摄像头 ...),
      动态下发适合客户端的音视频特性,达到用户体验效果最佳。
    • 客户端升级统一控制

      1
      该系统统一控制各个客户端是否升级,如果升级,那升级到的版本是多少? 是可选升级还是强制升级 ?
    • 服务器地址统一管理

      1
      从该系统统一下发给客户端,使得客户端轻量级,让各个客户端不再因为管理近50个服务器地址而烦恼。
    • 配置公共元数据统一管理

      1
      字典,错误码 ...
  2. 特点

    • 必须保证高可靠

      1
      该系统是客户端直接对接的第一个后台应用,该系统不可用,则公司整个产品不可用; 系统可水平扩展。
    • 并发能力有要求

      1
      该系统的并发代表公司产品的最大并发。
    • 性能要求较高

      1
      能快速的处理客户端获取特性、地址、升级的响应。
    • 安全性要求

      1
      必须对该系统提供安全性措施,避免恶意攻击导致系统崩溃。

技术实现

  1. 技术栈

    1
    Spring + SpringMVC + Mybatis + MQ + MySQL + Canal + Redis + Dubbo + Restful API
  2. 技术细节

    • 高可用设计

      1
      2
      3
      同类型的服务(Web、dubbo)无状态、对等,部署2套或2套以上。
      可横向扩展、动态负载均衡,负载策略:轮询。
      技术手段:nginx + zookeeper。
    • 接口隔离

      1
      2
      不同的接口相互隔离,互不影响。
      技术手段:业务线程池 + Servlet 3.0。
    • 流控设计

      1
      2
      后台服务,底线是,即使穿透安全攻击,也不至于使服务宕机。
      技术手段:Guava RateLimiter ,令牌桶。
    • 缓存设计

      1
      2
      3
      4
      组件封装对数据库和缓存操作。简化客户端调用,客户端只管get key调用,不管 set。
      缓存全局开关,避免因缓存bug或不可用,导致整个服务不可用,运维手段后路。
      技术手段:Canal 实现数据库和缓存一致性。组件封装简化客户端操作,隐藏对数据源和缓存操作的细节。
      zookeeper客户端代码编写,实现分布式控制缓存开关。
    • 安全设计

      1
      2
      关键字段带时间戳接口签名
      appkey 授权合法性校验

数据流设计

Alt conf-workflow

接口安全性流程图

1
接口签名 + appkey授权合法性校验

Alt conf-sign

乱弹性能调优

Posted on 2018-06-13 | In java基础

调优思路

  1. 了解当前的现象

    有点赤脚医生问诊的意思

  2. 是否能重现

    能重现的问题,定位难度都不大,至少可以 debug 。暂时不能重现,让测试想办法重现。

  3. 了解当前资源的使用情况

    CPU、内存、磁盘、IO、硬盘 …

  4. 想办法找到性能瓶颈点

    a. 日志分析
    b. 工具分析(jstack,jmap …),产看调用栈,对象的使用情况,有没有死锁,锁住的资源有哪些?
    c. 工具慢查询查看(durid 数据源工具)

  5. 针对性能瓶颈点进行调优

调优手段

  1. 能缓存的缓存,能本地缓存就尽量用本地缓存
  2. 能异步的就异步
  3. 注重日志打印质量,减少垃圾日志打印

调优常见场景

  1. 响应报文太大,可能会造成响应时间慢,网络IO占用高。可以考虑数据压缩手段。
  2. 业务操作中,同步转异步,异步转同步,合并结果
  3. 通过设计减少RPC调用、数据库操作次数

HashMap

Posted on 2018-06-13 | In java基础

HashMap

  1. Key/Value 结构
  2. 线程不安全
  3. 一般Key用String类型

    String类为final,hashcode()计算是根据字符数组的每个元素,能保证同一个String会得到同一个hashcode。

  4. 数据结构

    1.7之前,数组(Entry)+ 链表

    Entry,数组,地址连续,大小固定,查询快。包含key、value、hash、next等数据。
    链表,为了节省空间,链表在内存中存储地址不连续,可以更好的利用内存空间。
    

    1.8,数组(Entry)+ 链表 + 红黑树

    当链表长度 > 8 , 链表转为红黑树 ,加快检索速度。
    
  5. 扩容机制

    负载因子(loadFactor)默认 0.75
    负载临界值(threshold)= loadFactor * loadFactor。
    capacity 容量大小 , 2的n次方 ,左移运算。
    put元素是,size >= threshold ,调用resize()方法,扩容,2倍。

  6. ConcurrentHashMap

    解决HashTable 和 Collections.synchronizedMap() 效率低下的问题

    1.7之前,使用分段锁,加锁基于segment(段)粒度

    static class Segment<K,V> extends ReentrantLock implements Serializable 
    

    Alt concurrenthashmap

    1.8,底层使用了Node数组+链表+红黑树数据结构,用synchronized的关键字

Hexo 入门

Posted on 2018-06-12

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Alt icon

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

18676780050@163.com

18676780050@163.com

8 posts
3 categories
6 tags
© 2018 18676780050@163.com