# Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

## redis淘汰策略复习

发表于 2021-08-01 分类于 redis 阅读次数： Disqus：

前面复习了 redis 的过期策略，这里再复习下淘汰策略，淘汰跟过期的区别有时候会被混淆了，过期主要针对那些设置了过期时间的 key，应该说是一种逻辑策略，是主动的还是被动的加定时的，两种有各自的取舍，而淘汰也可以看成是一种保持系统稳定的策略，因为如果内存满了，不采取任何策略处理，那大概率会导致系统故障，之前其实主要从源码角度分析过redis 的 LRU 和 LFU，但这个是偏底层的实现，抠得比较细，那么具体的系统层面的配置是有哪些策略，来看下 redis labs 的介绍

Policy | Description
--- | ---
noeviction 不逐出 | Returns an error if the memory limit has been reached when trying to insert more data，插入更多数据时，如果内存达到上限了，返回错误
allkeys-lru 所有的 key 使用 lru 逐出 | Evicts the least recently used keys out of all keys 在所有 key 中逐出最近最少使用的
allkeys-lfu 所有的 key 使用 lfu 逐出 | Evicts the least frequently used keys out of all keys 在所有 key 中逐出最近最不频繁使用的
allkeys-random 所有的 key 中随机逐出 | Randomly evicts keys out of all keys 在所有 key 中随机逐出
volatile-lru | Evicts the least recently used keys out of all keys with an “expire” field set 在设置了过期时间的 key 空间 expire 中使用 lru 策略逐出
volatile-lfu | Evicts the least frequently used keys out of all keys with an “expire” field set 在设置了过期时间的 key 空间 expire 中使用 lfu 策略逐出
volatile-random | Randomly evicts keys with an “expire” field set 在设置了过期时间的 key 空间 expire 中随机逐出
volatile-ttl | Evicts the shortest time-to-live keys out of all keys with an “expire” field set.在设置了过期时间的 key 空间 expire 中逐出更早过期的

而在这其中默认使用的策略是 volatile-lru，对 lru 跟 lfu 想有更多的了解可以看下我之前的文章redis系列介绍八-淘汰策略

## redis过期策略复习

发表于 2021-07-25 分类于 redis 阅读次数： Disqus：

# redis过期策略复习

之前其实写过redis的过期的一些原理，这次主要是记录下，一些使用上的概念，主要是redis使用的过期策略是懒过期和定时清除，懒过期的其实比较简单，即是在key被访问的时候会顺带着判断下这个key是否已过期了，如果已经过期了，就不返回了，但是这种策略有个漏洞是如果有些key之后一直不会被访问了，就等于沉在池底了，所以需要有一个定时的清理机制，去从设置了过期的key池子（expires）里随机地捞key，具体的策略我们看下官网的解释

1. Test 20 random keys from the set of keys with an associated expire.
2. Delete all the keys found expired.
3. If more than 25% of keys were expired, start again from step 1.

从池子里随机获取20个key，将其中过期的key删掉，如果这其中有超过25%的key已经过期了，那就再来一次，以此保持过期的key不超过25%（左右），并且这个定时策略可以在redis的配置文件

    # Redis calls an internal function to perform many background tasks, like
    # closing connections of clients in timeout, purging expired keys that are
    # never requested, and so forth.
    #
    # Not all tasks are performed with the same frequency, but Redis checks for
    # tasks to perform according to the specified "hz" value.
    #
    # By default "hz" is set to 10. Raising the value will use more CPU when
    # Redis is idle, but at the same time will make Redis more responsive when
    # there are many keys expiring at the same time, and timeouts may be
    # handled with more precision.
    #
    # The range is between 1 and 500, however a value over 100 is usually not
    # a good idea. Most users should use the default of 10 and raise this up to
    # 100 only in environments where very low latency is required.
    hz 10

可以配置这个hz的值，代表的含义是每秒的执行次数，默认是10，其实也用了hz的普遍含义。有兴趣可以看看之前写的一篇文章redis系列介绍七-过期策略

## 2021 年中总结

发表于 2021-07-18 分类于 生活 ， 年中总结 ， 2021 阅读次数： Disqus：

又到半年总结时，第一次写总结类型的文章感觉挺好写的，但是后面总觉得这过去的一段时间所做的事情，能力上的成长低于预期，但是是需要总结下，找找问题，顺便展望下未来。

这一年做的最让自己满意的应该就是看了一些书，由折腾群洋总发起的读书打卡活动，到目前为止已经读完了这几本书，《cUrl 必知必会》，《古董局中局 1》，《古董局中局 2》，《算法图解》，《每天 5 分钟玩转 Kubernetes》《幸福了吗？》《高可用可伸缩微服务架构：基于 Dubbo、Spring Cloud和 Service Mesh》《Rust 权威指南》后面可以写个专题说说看的这些书，虽然每天打卡如果时间安排不好，并且看的书像 rust 这样比较难的话还是会有点小焦虑，不过也是个调整过程，一方面可以在白天就抽空看一会，然后也不必要每次都看很大一章，注重吸收。

技术上的成长的话，有一些比较小的长进吧，对于一些之前忽视的 synchronized，ThreadLocal 和 AQS 等知识点做了下查漏补缺了，然后多了解了一些 Java 垃圾回收的内容，但是在实操上还是比较欠缺，成型的技术方案，架构上所谓的优化也比较少，一些想法也还有考虑不周全的地方，还需要多花时间和心思去学习加强，特别是在目前已经有的基础上如何做系统深层次的优化，既不要是鸡毛蒜皮的，也不能出现一些不可接受的问题和故障，这是个很重要的课题，需要好好学习，后面考虑定一些周期性目标，两个月左右能有一些成果和总结。

另外一部分是自己的服务，因为 ucloud 的机器太贵就没续费了，所以都迁移到腾讯云的小机器上了，顺便折腾了一点点 traefik，但是还很不熟练，不太习惯这一套，一方面是 docker 还不习惯，这也加重了对这套环境的不适应，还是习惯裸机部署，另一方面就是 k8s 了，家里的机器还没虚拟化，没有很好的条件可以做实验，这也是读书打卡的一个没做好的点，整体的学习效果受限于深度和实操，后面是看都是用 traefik，也找到了一篇文章可以 traefik 转发到裸机应用，因为主仓库用的是裸机的 gogs。

还有就是运动减肥上，唉，这又是很大的一个痛点，基本没效果，只是还算稳定，昨天看到一个视频说还需要力量训练来增肌，以此可以提升基础代谢，打算往这个方向尝试下，因为今天没有疫情限制了，在 6 月底完成了 200 公里的跑步小目标，只是有些膝盖跟大腿根外侧不适，抽空得去看下医生，后面打算每天也能做点卷腹跟俯卧撑。

下半年还希望能继续多看看书，比很多网上各种乱七八糟的文章会好很多，结合豆瓣评分，找一些评价高一些的文章，但也不是说分稍低点的就不行，有些也看人是不是适合，一般 6 分以上评价比较多的就可以试试。

## 聊聊 SpringBoot 自动装配

发表于 2021-07-11 更新于 2021-07-20 分类于 Java ， SpringBoot 阅读次数： Disqus：

springboot 自动装配调用链

springboot 相比 spring能更方便开发人员上手，比较重要的一点就是自动装配，大致来看下这个逻辑

    public static void main(String[] args) {
    		SpringApplication.run(SpbDemoApplication.class, args);
    	}

    	/**
    	 * Static helper that can be used to run a {@link SpringApplication} from the
    	 * specified source using default settings.
    	 * @param primarySource the primary source to load
    	 * @param args the application arguments (usually passed from a Java main method)
    	 * @return the running {@link ApplicationContext}
    	 */

然后就是上面调用的 run 方法

    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    	return run(new Class<?>[] { primarySource }, args);
    }

    /**
     * Static helper that can be used to run a {@link SpringApplication} from the
     * specified sources using default settings and user supplied arguments.
     * @param primarySources the primary sources to load
     * @param args the application arguments (usually passed from a Java main method)
     * @return the running {@link ApplicationContext}
     */

继续往下看

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    	return new SpringApplication(primarySources).run(args);
    }

阅读全文 »

## Leetcode 42 接雨水 (Trapping Rain Water) 题解分析

发表于 2021-07-04 更新于 2022-06-11 分类于 Java ， leetcode 阅读次数： Disqus：

## 题目介绍

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图，计算按此排列的柱子，下雨之后能接多少雨水。

## 示例

输入：height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出：6
解释：上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图，在这种情况下，可以接 6 个单位的雨水（蓝色部分表示雨水）。

## 简单分析

其实最开始的想法是从左到右扫区间，就是示例中的第一个水槽跟第二个水槽都可以用这个办法解决
前面这种是属于右侧比左侧高的情况，对于左侧高右侧低的就不行了，（写这篇的时候想起来可以再反着扫一遍可能可以）
所以这个方案不好，贴一下这个方案的代码

    public int trap(int[] height) {
        int lastLeft = -1;
        int sum = 0;
        int tempSum = 0;
        boolean startFlag = true;
        for (int j : height) {
            if (startFlag && j <= 0) {
                startFlag = false;
                continue;
            }
            if (j >= lastLeft) {
                sum += tempSum;
                tempSum = 0;
                lastLeft = j;
            } else {
                tempSum += lastLeft - j;
            }
        }
        return sum;
    }

后面结合网上的解法，其实可以反过来，对于每个格子找左右侧的最大值，取小的那个和当前格子的差值就是这一个的储水量了
理解了这种想法，代码其实就不难了

## 代码

    int n = height.length;
    if (n <= 2) {
        return 0;
    }
    // 思路转变下，其实可以对于每一格算储水量，算法就是找到这一格左边的最高点跟这一格右边的最高点，
    // 比较两侧的最高点，取小的那个，然后再跟当前格子的高度对比，差值就是当前格的储水量
    int maxL[] = new int[n];
    int maxR[] = new int[n];
    int max = height[0];
    maxL[0] = 0;
    // 计算左侧的最高点
    for (int i = 1; i < n - 1; i++) {
        maxL[i] = max;
        if (max < height[i]) {
            max = height[i];
        }
    }
    max = height[n - 1];
    maxR[n - 1] = 0;
    int tempSum, sum = 0;
    // 计算右侧的最高点，并且同步算出来储水量，节省一个循环
    for (int i = n - 2; i > 0; i--) {
        maxR[i] = max;
        if (height[i] > max) {
            max = height[i];
        }
        tempSum = Math.min(maxL[i], maxR[i]) - height[i];
        if (tempSum > 0) {
            sum += tempSum;
        }
    }
    return sum;