Skip to content

Latest commit

 

History

History
183 lines (121 loc) · 7.61 KB

2018-12-25.md

File metadata and controls

183 lines (121 loc) · 7.61 KB

一. Alogritgm

做了一到比较简单的题目,回文数的判断,用 Python 代码实现如下:

方式 1,将数字转为字符串后进行反转,若反转前后相等,则是回文数

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        str_x = str(x)
        palindrome_x = str_x[::-1]
        return str_x == palindrome_x

上面方式需要新建一个回文字符串,如果字符串较大的话会占用较多的空间,可以直接在原有字符串上同时进行前后遍历比较,实现如下:


class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        str_x  = str(x)

        length = len(str_x)
        index = int(length / 2)

        for i in range(index):
            if not str_x[i] == str_x[length - 1]:
                return False
            length -= 1
            
        return True

二. Review

本周 Review 读了耗子叔练级攻略中推荐的一篇数据库相关的文章: SQL vs. NoSQL Databases: What’s the Difference?

文章主要比较 SQL 数据库(关系型数据库) 和 NoSQL 数据库各自的特点以及主要的数据库软件,并给出了数据库选择的一些建议。简要整理如下:

1. 关系型数据库

关系型数据库数据存储有表和列组成,在数据存储前必须定义表中数据的基本信息以及表字段之间的关系,即 schema。Schema 的定义可以保证数据的准确性,但一定程度上也会影响扩展的灵活性。比如某一个字段要存储美国的手机号码,是长度为 10,一开始我们加上长度为 10 的限制可以避免不符合条件的数据存入,但是如果哪天我们要求改了,不仅仅存储美国的,还要存储世界各地的手机号,那么就需要修改表,这是非常重的操作。

关系型数据库通过 SQL 结构化查询语句实现数据的增删改查,同时一个非常有用的功能就是 join 查询,可以通过一条语句查询出几张表中的数据。

另外关系型数据库的 schema 结构非常符合现实世界中很多业务场景的逻辑关系,配合 Java 等面向对象语言,非常适合大部分的软件开发。

何时使用关系型数据库

  • 需要保证数据的 ACID。当对数据的一致性、隔离性等有严格要求时,就需要使用关系型数据库,对数据操作进行较为严格的约束。

  • 数据结构较为稳定,且暂时没用大规模增长的情况下可以考虑使用关系型数据库

2. NoSQL (Not Only SQL) 数据库

NoSQL 数据库没有 SQL 数据库那样严格也明确的数据结构限定,因为数据的存储可以非常的灵活。可以将 NoSQL 数据库看做是一个文件夹,如同电脑中的文件夹,我们可以存放图片、文本、音乐、视频等一个个文件数据,NoSQL 数据库也可以将数据看做一个个的文档进行存储。 但是 NoSQL 数据库往往占用的空间比 SQL 数据库要大,并且对事务操作支持并不好。

NoSQL 数据库分类

  • 键值数据库: 最简单的 NoSQL 数据库,数据由键值对组成,比如 Cassandra, Azure, LevelDB、 Riak 等
  • 文档数据库: 可以存放文档数据,其数据格式为 Json/Bson/XML 等,比如 MongoDB 数据库
  • 列数据库: 将数据存储为列而不是行,具有很高的扩展性,比如 HBase、BigTable 等
  • 图数据库: 存储相互关联并且可以用图来表示的数据,比如 Polyglot, Neo4J。

选择 NoSQL 的一些建议

  • 需要存储大量的非结构化数据时
  • 需要充分的利用到云计算和云存储时可以考虑采用 NoSQL 数据库。

以上就是文章的简要总结,关于 NoSQL 耗子叔在专栏中推荐了一本 NoSQL 精粹,非常值得一读。

三. Tips

分享几个在 Go101 中读到的几个关于 Go 的编程技巧。

1. 快速定义 int 和 uint 的最大值常量

const MaxUint = ^uint(0)
const MaxInt = int(^uint(0) >> 1)

2. 模拟 for 0...N

在其他语言中可以快速的实现 0 到 N 的遍历,比如 Python:


In [2]: for i in range(5):
   ...:     print(i)
   ...:
   

Go 语言中可通过如下方式快速实现同样的功能:

ackage main

import "fmt"

func main() {
	const N = 5

	for i := range [N]struct{}{} {
		fmt.Println(i)
	}
	for i := range [N][0]int{} {
		fmt.Println(i)
	}
	for i := range (*[N]int)(nil) {
		fmt.Println(i)
	}
}

3. 如何优雅的拷贝一个 slice

Go 的 wiki 中提供了如下两种方式:

// 方式 1
b = make([]T, len(a))
copy(b, a)

// 方式 2
b = append([]T(nil), a...)

但是以上两种方式都有问题:

  • 方式1: 即使 a 是 nil, b 也会创建一个新的 slice
  • 方式2: 如果 a 是一个非 nil 的空切片,那么 b 是为 nil

可以通过下面方式解决上面的两个维内托:

if a == nil {
	b = nil
} else {
	b = make([]T, len(a))
	copy(b, a)
}

相当于提前做了一次判断,但代码并不优雅,可以简化如下:

b = append(a[:0:0], a...)

这样保证如果 a 不是 nil 则 b 也不是 nil,a 是 nil 的话 b 也是 nil。

四. Share

读了耗子叔新发表的问题 K8S 的问题排查文章,简要写几点看之后的感想:

  • 对于技术问题,高效的问题定位与解决取决于知识的广度与深度。作为程序员拥有扎实的基础知识永远是最硬核的技能。 耗子叔在文中提高的很多命令行、网络相关的知识、systemd 相关的知识,都是实打实的基础知识,这些都是需要下功夫学习实践之后才能积累下来的。

  • 对于知识的掌握要结合场景,明白哪个知识点对应怎样的场景,这样就能在实践中充分发挥威力,针对每个故障找到可能的对应的问题点和检验方式。

  • 接上一条,当明白了知识点对应的场景时,就能按部就班的排查问题了,使用排除法一步步的探查问题,如果一遍没有查出,就退回去重新梳理所有细节再次排查。

举一个自己的反面例子吧,最近公司自己出了一门能够进行人脸识别的智能门禁,用户上传照片后服务端拿到算法生成的人脸 ID 需要同步给各个门禁端。但有一个门禁无论怎样就是同步不过去。当时和客户端同事没有细致的思考原因所在,一步步的排查问题,大部分都是在用蛮力在一次次的重试。正确的做法应该如下:

  • 门禁设备是通过长连接连到服务端的,接收服务端数据 push。因此最有可能的原因是 push 服务不可用
  • 检查其他门禁,是没有问题的,说明 push 服务可用,问题出在这台门禁上。(当时就是卡在这里,没有进一步思考连不上的原因)
  • 拿到服务监控 API 发现该门禁对应的 channel 没有连接,说明门禁没有连上长连接 - 门禁的连接是通过和服务端约定好的通过 md5 算法生成的 channel_id 连接的,按理来说只要 channel_id 一直不应该连接不上
  • 经比对后发现,客户端用 Java 开发,当 md5 开头一位是 0 时会省略掉,由此导致客户端生成的 channel_id 和服务端不一致,因此导致连接不上,因为并不必现,因此之前没有发生这个问题。

回头来看只是是一个挺简单的问题排查过程,但是确实当时没有动脑子快速解决,需要深刻反省。另外就是想到了上司说的一句话: 软件开发没有玄学,问题都是能找到原因的。