StringUtils里的isEmpty方法和isBlank方法的区别

isEmpty()


public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}


isBlank()


public static boolean isBlank(String str) {
int strLen;
if (str != null && (strLen = str.length()) != 0) {
for(int i = 0; i < strLen; ++i) {
// 判断字符是否为空格、制表符、tab
if (!Character.isWhitespace(str.charAt(i))) {
return false;
}
}
return true;
} else {
return true;
}
}


结论
通过以上代码对比我们可以看出:

    1.isEmpty 没有忽略空格参数,是以是否为空和是否存在为判断依据。

    2.isBlank 是在 isEmpty 的基础上进行了为空(字符串都为空格、制表符、tab 的情况)的判断。(一般更为常用)

大家可以看下面的例子去体会一下。

StringUtils.isEmpty(“yyy”) = false
StringUtils.isEmpty(“”) = true
StringUtils.isEmpty(” “) = false

StringUtils.isBlank(“yyy”) = false
StringUtils.isBlank(“”) = true
StringUtils.isBlank(” “) = true

Linux top 命令

Top:Linux 系统下常用的监控工具,用于实时获取进程级别的 CPU 或内存使用情况。以下图 top 命令的输出信息为例。

Top 命令的输出信息主要分为两部分,上半部分显示 CPU 和内存资源的总体使用情况:

  • 第一行:系统当前时间,当前登录用户个数以及系统负载。
  • 第二行:系统总进程数、运行中进程数、休眠、睡眠和僵尸进程数量。
  • 第三行:CPU 当前使用情况。
  • 第四行:内存当前使用情况。
  • 第五行:Swap 空间当前使用情况。

下半部分以进程为维度显示资源的占用情况:

  • PID:进程 ID。
  • USER:进程所有者。
  • PR:进程优先级 NI:NICE 值,NICE 值越小,优先级越高。
  • VIRT:使用的虚拟内存大小,单位 KB。
  • RES:当前使用的内存大小,单位 KB。
  • SHR:使用的共享内存的大小,单位 KB。
  • S:进程状态。
  • %CPU:更新时间间隔内进程所使用的 CPU 时间的百分比。
  • %MEM:更新时间间隔内进程所使用的内存的百分比。
  • TIME+:进程使用的 CPU 时间,精确到 0.01s。
  • COMMAND:进程名称。

elastic 内存

1、JVM heap

ES 建议分配不超过 50% 的内存给 JVM,同时总量不要大于 32 GB。

# 设置 max heap size
export ES_HEAP_SIZE=10g

# 查看当前 max heap size
GET /_cat/nodes?h=heap.max

JVM 使用的内存越小,留给 Lucene 的内存就越多,就可以有更多的内存作为缓存,提高性能。但是 JVM 的内存也不能太小,否则会导致 OOM 或 FullGC,而这会导致节点超时被移出,shards reallocate 又会极大的影响性能。

ES 有两个组件需要使用内存:

  • JVM
  • Lucene

JVM 主要存放各种 in-memory 的数据结构,Lucene 负责底层的存储。因为 Lucene 依赖操作系统的缓存机制,而操作系统会把所有的空闲内存分配为 page cache,所以如果 JVM heap 过大,会导致 segment 没有足够的 cache。

64 位的指针会带来额外的性能开销,为了提高性能,Java 会采用 compressed oops 的技术,依然使用 32 位的指针,不过指针用来表示 object offsets,此时一个 32 位指针可以表示 4 G 的 object,而不是 4 G 的 bytes,这种情况下,可以让 heap 的空间达到 32 GB。但如果给 heap 分配的空间超过 32 GB,Java 就会采用 64 bit 的 ordinary object pointers(OOP),运行性能会出现显著下降,据估测,heap 大小达到 40-50 GB 时,性能才与 32 GB 时相同。

如果机器内存远大于 32 GB,也建议不要给 heap 设置超过 32 GB 的内存,可以考虑把机器划分为多个 64 GB 内存的节点,然后每个节点分配 32 GB heap。

2、GC

JVM 会申请一大块内存,称为 heap。heap 中的所有对象会被分为两个集合:Young(Eden)和 Old,一般来说 Old 的空间会显著的大于 Young。

每当 Young 的空间耗尽时,就会启动 young gc,所有幸存的对象会被标记为 survivor,如果一个对象连续两次被标记为 survivor,就会被放入 Old。Old 类似,空间耗尽时会触发 old gc。这两种 GC 都会导致 stop-the-world。不过因为 young 空间较小,gc 耗时一般也很短。带来严重暂停的一般都是 old gc。

ES 默认当 JVM heap 超过 75% 的时候启动 GC,所以应该监控 heap 使用率超过 80% 的情形,此时 gc 已无法有效的清理内存。默认的 heap 是 1GB,这个值太小,实际上线时要根据内存大小进行调整(一般小于 50% 内存)。但是 JVM heap 太大时,会导致 GC 时间过长。如果超过 30s 无响应,就会被 master 移出集群。

相关指标:

  • jvm.gc.collectors.young.collection_count
  • jvm.gc.collectors.young.collection_time_in_millis
  • jvm.gc.collectors.old.collection_count
  • jvm.gc.collectors.old.collection_time_in_millis
  • jvm.mem.heap_used_percent
  • jvm.mem.heap_committed_in_bytes

CMS & G1

ES 默认使用 CMS,在 Heap 较大时性能会比较差(更长的 Stop-the-world),相较之下 G1 在大 heap 时性能更好,但是 ES 官方不推荐使用 G1,因为 Lucene 在 G1 下会出现数据丢失的 bug。

Do not, under any circumstances, run Lucene with the G1 garbage collector. Lucene’s test suite fails with the G1 garbage collector on a regular basis, including bugs that cause index corruption. There is no person on this planet that seems to understand such bugs (see https://bugs.openjdk.java.net/browse/JDK-8038348, open for over a year), so don’t count on the situation changing soon.

3、swap

要尽一切可能避免系统 swap 内存。

不建议直接关闭 swap,应该调整 swappiness 来让系统降低 swap 的频率。swappiness 的取值范围为 0-100,0 表示仅在 OOM 时 swap,100 表示系统会尽一切可能 swap,默认值为 60,ES 建议设置为 1。

# 查询 swappiness
cat /proc/sys/vm/swappiness

# 设置
sudo vi /etc/sysctl.conf
vm.swappiness = 1

如果无法修改系统参数,可以修改 ES 的参数 mlockall,该参数会让 JVM 锁定进程的地址空间始终在内存内,避免被 swap:

bootstrap.memory_lock: true

# 查看是否启用 mlockall
GET _nodes?filter_path=**.mlockall

elastic 创建文档

创建新文档(indexing)的操作分为两步:refresh 和 flush。

Refresh

  1. 新插入的文档存放在 in-memory buffer 中
  2. 默认每秒一次的 refresh,会将 in-memory buffer 写入 in-memory segment(到这一步后,新文档就可被检索了)

每一个 shard 都有多个连续的 segment 组成,segment 是不可变的,所以每一次的 update 都意味着两步:

  • 写入新数据
  • 将老数据标记为已删除(在 merged 的时候才会真正删除)

Flush

  • 文档在被写入 in-memory buffer 的同时,也会写入 shard 的 translog
  • 每 30 分钟(或 translog 大小达到阈值),会促发 flush
  • flush 会清空 in-memory buffer,并且将 in-memory segment 提交到磁盘,然后清空 translog

translog 每 5s 就被提交到磁盘一次,可以通过 index.translog.flush_threshold_size 调整 translog 刷新的大小阈值。

涉及的指标:

  • indices.indexing.index_total
  • indices.indexing.index_time_in_millis
  • indices.indexing.index_current
  • indices.refresh.total
  • indices.refresh.total_time_in_millis
  • indices.flush.total
  • indices.flush.total_time_in_millis

通过监控 indexing latency,可以了解 ES 是否逼近写入极限。

1、提高写入性能

适当的制定 shards 数,让 index 分散于各个 node 之上,提高并发性能。

关闭 merge throttling,如果 ES 发觉有 merging 操作失败,就会自动会 index 进行限流,可以通过将 indices.store.throttle.type 设置为 none 来关闭这一功能。

提高 index buffer,indices.memory.index_buffer_size 默认为 10%。

在初始化 index 并需要执行大量 index 的时候,可以先不要设置 replicas,等大批量写入完成后,再设置 replica,可以显著提高性能。

默认每秒执行一次 refresh,降低 refresh 频率可以提高写入性能。

ES 2.0 以后,会在每一次 request 后 flush translog,设置 index.translog.durability=async 可以将 flush 设置为异步,并通过 sync_interval 设置刷新间隔。

需要注意的是,primary shards 数仅在创建 index 时可以指定,之后无法修改。只能通过创建新 index 再 reindex 的方式来实现扩展。

2、Store

File system storage types

GET /_settings

创建 index 时,可以指定文件系统,可用选项有:

  • fs:系统默认,系统兼容性好;
  • simplefs:并发性能差;
  • niofs:并发效率高,不支持 windows;
  • mmapfs:使用 mmap

推荐使用 niofs。

MySQL 中的 timestamp 和 datetime

两者都可用来表示YYYY-MM-DD HH:MM:SS[.fraction]类型的日期。

对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。

而对于DATETIME,不做任何改变,基本上是原样输入和输出。

timestamp所能存储的时间范围为:’1970-01-01 00:00:01.000000′ 到 ‘2038-01-19 03:14:07.999999’。

datetime所能存储的时间范围为:’1000-01-01 00:00:00.000000′ 到 ‘9999-12-31 23:59:59.999999’。

在MySQL 5.6.5版本之前,Automatic Initialization and Updating只适用于TIMESTAMP,而且一张表中,最多允许一个TIMESTAMP字段采用该特性。从MySQL 5.6.5开始,Automatic Initialization and Updating同时适用于TIMESTAMP和DATETIME,且不限制数量。

ps: 自动初始化和自动更新(Automatic Initialization and Updating)

自动初始化指的是如果对该字段(譬如上例中的hiredate字段)没有显性赋值,则自动设置为当前系统时间。

自动更新指的是如果修改了其它字段,则该字段的值将自动更新为当前系统时间。

设置自动修改时间:

–添加UpdateTime 设置 默认时间 CURRENT_TIMESTAMP   设置更新时间为 ON UPDATE CURRENT_TIMESTAMP 
ALTER TABLE table_name
ADD COLUMN UpdateTime datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘创建时间’ ;

TIMESTAMP(3)与 DATETIME(3)意思是保留3为毫秒数

TIMESTAMP(6)与 DATETIME(6)意思是保留6为毫秒数

PHP 毫秒时间戳

大多数网上都是这种

function msectime()
{
    list($msec, $sec) = explode(' ', microtime());
    $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    return $msectime;
}

但是,PHP `microtime`函数可以支持毫秒

`round(microtime(true)*1000)` 可以输出毫秒时间戳

vultr 选择适合的服务器

进入https://www.vultr.com/resources/faq/ 页面

搜 `speed`

查找搜索结果,How can I test Vultr download speeds?

下载对应的节点数据。哪个速度快表示那个服务器合适

elasticsearch使用bulk实现批量操作

bulk的格式: 
{action:{metadata}}\n 
{requstbody}\n (请求体)

action:(行为),包含create(文档不存在时创建)、update(更新文档)、index(创建新文档或替换已用文档)、delete(删除一个文档)。 
create和index的区别:如果数据存在,使用create操作失败,会提示文档已存在,使用index则可以成功执行。
metadata:(行为操作的具体索引信息),需要指明数据的_index、_type、_id。

批量添加

POST /lib2/books/_bulk

{"index":{"_id":1}}  \\行为:索引信息
{"title":"Java","price","55"} \\请求体
{"index":{"_id":2}}
{"title":"Html5","price","45"}
{"index":{"_id":3}}
{"title":"Php","price","35"}
{"index":{"_id":4}}
{"title":"Python","price","50"}

批量删除 
删除的批量操作不需要请求体

POST /lib/books/_bulk
{"delete":{"_index":"lib","_type":"books","_id":"4"}} //删除的批量操作不需要请求体
{"create":{"_index":"tt","_type":"ttt","_id":"100"}}
{"name":"lisi"} //请求体
{"index":{"_index":"tt","_type":"ttt"}} //没有指定_id,elasticsearch将会自动生成_id
{"name":"zhaosi"} //请求体
{"update":{"_index":"lib","_type":"books","_id":"4"}} //更新动作不能缺失_id,文档不存在更新将会失败
{"doc":{"price":58}} //请求体

bluk一次最大处理多少数据量 
bulk会将要处理的数据载入内存中,所以数据量是有限的,最佳的数据两不是一个确定的数据,它取决于你的硬件,你的文档大小以及复杂性,你的索引以及搜索的负载。

一般建议是1000-5000个文档,大小建议是5-15MB,默认不能超过100M,可以在es的配置文件(即$ES_HOME下的config下的elasticsearch.yml)中,bulk的线程池配置是内核数+1。