你要如何衡量你的人生

坚持,努力,让好事发生

其实,很多东西都是经历过,遇到问题,解决了,然后才知道。大学时候学过设计模式,但是没有实践过,很快就忘了。后来开发的时候遇到一些问题,解决了,然后感觉像哪个设计模式,回过头去看设计模式,感觉挺有用的。

学完设计模式以后,建议用简单、高效、易维护的态度去设计开发。

(1) 什么是设计模式

软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

(2) 设计模式的分类

创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。

结构型模式:把类或对象结合在一起形成一个更大的结构。

行为型模式:类和对象如何交互,及划分责任和算法。

阅读全文 »

在很长的一段时间里,使用的是多域名,主要有 weikeqin.cn weikeqin.com,但是两个域名解析到的是同一个博客,想把 weikeqin.cn 的流量全部转到 weikeqin.com,因为有些时候 .cn 不如 .com 域名,在某个特殊的时候感觉特别明显。然后就有了这篇文章。
在具体更换域名前的测试中,发现github.com还是比coding.net好用。

(1) 博客域名更换

域名的重定向的方法有 1.域名转发 2.301重定向 3.JS跳转
方法一,域名注册商支持域名转发功能才行!国内的绝大部分域名注册商不支持。
方法二,是Web 服务器给访问老域名的请求返回一个 301 或者 302,然后跳转到新域名上。 如果转发前的域名和转发后的域名访问的都是中国大陆的服务器而且已经备案,可以直接通过域名解析配置 显性URL 301重定向。 由于使用的是 github.com coding.net 的page服务,解析到的不是中国大陆的服务器,这个方法也不可行。
方法三,使用js跳转。具体方法如下。

网站重定向

(1.1) index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>新域名 https://weikeqin.com</title>
</head>

<body>
    <p> 跳转中,访问新域名站点 <a href="https://weikeqin.com" target="_blank"> https://weikeqin.com </a> </p>
</body>
<script type="text/javascript">console.log("index.html")</script>
<script type="text/javascript">window.location.href = "https://weikeqin.com";</script>

</html>
阅读全文 »

GitHub上搜索代码时,是怎么样操作的呢?是不是也是像普通人一样,直接在搜索框里输入要检索的内容,然后不断在列表里翻页找自己需要的内容?或者是简单筛选下,过滤一下。再或者改变一下列表的排序方式。这就是「全部」了吗?

一般的系统检索功能,都会有一个「高级搜索」的功能。需要在另外的界面里展开,进行二次搜索之类的。 GitHub 有没有类似的呢?

答案是「肯定的」。做为一个为万千工程师提供服务的网站,不仅要有,而且还要技术范儿。

(1) github高级搜索

高级搜索时,特殊字符会进行转码
%20 是 空格
%3A 是 :
%3E 是 >

(1.1) 明确搜索仓库标题、仓库描述、README

GitHub 提供了便捷的搜索方式,可以限定只搜索仓库的标题、或者描述、README等。

以Spring Cloud 为例,一般一个仓库,大概是这样的

红色箭头指的两个地方,分别是仓库的名称和描述。咱们可以直接限定关键字只查特定的地方。

比如只想查找仓库名称包含 spring cloud 的仓库,可以使用 in:name 关键词
https://github.com/search?utf8=%E2%9C%93&q=in%3Aname+spring+cloud&type=

如果想查找描述的内容,可以使用 in:descripton 关键词
https://github.com/search?q=in%3Adescripton+spring+cloud
https://github.com/search?utf8=%E2%9C%93&q=in%3Adescripton+spring+cloud&type=

阅读全文 »

在使用MySQL时,如果发现查询语句耗时,会进行排查及调优,其中常用的一个方法是用explain查看sql执行计划。

(1) explain小试牛刀

通过一个简单的例子来了解explain的使用

CREATE TABLE `t2` (
  `id` int NOT NULL AUTO_INCREMENT,
  `a` int DEFAULT NULL,
  `b` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_a` (`a`),
  KEY `idx_b` (`b`)
) ENGINE=InnoDB ;

往表 t2 中插入 10 万行记录,取值按整数递增,即:(1,1,1),(2,2,2),(3,3,3) 直到 (100000,100000,100000)。

用存储过程来插入10万数据,sql如下:

delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=100000)do
    insert into t values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;

call idata(); /** 调用存储过程 */

假设需要执行下面这条语句,语句的执行结果最多只有1条,因为有limit 1,但是表t2有2个索引 idx_a idx_b ,MySQL会选用哪个?
如果是我们来分析,肯定是选idx_a,因为 a between 1 and 1000 只需要扫描idx_a索引1000个值,而 b between 50000 and 100000需要扫描idx_b索引50000个值

mysql> select * from t where (a between 1 and 1000)  and (b between 50000 and 100000) order by b limit 1;
mysql> explain select * from t2 where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;
+----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                              |
+----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | range | a,b           | b    | 5       | NULL | 50128 |     1.00 | Using index condition; Using where |
+----+-------------+-------+------------+-------+---------------+------+---------+------+-------+----------+------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql>

结合慢查询日志

# Time: 2022-12-10T17:11:35.593173+08:00
# User@Host: admin[admin] @ localhost [127.0.0.1]  Id:    16
# Query_time: 0.105205  Lock_time: 0.000003 Rows_sent: 0  Rows_examined: 50001
SET timestamp=1670663495;
select * from t2 where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;

慢日志的Rows_examined:执行该SQL,实际扫描的行数,真实值
慢日志的Rows_sent:执行该SQL,实际返回的行数

之前优化器选择使用索引 b,是因为它认为使用索引 b 可以避免排序(b 本身是索引,已经是有序的了,如果选择索引 b 的话,不需要再做排序,只需要遍历),所以即使扫描行数多,也判定为代价更小。

mysql> explain select * from t2 where (a between 1 and 1000) and (b between 50000 and 100000) order by b,a limit 1;
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | range | a,b           | a    | 5       | NULL | 1000 |    50.00 | Using index condition; Using where; Using filesort |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+----------------------------------------------------+
1 row in set, 1 warning (0.01 sec)

mysql>

order by b,a 这种写法,要求按照 b,a 排序,就意味着使用这两个索引都需要排序。因此,扫描行数成了影响决策的主要条件,于是此时优化器选了只需要扫描 1000 行的索引 a。

# Time: 2022-12-10T17:27:04.352721+08:00
# User@Host: admin[admin] @ localhost [127.0.0.1]  Id:    16
# Query_time: 0.020284  Lock_time: 0.000020 Rows_sent: 0  Rows_examined: 1000
SET timestamp=1670664424;
select * from t2 where (a between 1 and 1000) and (b between 50000 and 100000) order by b,a limit 1;
阅读全文 »

(1) Java内存模型

Java内存模式是一种虚拟机规范。

Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM),用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果

JMM规范了Java虚拟机与计算机内存是如何协同工作的:
规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,
以及在必须时如何同步的访问共享变量。

JSR 133 (Java Memory Model) FAQ

阅读全文 »

为什么要使用并发编程?

  1. 随着硬件的发展,互联网系统并发量轻松过百万,传统的中间件和数据库已经不能满足需求,成为瓶颈所在。
  2. 很多情况下,服务器的资源使用率并不高,导致资源浪费,比如线上服务器的CPU使用率经常是10%,并发编程可以提高资源使用率。

但是在并发编程里,很多单线程的规则不太适用,就像汽车的用法不适用飞机一样。

在并发编程里,经常遇到很多诡异的bug,这些bug大多可能是逻辑问题或者是对使用的技术不了解导致的。

并发编程的三个核心问题

并发编程可以总结为三个核心问题:分工、同步、互斥。

Java SDK 并发包很大部分内容都是按照这三个维度组织的

阅读全文 »

当摆弄索引里面的数据时,我们发现一些奇怪的事情。一些事情看起来被打乱了:在我们的索引中有12条推文,其中只有一条包含日期 2014-09-15 ,但是看一看下面查询命中的 总数 (total):

GET /_search?q=2014              # 12 results
GET /_search?q=2014-09-15        # 12 results !
GET /_search?q=date:2014-09-15   # 1  result
GET /_search?q=date:2014         # 0  results !

为什么在 _all 字段查询日期返回所有推文,而在 date 字段只查询年份却没有返回结果?为什么我们在 _all 字段和 date 字段的查询结果有差别?
因为数据在 _all 字段与 date 字段的索引方式不同。

阅读全文 »

search 最基本的工具

Elasticsearch 不只会_存储(stores)_ 文档,为了能被搜索到也会为文档添加_索引(indexes)_ ,这也是为什么我们使用结构化的 JSON 文档,而不是无结构的二进制数据。

文档中的每个字段都将被索引并且可以被查询 。不仅如此,在简单查询时,Elasticsearch 可以使用 所有(all) 这些索引字段,以惊人的速度返回结果。

搜索(search) 可以做到:
在类似于 gender 或者 age 这样的字段上使用结构化查询,join_date 这样的字段上使用排序,就像SQL的结构化查询一样。
全文检索,找出所有匹配关键字的文档并按照_相关性(relevance)_ 排序后返回结果。
以上二者兼而有之。

很多搜索都是开箱即用的,为了充分挖掘 Elasticsearch 的潜力,你需要理解以下三个概念:

映射(Mapping)
描述数据在每个字段内如何存储
分析(Analysis)
全文是如何处理使之可以被搜索的
领域特定查询语言(Query DSL)
Elasticsearch 中强大灵活的查询语言

阅读全文 »

文件是如何分布到集群的,又是如何从集群中获取的。

(1) 路由一个文档到一个分片中

当索引一个文档的时候,文档会被存储到一个主分片中。
这个过程是根据下面这个公式决定的:
shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

所有的文档 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一个叫做 routing 的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

阅读全文 »

Elastcisearch 是分布式的 文档 存储。它能存储和检索复杂的数据结构—​序列化成为JSON文档—​以 实时 的方式。 换句话说,一旦一个文档被存储在 Elasticsearch 中,它就是可以被集群中的任意节点检索到。

在 Elasticsearch 中, 每个字段的所有数据 都是 默认被索引的 。 即每个字段都有为了快速检索设置的专用倒排索引。而且,不像其他多数的数据库,它能在 同一个查询中 使用所有这些倒排索引,并以惊人的速度返回结果。

ElasticSearch 和 MySQL 结构对照

ES MySQL
Node/Cluster Cluster
Index Database
Type table
Document row (一行)
field field (一列)

(1) 什么是文档?

{
    "name":         "John Smith",
    "age":          42,
    "confirmed":    true,
    "join_date":    "2014-06-01",
    "home": {
        "lat":      51.5,
        "lon":      0.1
    },
    "accounts": [
        {
            "type": "facebook",
            "id":   "johnsmith"
        },
        {
            "type": "twitter",
            "id":   "johnsmith"
        }
    ]
}

在 Elasticsearch 中,术语 文档 有着特定的含义。它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了唯一 ID。

字段的名字可以是任何合法的字符串,但 不可以 包含英文句号(.)。

阅读全文 »
0%