ARTS | week 16

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mike_learns_to_rock/article/details/89181010

Algorithm

https://leetcode.com/problems/jump-game/
jump game:判断是否可以跳跃到最后

  • 解法1: DFS,会超时;用贪心法加快收敛速度
  • 解法2: BFS,也需要贪心加快收敛
  • 解法3: 动态规划,Bottom-up
class Solution {  
    public boolean canJump(int[] nums) {
        boolean[] top = new boolean[nums.length];
        int last = nums.length - 1;
        for (int i = nums.length - 1; i >= 0; i--) {
            if (nums[i] >= last - i) {
                top[i] = true;
                last = i;
            }
        }
        return top[0];
    }
}
  • 解法4:动态规划,Top-down,就是把dfs的中间状态存储下来
enum Index {
    GOOD, BAD, UNKNOWN
}
class Solution {  
    Index[] memo;
    
    private boolean dfs(int p, int[] nums) {
        if (memo[p] != Index.UNKNOWN) {
            return  memo[p] == Index.GOOD ? true : false;
        }
        
        for (int i = p + 1; i <= p + nums[p]; i++) {
            if (dfs(i, nums)) {
                memo[i] = Index.GOOD;
                return true;
            }
        }
        
        memo[p] = Index.BAD;
        return false;
    }
    
      public boolean canJump(int[] nums) {
        memo = new Index[nums.length];
        for (int i = 0; i < memo.length; i++) {
            memo[i] = Index.UNKNOWN;
        }
        memo[memo.length - 1] = Index.GOOD;
        return dfs(0, nums);
    }
}

https://leetcode.com/problems/jump-game-ii/
jump game 2 :找到最小的跳跃步数

  • 解法是BFS,用贪心算法来加快收敛速度
class Solution {
   public int jump(int[] nums) {
        if (nums.length == 1) {
            return 0;
        }
        Queue<Integer> queue = new LinkedList<>();
        boolean[] visit = new boolean[nums.length];
        int step = 1;
        queue.add(0);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int cur = ((LinkedList<Integer>) queue).pop();
                if (cur + nums[cur] >= nums.length - 1) {
                    return step;
                }
                int maxJ = 0;
                int maxDistance = 0;
                for (int j = 1; j <= nums[cur]; j++) {
                    int distance = nums[cur + j] + cur + j;
                    if (distance > maxDistance) {
                        maxDistance = distance;
                        maxJ = j;
                    }
                }
                if (!visit[cur + maxJ]) {
                    visit[cur + maxJ] = true;
                    queue.add(cur + maxJ);
                }
            }
            step++;
        }
        return -1;
    }
}

Review

Design a key-value cache to save the results of the most recent web server queries

  1. 明确用户场景和约束

场景

  • 用户发送一条search请求,缓存hit
  • 用户发送一条search请求,缓存miss
  • 缓存服务高可用

约束

  • 流量不均匀,热点请求需要缓存,
  • 缓存空间有限,how/when 更新缓存
  • 低时延
  • 1000万用户,100亿请求/月

存储评估

  • 一条key + value = ?(270B)
  • 一个月数据量最多2.7TB(100亿不同的请求),缓存肯定存储不下,需要淘汰
  • 服务qps 4000
  1. 粗设计
  • 客户端 - 服务端(反向代理)- 查询api - <倒排索引服务,文档服务> - 内存缓存
  1. 设计核心组件
    缓存
  • [HOW] LRU淘汰策略,那么参照https://leetcode.com/problems/lru-cache/ 双端链表 + 哈希表
  • [WHEN] 何时更新:页内容变更/页删除以及新页添加/页排名变化
  1. 扩展系统

Tips

  • 需求背景是一个任务下包含上万个子任务,子任务都是网络IO耗时较长的任务,客户端需要等待较长时间;java使用CloseableHttpAsyncClient时,因为任务数量远大于任务处理能力,导致很多request队列时间过长,造成header中的token过期;
  • 暂时使用同步client解决的,真正消费的时候才去计算token;后面需要研究下CloseableHttpAsyncClient的玩法儿。感觉应该有解法;
  • 或者把任务数量分摊到多个节点上,后面需要重新优化下架构了。

share

java虚拟机内存分配与回收策略

  • 对象优先在Eden分配,Eden空间不足时,发起minor GC
  • 大对象直接进入老年代,防止在 Eden 和 Survivor 之间的大量内存复制,-XX:PretenureSizeThreshold
  • 长期存活的对象进入老年代,经过多次minor GC依然存活的对象,会进入老年代,-XX:MaxTenuringThreshold
  • 动态对象年龄判定,虚拟机不会傻傻得以MaxTenuringThreshold为标准处理昌吉存活对象,会根据Survivor中的情况,重新定义年龄段
  • 空间分配担保,就是为了确保minor GC是安全的,就是老年代担保自己可以装下新生代GC的对象;如果多维度考察,仍然失败,则full gc

fullGC的条件

  • 老年代空间不足,大对象进入老年代

    1. 为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。
    2. -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代
    3. -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间
  • 空间分配担保失败

  • JDK 1.7 及以前的永久代空间不足

猜你喜欢

转载自blog.csdn.net/mike_learns_to_rock/article/details/89181010