Skip to content

Latest commit

 

History

History
230 lines (153 loc) · 13 KB

2019-01-09.md

File metadata and controls

230 lines (153 loc) · 13 KB

一. Algorithm

本次做了 739. Daily Temperatures。给予一个数组,对于一个元素,查出与比该元素大的第一个元素的相差的位置。首先想到的是双重遍历,查出每个差值,代码如下:

class Solution {
     public int[] dailyTemperatures(int[] T) {

        int length = T.length;
        int[] result = new int[length];
         
        int days = 0;
        for (int i = 0; i < length - 1; i ++) {
            for (int j = i + 1; j < length; j ++) {
                days ++;
                if (T[j] > T[i]) {
                    result[i] = days;
                    break;
                }
            }
            days = 0;
        }
        return result;

    }
}

如果给出的数组是完全降序,最坏情况下时间复杂度为O(N^2), 提交时运行时间为 300 多ms。

然后就是查找相关资料可以使用栈来实现时间复杂度为 O(N) 的操作,基本思路是先将每个索引入栈,在遍历后续的元素时,如果该元素比栈中索引对应的元素大,则将该索引出栈,并计算两个索引的差值。这样每个元素在循环时会访问一次,然后在栈操作时还会判断一次,时间复杂度为 O(N),代码如下:

class Solution {
     public int[] dailyTemperatures(int[] T) {

       Stack<Integer> stack = new Stack();

        int length = T.length;

        int[] result = new int[length];

        for (int i = 0; i < length; i ++) {

            while (!stack.empty() && T[i] > T[stack.peek()]) {
                int index = stack.pop();
                result[index] = i - index;
            }
            stack.push(i);
        }
        return result;


    }
}

二. Review

本周读了一篇 FileBeat 相关的文章: 5 Filebeat Pitfalls To Be Aware Of

Filebeat 是 ELK 技术栈中用来收集日志文件的工具,是用 Go 语言写的,因此性能非常高,逐渐替代了 Logstash-forawrd 成为了日志收集的主要工具。虽然 FileBeat 比较简单易用,但也存在一些容易被忽略的问题。文章主要讲了如下 5 个使用 FileBeat 时需要注意的问题:


1. YAML 配置

FileBeat 使用 YAML 格式的文件作为配置文件,因此和其他使用 Yaml 文件作为配置文件的软件一样,会因为 YAML 配置的语法出现错误。

YAML 文件本身对缩进和结构有比较严格的要求,有时候一个错误的缩进就可能导致整个应用无法使用,因此在配置时务必要谨慎细致。关于 YAML 配置的问题,作者推荐了另一篇文章 Musings in YAML – Tips for Configuring Your Beats 供作参考。

2. Registry File

FileBeat 为了保证不丢失数据,会将每个要收集的文件的读取信息记录到 Registry File 中。如果出现短时间内创建大量日志文件的情况,那么向 Registry File 中记录的信息会急剧增加,从而占用过高的内存空间,影响软件和服务器的性能,因此在使用时要注意避免类似的情况。

另外 FileBeat 也提供了 clean_removed 配置项,当日志文件被删除时,其在 Registry File 中的信息也会被删除,从而节省空间。关于该配置的信息参见文档:Configure FileBeat

3. 删除或者重命名文件时释放资源

当文件被删除或者重命名时,FileBeat 依然会保留对该文件的追踪,即依然占用着服务器资源,随着文件数量的增多,久而久之占用的资源就会越来越大,影响性能。为了解决该问题,需要用到 close_inactiveclosed_removed 配置项。简介如下:

  • close_inactive: 按照一定的时间间隔检查文件是否有改动,如果没有则结束对该文件的读取,释放资源。默认设置是 5 分钟。
  • closed_removed: 当文件被移除时,结束对该文件的读取,释放资源。

通过上述两个配置项,可以释放资源,更详细的解释参阅文档:Configure FileBeat

4. 多个文件源

FileBeat 本身允许我们配置多个文件路径,如下:

- type: log
  enabled: false
  paths:
    - /var/log/*.log

- type: log
  enable: true
  tags: ['nginx', 'p1', 'access']
  paths:
    - /var/log/nginx/*.p1.access.log
  fields:
     log_topic: nginx

- type: log
  enable: true
  tags: ['nginx', 'p2', 'access']
  paths:
    - /var/log/nginx/*.p2.access.log
    - /var/log/nginx/*.p2.access.log.1
  fields:
     log_topic: nginx

虽然方便,但是当我们想追踪某一类文件时就会很麻烦,因此建议对每一类文件配置,都加一个type 或者 tag 以便于之后的进行区分。

5. CPU 的使用

因为是 Go 语言编写的,FileBeat 的整体性能是非常高的,很少出现占用过高 CPU 的情况。但是有一种情况可能会造成 CPU 占用的上升: FileBeat 对于每个 log 配置都可以通过配置项 scan_frequency 来设置读取文件的频率,默认是 10s, 官方文档中提示不建议小于 1s。当设置的读取文件过多,并且读取频率过于频繁时就会造成问题,实际使用中要避免这种情况。

以上就是文章主要提到的内容,总体而言 FileBeat 的使用还是非常简单的,不过随着 ES 的普及,FileBeat 的使用也会增多,因此多了解一些相关的细节和问题也是非常有必要的。

三. Tips

分享一下用 基于 Django Admin 定制任务的操作吧。

Django 最大的好处就是其提供了便捷的 ORM 操作和一套很成熟的后台 admin 管理后台,可以使我们方便的管理各个表的数据。大多数时候的使用都只是简单的罗列数据,但其实 admin 可以能做的有很多,这里分享两个: 展示外键特定字段数据以及定制数据任务。

示例如下,我有一张用户表:

class User(models.Model):
    class Meta:
        db_table = "user"
        app_label = "user"
        verbose_name_plural = "用户"

    username = models.CharField(verbose_name="用户名", max_length=120, default="")
    phone = models.CharField(verbose_name="电话", max_length=120, default="")
    shop = models.ForeignKey(Shop, verbose_name="所属店铺", default=None)
    status = models.CharField(verbose_name="状态", max_length=120, default="")

如果我想在 admin 中展示所有字段的值,可以如下配置:

class UserAdmin(admin.ModelAdmin):
    list_display = ["id", "username", "shop", "phone", "status"]
    # 要展示外键必须要填加
    raw_id_fields = ["shop"]

上面的配置可以将 shop 字段的默认配置文本展示出来,但如果我想展示店铺的地址改怎么做的呢?首先要在 list_display 中添加上字段,

list_display = ["id", "username", "shop", "phone", "status", "shop_address"]

然后就要实现对应的方法和指定标题了,如下:

def list_display(self, obj):
        return obj.shop.address
get_gym_logo.short_description = u"店铺地址"

这样我们就可以在 用户的 admin 列表中看到 shop 的地址信息了,有了信息此时我们想将其批量导出怎么办呢?当然可以通过写脚本解决,但是未免有点麻烦,我们通过 actions 配置一个导出任务,配置如下:

class UserAdmin(admin.ModelAdmin):
    list_display = ["id", "username", "shop", "phone", "status"]
    # 要展示外键必须要填加
    raw_id_fields = ["shop"]
    actions = ['output_excel']
    
    def output_excel(self, request, queryset):
        data = []
        headers = [u"用户 ID", u"用户名", u"电话", "用户状态"]
        data.append(headers)

        for item in queryset:
            user_id = item.id
            username = item.username
            phone = item.phone
            status = item.status
            line = [user_id, username, phone, status]
            data.append(line)
        return ExcelResponse(data, output_name="shop_qrcode_%s" % date_to_str(datetime_now().date()))

    output_excel.short_description = u"导出用户数据"

通过 action 添加任务类型,然后实现对应的方法并指定任务名,然后结合 list_filter 删选项就可以实现特定数据的直接导出了。

关于 admin 的操作还有很多,有兴趣的同学可以参阅其官方文档: Admin

四. Share

这两天在思考一个问题:

我们需要那么多的公众号文章吗?

起因是一位之前交流比较多的同行重拾公众号写作,并发起了调研和接受粉丝投稿。微信公众号越来越多,成了信息洪流中一个非常重要的组成。我非常赞同通过公众号输出自己所学的行为以及互相交流学习的心态和氛围。但对于技术学习来说,本人并不觉得技术公众号有很大的价值,通过公众号文章学习,个人觉得主要有下面几个问题,

1. 过于碎片化

公众号最大问题就是知识点过于碎片化,不够系统。很少有公众号作者可以一个专题一个专题系统的输出某一知识点的内容。更多时候是今天发的是 MySQL 相关的内容,明天就可能是某一门语言的某个语法。这样当你通过公众号文章进行学习的时候其实是一个个的点去学习,并且很难将这些点连点成线,形成一个框架。这对于学习的沉淀积累是非常不利的,久而久之就会像狗熊掰棒子一样,学了一点忘了另一点,无法积累。

2. 不够深刻

现代人的时间被严重的碎片化了,一般来说读微信公众号的文章时并不都是有大块时间的时候,这就注定了对于技术文章,你无法写的太过深刻和详细,因为很难在十分钟甚至更少的时间内将一个技术写的非常明白。当然也可以分为多篇进行讲解,但是这样无形中拉长了对于某一知识点的学习时长,并且因为中间有中断过,再次学习时的熟悉感会降低。更好的方式时拿出大块时间来专注学习,然后可以通过类似的碎片化文章进行复习。

3. 信息重复严重

同样的一个知识点,可能 N 个公众号都会发文章讲述。记得刚毕业时是做 Android 开发,订阅了一些 Android 开发相关的订阅号,每天早上都会收到各个公众号的推送文章,并且很多是接受的粉丝的投稿,感觉同质化非常严重。经常一天几个公众号收到的都是同一类的文章,而且就 Android 开发而言有个特点就是自定义组件的文章非常多,可能是因为写出一个比较好的自定义的组件或者界面非常有成就感吧。但其实针对自定义组件的学习,我们可能根本不需要参考这些订阅号文章,因为这些文章其实最核心的不是自定义组件的流程,而是其实现那些界面效果时的逻辑与算法,如果不是特定的需求用到特定的逻辑,这些内容不会对你的学习有太大的帮助,反而因为逻辑的复杂导致理解起来更加浪费时间。真要学习自定义组件,买本《Android 开发艺术探索》,加上官方文档和源码认认真真的过两边遍足矣,剩下的就是组件实现时的逻辑问题了,比如色彩的变化,高度厚度的变化规律等。

4. 目的性不强

记得读过和菜头的一篇文章:《成年人的学习方式》,里面提到的核心就是带着问题去学习。当我们遇到问题时,一般来说官方文档和搜索引擎是最好的帮手。很少会有遇到一个问题,刚好碰到了一篇相关文章的情况。这种情况下大部分阅读其实是不会留下深刻的印象的,也就不会带给我们真正的提高。

5. 导致时间碎片化

有段时间非常容易分心,看到一个公众号推送了就想去点开看下,不知道有多少人一样和我有类似的坏习惯,其实这是很严重的打断预定工作和学习计划的行为。一个小时就 60 分钟,打断三次就可能成了三段平均时间不足 20 分钟的碎片化时间了。对于要进行深度学习的人来说,尽可能的远离各种具有信息流特点的软件和平台是非常重要的,千万不要高估自己的意志力以及通过看一篇公众号文章得到很大收获的幻觉。

以上就是自己想到的过度关注微信公众号,想借此学习带来的几个问题,感觉公众号还是比较适合社科性的文章的阅读,增加思考的广度和视野,对于技术性的学习还是老老实实看书,看官方文档,源码,不断上手实践吧。而比起读他人的公众号,自己写公众号反而是一件收获更大的事情,将自己的所学不断输出,即梳理了学习体系,又因为要经得起别人的批判而对不断的提高自己的要求,这样会进一步逼迫自己不断成长。