王某某的笔记

记录我的编程之路

Curator框架提供了一种流式接口。 操作通过builder串联起来, 这样方法调用类似语句一样。

1
2
3
4
5
client.create().forPath("/head", new byte[0]);
client.delete().inBackground().forPath("/head");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/head/child", new byte[0]);
client.getData().watched().inBackground().forPath("/test");

CuratorFramework提供的方法:

方法名 描述
create() 开始创建操作, 可以调用额外的方法(比如方式mode 或者后台执行background) 并在最后调用forPath()指定要操作的ZNode
delete() 开始删除操作. 可以调用额外的方法(版本或者后台处理version or background)并在最后调用forPath()指定要操作的ZNode
checkExists() 开始检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath()指定要操作的ZNode
getData() 开始获得ZNode节点数据的操作. 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode
setData() 开始设置ZNode节点数据的操作. 可以调用额外的方法(版本或者后台处理) 并在最后调用forPath()指定要操作的ZNode
getChildren() 开始获得ZNode的子节点列表。 以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode
inTransaction() 开始是原子ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交

后台操作的通知和监控可以通过ClientListener接口发布. 你可以在CuratorFramework实例上通过addListener()注册listener, Listener实现了下面的方法:

  • eventReceived() 一个后台操作完成或者一个监控被触发
Event Type Event Methods
CREATE getResultCode() and getPath()
DELETE getResultCode() and getPath()
EXISTS getResultCode(), getPath() and getStat()
GETDATA getResultCode(), getPath(), getStat() and getData()
SETDATA getResultCode(), getPath() and getStat()
CHILDREN getResultCode(), getPath(), getStat(), getChildren()
WATCHED getWatchedEvent()

还可以通过ConnectionStateListener接口监控连接的状态。

可以使用命名空间Namespace避免多个应用的节点的名称冲突。 CuratorFramework提供了命名空间的概念,这样CuratorFramework会为它的API调用的path加上命名空间:

1
2
3
4
CuratorFramework client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();
...
client.create().forPath("/test", data);
// node was actually written to: "/MyApp/test"

Curator还提供了临时的CuratorFramework: CuratorTempFramework, 一定时间不活动后连接会被关闭

Linux 系统目录结构

/bin:

bin是Binary的缩写, 这个目录存放着最经常使用的命令。

/boot:

这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。

/dev :

dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。

/etc:

这个目录用来存放所有的系统管理所需要的配置文件和子目录。

/home:

用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。

/lib:

这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

/lost+found:

这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。

/media:

linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。

/mnt:

系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。

/opt:

这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。

/proc:

这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。
这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:

1
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

/root:

该目录为系统管理员,也称作超级权限者的用户主目录。

/sbin:

s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。

/selinux:

这个目录是Redhat/CentOS所特有的目录,Selinux是一个安全机制,类似于windows的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。

/srv:

该目录存放一些服务启动之后需要提取的数据。

/sys:

这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs 。
sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统。
该文件系统是内核设备树的一个直观反映。
当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。

/tmp:

这个目录是用来存放一些临时文件的。

/usr:

这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似与windows下的program files目录。

/usr/bin:

系统用户使用的应用程序。

/usr/sbin:

超级用户使用的比较高级的管理程序和系统守护程序。

/usr/src:

内核源代码默认的放置目录。

/var:

这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。

升级之前请备份数据


https://dev.mysql.com/downloads/repo/yum/

https://dev.mysql.com/doc/refman/5.7/en/upgrading.html

https://dev.mysql.com/doc/refman/5.7/en/mysql-upgrade.html

更新程序

使用MySQL Yum Repository升级MySQL

https://dev.mysql.com/doc/refman/5.7/en/updating-yum-repo.html

通过yum升级

  1. 更换新的yum 资源库,或者禁用旧版本系列 启用新版本系列。

  2. 通过以下命令升级MySQL及其组件

    1
    2
    shell> sudo yum update mysql-server

    或者,通过Yum更新系统上的所有内容来更新MySQL

    1
    2
    shell> sudo yum update

  3. 查看已经安装了的

    1
    2
    shell> sudo yum list installed | grep "^mysql"

关闭旧的服务器

  1. 配置MySQL通过设置innodb_fast_shutdown来 执行缓慢的关闭 0。例如:

    1
    mysql -u root -p --execute="SET GLOBAL innodb_fast_shutdown=0"

    缓慢关闭时,InnoDB执行完全清除并在关闭之前更改缓冲区合并,从而确保数据文件在发布之间的文件格式不同的情况下完全准备好。

  2. 关闭旧的MySQL服务器。例如:

    1
    mysqladmin -u root -p shutdown

升级数据

mysql_upgrade - 检查和升级MySQL表

mysql_upgrade检查所有数据库中的所有表与当前版本的MySQL Server的不兼容性。mysql_upgrade还升级系统表,以便您可以利用可能已添加的新特权或功能。

如果mysql_upgrade发现表有可能的不兼容性,它会执行表检查,如果发现问题,则尝试进行表修复。如果表不能修复,请参见第2.11.3节“重建或修复表或索引”以获取手动表修复策略。

每次升级MySQL时,都 应该执行mysql_upgrade。

从MySQL 5.7.5开始,mysql_upgrade与MySQL服务器直接通信,发送执行升级所需的SQL语句。5.7.5之前, mysql_upgrade调用 mysql和mysqlcheck 客户端程序来执行所需的操作。对于较旧的实现,如果在Linux上从RPM软件包安装MySQL,则必须安装服务器和客户机RPM。 mysql_upgrade包含在服务器RPM中,但需要客户端RPM,因为后者包括 mysqlcheck。(请参见 第2.5.5节“使用Oracle的RPM软件包在Linux上安装MySQL”。)

要使用mysql_upgrade,请确保服务器正在运行。然后像这样调用它来检查和修复表并升级系统表:

1
2
3
4
shell> mysql_upgrade [options]

# 例如:
shell> mysql_upgrade -u root -p

运行mysql_upgrade后,停止服务器并重新启动,以便对系统表进行的任何更改生效。

1
2
mysqladmin -u root -p shutdown

使用客户端工具

1
bin/redis-cli 

测试命令

1
2
3
127.0.0.1:6379> ping
PONG

数据库

redis 可以提供16个数据库

通过select 选择,默认是0数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
1) "num"
2) "myb2"
3) "mylist2"
4) "myhash"
5) "myb1"
6) "myset"
7) "name"
8) "eclipse"
9) "myb3"
10) "name2"
11) "mya1"
12) "mylist"
13) "mya2"
14) "mysort"
15) "myahs"
16) "aa1"
17) "mya3"

清空数据库

1
flushall

基本数据

存数据

1
2
127.0.0.1:6379> set name zhangsan
OK

获取数据

1
2
127.0.0.1:6379> get name
"zhangsan"

删除数据

1
2
127.0.0.1:6379> del name
(integer) 1

查看所有的key

1
2
3
127.0.0.1:6379> keys *
1) "name2"
2) "name"

查看匹配可以

1
2
3
127.0.0.1:6379> keys a*
1) "abc"
2) "aa1"

数字递增

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> get num
"1"
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379>

如果不存在会设置初始值为0,然后+1

数字递减

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379> decr num
(integer) 1
127.0.0.1:6379> get num
"1"
127.0.0.1:6379> decr num
(integer) 0
127.0.0.1:6379> get num
"0"
127.0.0.1:6379>
127.0.0.1:6379> decr num
(integer) -1
127.0.0.1:6379> get num
"-1"

数字增加指定的值

1
2
3
4
5
127.0.0.1:6379> incrby num 5
(integer) 4
127.0.0.1:6379> incrby num 5
(integer) 9
127.0.0.1:6379>

数字减去指定的值

1
2
3
4
5
6
7
127.0.0.1:6379> decrby num 3
(integer) 6
127.0.0.1:6379> decrby num 3
(integer) 3
127.0.0.1:6379> decrby num 3
(integer) 0
127.0.0.1:6379>

拼接字符串

1
2
3
4
127.0.0.1:6379> append name laoli
(integer) 13
127.0.0.1:6379> get name
"zhangsanlaoli"

重命名KEY

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> set a1 a1
OK
127.0.0.1:6379> get a1
"a1"
127.0.0.1:6379> rename a1 aa1
OK
127.0.0.1:6379> get a1
(nil)
127.0.0.1:6379> get aa1
"a1"

设置过期时间
单位秒

1
2
3
4
5
6
7
8
127.0.0.1:6379> get abc
"abc"
127.0.0.1:6379> expire abc 10
(integer) 1
127.0.0.1:6379> get abc
"abc"
127.0.0.1:6379> get abc
(nil)

查看超时时间

1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> set abc abc
OK
127.0.0.1:6379> get abc
"abc"
127.0.0.1:6379> ttl abc
(integer) -1
127.0.0.1:6379> expire abc 100
(integer) 1
127.0.0.1:6379> ttl abc
(integer) 96
127.0.0.1:6379>

获取key存储的数据类型

1
2
3
4
5
6
127.0.0.1:6379> type abc
string
127.0.0.1:6379> type mylist
list
127.0.0.1:6379> type myset
set

Hash 类型

设值

1
2
3
4
127.0.0.1:6379> hset myhash uname zhangsan
(integer) 1
127.0.0.1:6379> hset myhash age 18
(integer) 1

设置多个值

1
2
127.0.0.1:6379> hmset myhash2 uname zhangs age 11
OK

取值

1
2
127.0.0.1:6379> hget myhash uname
"zhangsan"

一次取多个值

1
2
3
127.0.0.1:6379> hmget myhash uname age
1) "zhangsan"
2) "18"

获取全部值

1
2
3
4
5
127.0.0.1:6379> hgetall myhash
1) "uname"
2) "zhangsan"
3) "age"
4) "18"

删除一个值

1
2
3
4
127.0.0.1:6379> hdel myhash2 uname age
(integer) 2
127.0.0.1:6379> hgetall myhash2
(empty list or set)

删除不存在的

1
2
127.0.0.1:6379> hdel myhash2 uname
(integer) 0

删除整个集合

1
2
3
4
5
6
127.0.0.1:6379> hmset myhash2 uname zhangs age 21
OK
127.0.0.1:6379> del myhash2
(integer) 1
127.0.0.1:6379> hget myhash2 uname
(nil)

增加数据

1
2
3
4
5
6
127.0.0.1:6379> hget myhash age
"18"
127.0.0.1:6379> hincrby myhash age 5
(integer) 23
127.0.0.1:6379> hget myhash age
"23"

判断hash中某个键值是否存在

1
2
127.0.0.1:6379> hexists myhash uname
(integer) 1

1表示存在,0表示不存在

获取HASH中的键值对数量

1
2
3
4
5
6
7
127.0.0.1:6379> hgetall myhash
1) "uname"
2) "zhangsan"
3) "age"
4) "23"
127.0.0.1:6379> hlen myhash
(integer) 2

获取Hash中所有的key

1
2
3
127.0.0.1:6379> hkeys myhash
1) "uname"
2) "age"

获取hash中所有的值

1
2
3
127.0.0.1:6379> hvals myhash
1) "zhangsan"
2) "23"

数据结构list

ArrayList使用数组方式, LinkedList使用双向链表

从左侧向列表中添加数据

1
2
3
4
5
6
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> lpush mylist 1 2 3
(integer) 6
127.0.0.1:6379>

右侧添加

1
2
3
4
127.0.0.1:6379> rpush mylist2 a b c
(integer) 3
127.0.0.1:6379> rpush mylist2 1 2 3
(integer) 6

查看列表

1
2
3
4
5
6
7
127.0.0.1:6379> lrange mylist 0 5
1) "3"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"

后面指定范围,可以是负数,负数从后面开始

弹出列表中的元素
左侧弹出

1
2
127.0.0.1:6379> lpop mylist
"3"

右侧弹出

1
2
127.0.0.1:6379> rpop mylist2
"3"

获取列表中的元素数量

1
2
127.0.0.1:6379> llen mylist
(integer) 5

lrem 删除

lset 设置某个index 的值

插入 linsert 列表 before index value

rpoplpush 列表1 列表2 从一个队列中移除添加到另外一个队列中

数据结构set

Set不允许出现重复的元素

添加

1
2
3
4
127.0.0.1:6379> sadd myset a b c
(integer) 3
127.0.0.1:6379> sadd myset a
(integer) 0

删除

1
2
3
4
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> srem myset 1 2
(integer) 2

查看

1
2
3
4
5
127.0.0.1:6379> smembers myset
1) "a"
2) "b"
3) "c"
4) "3"

判断是否存在

1
2
3
4
127.0.0.1:6379> sismember myset a
(integer) 1
127.0.0.1:6379> sismember myset x
(integer) 0

1表示存在,0表示不存在

差集运算

1
2
3
4
5
6
127.0.0.1:6379> sadd mya1 a b c
(integer) 3
127.0.0.1:6379> sadd myb1 a c 1 2
(integer) 4
127.0.0.1:6379> sdiff mya1 myb1
1) "b"

交集运算

1
2
3
4
5
6
7
127.0.0.1:6379> sadd mya2 a b c
(integer) 3
127.0.0.1:6379> sadd myb2 a c 1 2
(integer) 4
127.0.0.1:6379> sinter mya2 myb2
1) "a"
2) "c"

并集运算

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> sadd mya3 a b c
(integer) 3
127.0.0.1:6379> sadd myb3 a c 1 2
(integer) 4
127.0.0.1:6379> sunion mya3 myb3
1) "2"
2) "a"
3) "1"
4) "c"
5) "b"

获取set中的成员数量

1
2
127.0.0.1:6379> scard myset
(integer) 4

随机返回一个

1
2
3
4
5
6
127.0.0.1:6379> srandmember myset
"b"
127.0.0.1:6379> srandmember myset
"c"
127.0.0.1:6379> srandmember myset
"a"

存储交集、并集、差集到一个新的集合中
sdiffstore sinterstore sunionstore

sorted-set

排序,有个分数

添加

1
2
3
4
5
6
127.0.0.1:6379> zadd mysort 70 zhangsan 80 lisi 90 wangwu
(integer) 3
127.0.0.1:6379> zadd mysort 100 zhangsan
(integer) 0
127.0.0.1:6379> zadd mysort 60 tom
(integer) 1

获取分数

1
2
127.0.0.1:6379> zscore mysort zhangsan
"100"

或成员数量

1
2
127.0.0.1:6379> zcard mysort
(integer) 4

删除

1
2
3
4
127.0.0.1:6379> zrem mysort tom wangwu
(integer) 2
127.0.0.1:6379> zcard mysort
(integer) 2

范围查找

1
2
3
4
5
6
7
127.0.0.1:6379> zadd mysort 85 jack 95 rose
(integer) 2
127.0.0.1:6379> zrange mysort 0 -1
1) "lisi"
2) "jack"
3) "rose"
4) "zhangsan"

显示分数

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "lisi"
2) "80"
3) "jack"
4) "85"
5) "rose"
6) "95"
7) "zhangsan"
8) "100"

从大到小

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> zrevrange mysort 0 -1 withscores
1) "zhangsan"
2) "100"
3) "rose"
4) "95"
5) "jack"
6) "85"
7) "lisi"
8) "80"

范围删除
zremrangebyrank mysort 0 4

按照分数删除
zremrangebyscore mysort 80 100

事物

开启事物
multi

提交事物
exec

回滚事物
discard




图形化客户端工具 Redis Desktop Manager 更好用

1722585790528.png

画面板 MonitorPanel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
package com.wwh.test.swing.monitor;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.swing.JPanel;

/**
* <pre>
* 有XY轴的曲线图监控面板
*
* <pre>
*
* @author 313921
* @date 2015-01-28 22:11:04
*/
public class MonitorPanel extends JPanel implements MonitorPanelModelListener {

/**
* 最合适的Y轴线条高度间距
*/
private static final int bastYAxisLineHeightInterval = 26;

/**
* X轴上默认的线与线之间的像素
*/
public static final int DEFAULT_X_AXIS_LINE_INTERVAL = 70;
/**
* 默认的当前值文本宽度
*/
private static final int defaultCurrentTextWidth = 50;

/**
* 最少的Y轴线条数量
*/
private static final int minYAxisLineCount = 3;

private static final long serialVersionUID = 1L;

/**
* 图片
*/
private BufferedImage bufferImage;

/**
* 显示当前值的文本宽度
*/
private int currentTextWidth = 50;

private MonitorPanelModel dataModel;

private SimpleDateFormat dateF = new SimpleDateFormat("HH:mm");

/**
* 是否显示最后一个值
*/
private boolean displayLastValue = true;

private boolean drawEmptyGraph = true;

private Color fontColor = Color.BLACK;

/**
* 曲线区域的背景颜色
*/
private Color graphBackgroundColor = new Color(0, 100, 0);

private Graphics2D graphics;

/**
* 曲线的颜色
*/
private Color graphLineColor = new Color(250, 0, 0);

private String graphTitle = "监控面板";

private Color gridLineColor = new Color(0, 0, 0);
/**
* 图片的高度
*/
private int imgHeight;

/**
* 图片的宽度,整个组件就是一个画上去的图片
*/
private int imgWidth;

/**
* 标题字体
*/
private Font titleFont = new Font("宋体", Font.BOLD, 14);

/**
* 标题颜色
*/
private Color titleFontColor = Color.BLACK;

/**
* 标题的高度
*/
private int titleHeight = 20;

/**
* X轴上的线与线之间的像素
*/
private int xAxisLineInterval = DEFAULT_X_AXIS_LINE_INTERVAL;

/**
* X轴上的一个与像素点的比例
*/
private double xRatio;

/**
* X轴的文本高度
*/
private int XTextHeight = 20;

/**
* Y轴上一个与像素点的比例
*/
private double yRatio;

/**
* Y轴的文本宽度
*/
private int YTextWidth = 40;

public MonitorPanel() {
this(null);
}

public MonitorPanel(MonitorPanelModel model) {
if (model == null) {
model = new MonitorPanelModel();
}
setModel(model);
updateUI();
}

/**
* <pre>
* 计算X轴的比例
* </pre>
*/
private void calcXRatio() {
Long maxXCoords = dataModel.getMaxXCoords();
if (maxXCoords == null) {
return;
}
Long minXCoords = dataModel.getMinXCoords();
if (minXCoords == null) {
return;
}
// 曲线图的宽度
int graphWidth = getGraphWidth();
if (graphWidth <= 0) {
xRatio = 0;
return;
}
long xv = maxXCoords - minXCoords;
// 得到比例
xRatio = (double) graphWidth / (double) xv;
}

/**
* <pre>
* 计算Y轴比例
* 既:值与显示区域的像素的比例
* </pre>
*/
private void calcYRatio() {
Long maxYCoords = dataModel.getMaxYCoords();
if (maxYCoords == null) {
return;
}
Long minYCoords = dataModel.getMinYCoords();
if (minYCoords == null) {
return;
}
// 计算曲线图的高度
int graphHeight = getGraphHeight();

if (graphHeight <= 0) {
yRatio = 0;
return;
}
long yd = maxYCoords - minYCoords;// Y轴
if (yd <= 0) {
yRatio = 0;
return;
}
yRatio = (double) graphHeight / (double) yd;// 得到比例
}

private void clearBufferImage() {
graphics.setBackground(getBackground());
graphics.clearRect(0, 0, imgWidth, imgHeight);
}

private void drawDefaultXAxis() {
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();
// 每隔一定的像素画一条竖线
graphics.setColor(gridLineColor);

for (int i = YTextWidth + xAxisLineInterval; i < YTextWidth + graphWidth; i += xAxisLineInterval) {
graphics.drawLine(i, titleHeight, i, titleHeight + graphHeight);
}
}

private void drawDefaultYAxis() {
// 每隔一定的像素画一条线
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();

// 画横线
graphics.setColor(gridLineColor);
for (int i = graphHeight; i - bastYAxisLineHeightInterval > 0; i -= bastYAxisLineHeightInterval) {
int yPosition = i - bastYAxisLineHeightInterval + titleHeight;
graphics.drawLine(YTextWidth, yPosition, YTextWidth + graphWidth, yPosition);
}
}

/**
* 绘制曲线
*/
private void drawGraph() {
graphics.setColor(graphLineColor);
List<Coordinate> coordinatelist = dataModel.getCoordinatelist();
int size = coordinatelist.size();
if (size < 2) {
return;
}
int[] xPoints = new int[size];
int[] yPoints = new int[size];

for (int i = 0; i < size; i++) {
xPoints[i] = getXPoint(coordinatelist.get(i).getxValue());
yPoints[i] = getYPoint(coordinatelist.get(i).getyValue());
}

graphics.drawPolyline(xPoints, yPoints, size);

// 画一个当前值
Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int descent = fm.getDescent();
graphics.setColor(fontColor);
int _yPoint = yPoints[size - 1];
int graphWidth = getGraphWidth();
int _xPoint = YTextWidth + graphWidth + 1;
long currentValue = coordinatelist.get(coordinatelist.size() - 1).getyValue();
String valueOf = String.valueOf(currentValue);
graphics.drawString(valueOf, _xPoint, _yPoint - descent);
graphics.drawLine(_xPoint, _yPoint, _xPoint + fm.stringWidth(valueOf), _yPoint);
}

/**
* <pre>
* 画背景
* </pre>
*/
private void drawGraphBackgound() {
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();

graphics.setColor(graphBackgroundColor);
// big.fill3DRect(YTextWidth, titleHeight, imgWidth - YTextWidth
// - cutlineWidth, imgHeight - titleHeight - XTextHeight, false);

// 填充指定的矩形。该矩形左边缘和右边缘分别位于 x 和 x + width - 1。上边缘和下边缘分别位于 y 和 y + height -
// 1。得到的矩形覆盖 width 像素宽乘以 height 像素高的区域。使用图形上下文的当前颜色填充该矩形。
graphics.fillRect(YTextWidth, titleHeight, graphWidth, graphHeight);

graphics.setColor(gridLineColor);
// 绘制指定矩形的边框。矩形的左边缘和右边缘分别位于 x 和 x + width。上边缘和下边缘分别位于 y 和 y +
// height。使用图形上下文的当前颜色绘制该矩形。
graphics.drawRect(YTextWidth, titleHeight, graphWidth, graphHeight);

}

/**
* <pre>
* 将内容画在图片上
* </pre>
*/
private void drawImage() {
int tw = getWidth();
int th = getHeight();
if (tw != imgWidth || th != imgHeight) {
// 大小有变化,重建一张图片
imgWidth = tw;
imgHeight = th;
bufferImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
graphics = bufferImage.createGraphics();
}
if (bufferImage == null) {
return;
}

// 先清空图片
clearBufferImage();

// 画标题
drawTitle();

// 画内容区域 背景
drawGraphBackgound();

// 获取XY轴上的线
long[] xLine = dataModel.getXAxisLines(getBestXAxisLineCount());
long[] yLine = dataModel.getYAxisLines(getBestYAxisLineCount());

// 计算X 和 Y 的比例
calcYRatio();
calcXRatio();

// 画X坐标
if (xLine != null) {
drawXAxis(xLine);
} else {
if (drawEmptyGraph) {
// 画缺省的X坐标
drawDefaultXAxis();
}
}

// 画Y坐标
if (yLine != null) {
drawYAxis(yLine);
} else if (drawEmptyGraph) {
// 画缺省的Y坐标
drawDefaultYAxis();
}

// 画曲线
drawGraph();
}

/**
* <pre>
* 画标题
* </pre>
*/
private void drawTitle() {
if (graphTitle == null || graphTitle.isEmpty() || titleHeight < 1) {
return;
}
graphics.setColor(titleFontColor);
graphics.setFont(titleFont);
FontMetrics fm = graphics.getFontMetrics(titleFont);
int titleWidth = fm.stringWidth(graphTitle);

int graphWidth = getGraphWidth();
int titleX = (graphWidth - titleWidth) / 2 + YTextWidth;
graphics.drawString(graphTitle, titleX, fm.getAscent());
}

/**
* <pre>
* 画X轴
* </pre>
*/
private void drawXAxis(long[] xLine) {
if (xLine == null) {
return;
}

Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int ascent = fm.getAscent();
// int descent = fm.getDescent();
// int fHeight = fm.getHeight();

int graphHeight = getGraphHeight();

// 画X坐标
for (long l : xLine) {
int xPoint = getXPoint(l);

graphics.setColor(gridLineColor);
graphics.drawLine(xPoint, titleHeight, xPoint, titleHeight + graphHeight);

Date date = new Date(l);
String dateStr = dateF.format(date);

graphics.setColor(fontColor);
graphics.drawString(dateStr, xPoint, titleHeight + graphHeight + ascent);

}
}

/**
* <pre>
* 画Y轴
* </pre>
*/
private void drawYAxis(long[] yLine) {
if (yLine == null) {
return;
}

Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int descent = fm.getDescent();
// 先设置字体
graphics.setFont(font);

// 画最大值
// String maxYStr = String.valueOf(maxY);
// big.drawString(maxYStr, YTextWidth - fm.stringWidth(maxYStr) - 1,
// titleHeight + descent);
// // 画最小值
// String minYStr = String.valueOf(minY);
// big.drawString(minYStr, YTextWidth - fm.stringWidth(minYStr) - 1,
// titleHeight + graphHeight);

int graphWidth = getGraphWidth();

for (long l : yLine) {
String yNumberStr = String.valueOf(l);
int yPosition = getYPoint(l);
if (YTextWidth > 0) {
// 数字
graphics.setColor(fontColor);
graphics.drawString(yNumberStr, YTextWidth - fm.stringWidth(yNumberStr) - 1, yPosition + descent);
}

// 画横线
graphics.setColor(gridLineColor);
graphics.drawLine(YTextWidth, yPosition, YTextWidth + graphWidth, yPosition);

}
}

private int getBestXAxisLineCount() {
// 在X轴能显示几条线
int lineCount = getGraphWidth() / xAxisLineInterval;
lineCount = lineCount > 1 ? lineCount : 1;
return lineCount;
}

/**
* 根据坐标系高度计算最佳的横线条数
*
* @return
*/
private int getBestYAxisLineCount() {
int lineCount = getGraphHeight() / bastYAxisLineHeightInterval;
lineCount = lineCount > minYAxisLineCount ? lineCount : minYAxisLineCount;
return lineCount;
}

public int getCurrentTextWidth() {
return currentTextWidth;
}

public boolean getDisplayLastValue() {
return displayLastValue;
}

public Color getFontColor() {
return fontColor;
}

public Color getGraphBackgroundColor() {
return graphBackgroundColor;
}

/**
* 获取曲线图区域的高度
*
* @return
*/
public int getGraphHeight() {
if (bufferImage == null) {
return 0;
}
return bufferImage.getHeight() - titleHeight - XTextHeight;
}

public Color getGraphLineColor() {
return graphLineColor;
}

public String getGraphTitle() {
return graphTitle;
}

/**
* 获取曲线图区域的宽度
*
* @return
*/
public int getGraphWidth() {
if (bufferImage == null) {
return 0;
}
return bufferImage.getWidth() - YTextWidth - currentTextWidth;
}

public Color getGridLineColor() {
return gridLineColor;
}

/**
* <pre>
* 获取值对应X点坐标
* </pre>
*
* @param value
* @return
*/
private int getXPoint(long value) {
Long minXCoords = dataModel.getMinXCoords();
long v = value - minXCoords;
int x = (int) (v * xRatio);
return x + YTextWidth;
}

/**
* <pre>
* 获取值对应Y点坐标
* </pre>
*
* @param value
* @return
*/
private int getYPoint(long value) {
Long minYCoords = dataModel.getMinYCoords();
long v = value - minYCoords;
int y = (int) (v * yRatio);
int graphHeight = getGraphHeight();
return graphHeight - y + titleHeight;
}

public boolean isDrawEmptyGraph() {
return drawEmptyGraph;
}

@Override
public void monitorPanelChanged(MonitorPanelModelEvent e) {
repaint();
}

@Override
public void paint(Graphics g) {
super.paint(g);

drawImage();
// 用图片
if (bufferImage != null) {
g.drawImage(bufferImage, 0, 0, this);
}
}

public void setCurrentTextWidth(int currentTextWidth) {
this.currentTextWidth = currentTextWidth;
}

public void setDisplayLastValue(boolean display) {
displayLastValue = display;
if (display) {
currentTextWidth = defaultCurrentTextWidth;
} else {
currentTextWidth = 0;
}
}

public void setDrawEmptyGraph(boolean drawEmptyGraph) {
this.drawEmptyGraph = drawEmptyGraph;
}

public void setFontColor(Color fontColor) {
this.fontColor = fontColor;
}

public void setGraphBackgroundColor(Color graphBackgroundColor) {
this.graphBackgroundColor = graphBackgroundColor;
}

public void setGraphLineColor(Color graphLineColor) {
this.graphLineColor = graphLineColor;
}

public void setGraphTitle(String title) {
this.graphTitle = title;
}

public void setGridLineColor(Color gridLineColor) {
this.gridLineColor = gridLineColor;
}

public void setModel(MonitorPanelModel model) {
if (model == null) {
throw new IllegalArgumentException("不能为空");
}
if (this.dataModel != model) {
MonitorPanelModel old = this.dataModel;
if (old != null) {
old.removeMonitorPanelModelListener(this);
}
this.dataModel = model;
model.addMonitorPanelModelListener(this);
repaint();
}
}

}

数据模型 MonitorPanelModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
package com.wwh.test.swing.monitor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.event.EventListenerList;

// 应该抽象出接口
public class MonitorPanelModel implements Serializable {

public enum XAxisMode {
AUTO, FIXED, KEEP_MOVE
}

public enum YAxisMode {
AUTO, FIXED
}

/**
* 默认的最大坐标点的数量1000
*/
public static final int DEFAULT_MAX_COORDINATE_NUMBER = 1000;
private static final long serialVersionUID = 1L;
/**
* 坐标集合
*/
private List<Coordinate> coordinatelist;
/**
* 使X轴呈现一个向左边移动的效果<br>
* 需要指定一个时间段
*/
private Long keepMoveTimeInterval;
private EventListenerList listenerList = new EventListenerList();
/**
* 最大的坐标点个数
*/
private int maxCoordinateCount = DEFAULT_MAX_COORDINATE_NUMBER;
/**
* 最大X坐标
*/
private Long maxXCoords;
/**
* X轴上的最大值
*/
private Long maxXValue;
/**
* 最大Y坐标
*/
private Long maxYCoords;
/**
* Y轴上的最大值
*/
private Long maxYValue;
/**
* 最小X坐标
*/
private Long minXCoords;
/**
* X轴上的最小值
*/
private Long minXValue;
/**
* 最小Y坐标
*/
private Long minYCoords;

/**
* Y轴上的最小值
*/
private Long minYValue;

/**
* 记录一个开始的时间
*/
private Long startTime;

/**
* X 轴间距
*/
private Long xAxisInterval;

private XAxisMode xAxisMode = XAxisMode.AUTO;

/**
* Y轴间距
*/
private Long yAxisInterval;

private YAxisMode yAxisMode = YAxisMode.AUTO;

public MonitorPanelModel() {
coordinatelist = new ArrayList<Coordinate>();
}

public void addCoordinate(Coordinate coordinate) {
coordinatelist.add(coordinate);
if (coordinatelist.size() > maxCoordinateCount) {
coordinatelist.remove(0);
fireMonitorPanelDataChanged();
} else {
fireMonitorPanelDataAdd(coordinate);
}
}

public void addMonitorPanelModelListener(MonitorPanelModelListener l) {
listenerList.add(MonitorPanelModelListener.class, l);
}

/**
* 根据间隔计算Y轴上的线条数量
*
* @param interval
* @return
*/
private int calcLineCountByInterval(long interval) {
// 计算Y轴的最大值
long tmp = maxYValue / interval;
maxYCoords = tmp * interval;
if (maxYCoords < maxYValue) {
maxYCoords += interval;
}

tmp = minYValue / interval;
minYCoords = tmp * interval;
if (minYCoords > minYValue) {
minYCoords -= interval;
}

long line = (maxYCoords - minYCoords) / interval;

yAxisInterval = interval;

return (int) line;
}

public void clearCoordinate() {
coordinatelist.clear();
fireMonitorPanelDataChanged();
}

private void fireMonitorPanelChanged(MonitorPanelModelEvent e) {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == MonitorPanelModelListener.class) {
((MonitorPanelModelListener) listeners[i + 1]).monitorPanelChanged(e);
}
}
}

private void fireMonitorPanelDataAdd(Coordinate coordinate) {
refreshValue(coordinate);
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}

private void fireMonitorPanelDataChanged() {
// 刷新数据
refreshAllValue();
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}

private void fireMonitorPanelPropertyChanged(String property, Object oldValue, Object newValue) {
// 属性先不管
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}

private long[] getAutoXAxisLines(int bestXLineCount) {
if (maxXValue == null || minXValue == null) {
return null;
}
long differ = maxXValue - minXValue;
if (differ == 0) {
return null;
}
minXCoords = minXValue;
maxXCoords = maxXValue;
xAxisInterval = differ / bestXLineCount;
if (xAxisInterval < 1) {
return null;
}
List<Long> l = new ArrayList<>();
long tmp = maxXCoords;
while (tmp > minXCoords) {
l.add(tmp);
tmp -= xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}

private long[] getAutoYAxisLines(int bestYLineCount) {
if (maxYValue == null || minYValue == null) {
return null;
}
long differValue = maxYValue - minYValue;
if (differValue == 0) {
// 此时可能是一条横线
yAxisInterval = 1L;
long absMaxYValue = Math.abs(maxYValue);
if (absMaxYValue > 10) {
double log = Math.log10(absMaxYValue / 10);
// 四舍五入取整
log = Math.round(log);
// 间距
yAxisInterval = (long) Math.pow(10, log);
}
maxYCoords = ((maxYValue / yAxisInterval) + 1) * yAxisInterval;
minYCoords = ((maxYValue / yAxisInterval) - 1) * yAxisInterval;
long middleValue = (maxYValue / yAxisInterval) * yAxisInterval;
return new long[] { minYCoords, middleValue, maxYCoords };
}

long interval = 1;
if (differValue > 10) {
double log = Math.log10(differValue / 10);
// 四舍五入取整
log = Math.round(log);
// 间距
interval = (long) Math.pow(10, log);
}
readjustYAxis(interval, bestYLineCount);

// 返回Y轴上的坐标线
return getFixedYAxisLines();
}

public List<Coordinate> getCoordinatelist() {
return Collections.unmodifiableList(coordinatelist);
}

public int getCoordinateSize() {
return coordinatelist.size();
}

private long[] getFixedXAxisLines() {
if (maxXCoords == null || minXCoords == null || xAxisInterval == null) {
throw new IllegalArgumentException("固定模式下,最大值、最小值、间距都不能为空");
}
List<Long> l = new ArrayList<>();
long tmp = minXCoords;
while (tmp <= maxXCoords) {
l.add(tmp);
tmp += xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}

private long[] getFixedYAxisLines() {
if (maxYCoords == null || minYCoords == null || yAxisInterval == null) {
throw new IllegalArgumentException("固定模式下,最大值、最小值、间距都不能为空");
}
List<Long> l = new ArrayList<>();
long tmp = minYCoords;
while (tmp <= maxYCoords) {
l.add(tmp);
tmp += yAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}

public Long getKeepMoveTimeInterval() {
return keepMoveTimeInterval;
}

private long[] getKeepMoveXAxisLines(int bestXLineCount) {
if (keepMoveTimeInterval == null || keepMoveTimeInterval < 1) {
throw new IllegalArgumentException("移动模式下,固定的时间段不能为空或小于1");
}
if (startTime == null) {
startTime = System.currentTimeMillis();
}
maxXCoords = System.currentTimeMillis();
minXCoords = maxXCoords - keepMoveTimeInterval;

xAxisInterval = keepMoveTimeInterval / bestXLineCount;
if (xAxisInterval < 1) {
return null;
}
List<Long> l = new ArrayList<>();
long tmp = startTime;
while (tmp <= maxXCoords) {
if (tmp >= minXCoords) {
l.add(tmp);
}
tmp += xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}

public int getMaxCoordinateCount() {
return maxCoordinateCount;
}

public Long getMaxXCoords() {
return maxXCoords;
}

public Long getMaxXValue() {
return maxXValue;
}

public Long getMaxYCoords() {
return maxYCoords;
}

public Long getMaxYValue() {
return maxYValue;
}

public Long getMinXCoords() {
return minXCoords;
}

public Long getMinXValue() {
return minXValue;
}

public Long getMinYCoords() {
return minYCoords;
}

public Long getMinYValue() {
return minYValue;
}

public MonitorPanelModelListener[] getMonitorPanelModelListeners() {
return listenerList.getListeners(MonitorPanelModelListener.class);
}

public long getXAxisFirstValue() {
if (coordinatelist.isEmpty()) {
return 0;
}
return coordinatelist.get(0).getxValue();
}

public Long getxAxisInterval() {
return xAxisInterval;
}

public long getXAxisLastValue() {
if (coordinatelist.isEmpty()) {
return 0;
}
return coordinatelist.get(coordinatelist.size() - 1).getxValue();
}

/**
* X 轴上要画的竖线
*
* @param bestXLineCount 最佳的竖线条数
* @return
*/
public long[] getXAxisLines(int bestXLineCount) {

switch (xAxisMode) {
case AUTO:
return getAutoXAxisLines(bestXLineCount);
case FIXED:
return getFixedXAxisLines();
case KEEP_MOVE:
return getKeepMoveXAxisLines(bestXLineCount);
default:
return null;
}
}

public XAxisMode getxAxisMode() {
return xAxisMode;
}

public Long getyAxisInterval() {
return yAxisInterval;
}

/**
* Y 轴上要画的横线
*
* @param bestYLineCount 最佳的横线条数
* @return
*/
public long[] getYAxisLines(int bestYLineCount) {
switch (yAxisMode) {
case AUTO:
return getAutoYAxisLines(bestYLineCount);
case FIXED:
return getFixedYAxisLines();
default:
return null;
}
}

public YAxisMode getyAxisMode() {
return yAxisMode;
}

/**
* 重新计算Y轴
*
* @param interval
*/
private void readjustYAxis(long interval, int bestYLineCount) {
// 先根据目前的间距计算一次Y轴的行数
int lineCount = calcLineCountByInterval(interval);

// 再尝试调整为最佳的
long newInterval = 0;
if (bestYLineCount > lineCount) {
// 减小间距
float f = (float) bestYLineCount / lineCount;
int p = Math.round(f);
if (p == 1) {
return;
} else {
for (int i = p; i > 1; i--) {
if (interval % i == 0) {
newInterval = interval / i;
break;
}
}
}
} else {
// 增加间距
float f = (float) lineCount / bestYLineCount;
int p = Math.round(f);
if (p == 1) {
return;
} else {
newInterval = interval * p;
}
}

if (newInterval != 0) {
// 根据调整后的间距再算一次
lineCount = calcLineCountByInterval(newInterval);
}
}

private void refreshAllValue() {
minXValue = null;
maxXValue = null;
minYValue = null;
maxYValue = null;
for (Coordinate coordinate : coordinatelist) {
refreshValue(coordinate);
}
}

private void refreshValue(Coordinate coordinate) {
long y = coordinate.getyValue();
long x = coordinate.getxValue();
if (maxYValue == null || y > maxYValue) {
maxYValue = y;
}
if (minYValue == null || y < minYValue) {
minYValue = y;
}
if (maxXValue == null || x > maxXValue) {
maxXValue = x;
}
if (minXValue == null || x < minXValue) {
minXValue = x;
}
}

public void removeMonitorPanelModelListener(MonitorPanelModelListener l) {
listenerList.remove(MonitorPanelModelListener.class, l);
}

public void setCoordinatelist(List<Coordinate> coordinatelist) {
if (coordinatelist == null) {
throw new IllegalArgumentException("不能为空");
}
this.coordinatelist = coordinatelist;
fireMonitorPanelDataChanged();
}

public void setKeepMoveTimeInterval(Long keepMoveTimeInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.keepMoveTimeInterval = keepMoveTimeInterval;
}

public void setMaxCoordinateCount(int maxCoordinateCount) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxCoordinateCount = maxCoordinateCount;
}

public void setMaxXCoords(Long maxXCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxXCoords = maxXCoords;
}

public void setMaxYCoords(Long maxYCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxYCoords = maxYCoords;
}

public void setMinXCoords(Long minXCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.minXCoords = minXCoords;
}

public void setMinYCoords(Long minYCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.minYCoords = minYCoords;
}

public void setxAxisInterval(Long xAxisInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.xAxisInterval = xAxisInterval;
}

public void setxAxisMode(XAxisMode xAxisMode) {
fireMonitorPanelPropertyChanged(null, null, null);
this.xAxisMode = xAxisMode;
}

public void setyAxisInterval(Long yAxisInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.yAxisInterval = yAxisInterval;
}

public void setyAxisMode(YAxisMode yAxisMode) {
fireMonitorPanelPropertyChanged(null, null, null);
this.yAxisMode = yAxisMode;
}

}

坐标 Coordinate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.wwh.test.swing.monitor;

/**
* <pre>
* xy坐标
* X轴 为 具体的值
* Y轴 为 时间
* </pre>
*
* @author wwh
*/
public class Coordinate {

private long xValue;
private long yValue;

public Coordinate(long x, long y) {
this.xValue = x;
this.yValue = y;
}

public long getxValue() {
return xValue;
}

public void setxValue(long xValue) {
this.xValue = xValue;
}

public long getyValue() {
return yValue;
}

public void setyValue(long yValue) {
this.yValue = yValue;
}

}

事件 MonitorPanelModelEvent

1
2
3
4
5
6
7
8
9
10
11
package com.wwh.test.swing.monitor;

public class MonitorPanelModelEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;

public MonitorPanelModelEvent(Object source) {
super(source);
}

}

监听器接口 MonitorPanelModelListener

1
2
3
4
5
6
7
package com.wwh.test.swing.monitor;

public interface MonitorPanelModelListener extends java.util.EventListener {

public void monitorPanelChanged(MonitorPanelModelEvent e);
}

测试 MonitorPanelTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
package com.wwh.test.swing.monitor;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import com.wwh.test.swing.monitor.MonitorPanelModel.XAxisMode;
import com.wwh.test.swing.monitor.MonitorPanelModel.YAxisMode;

public class MonitorPanelTest extends JFrame {

private static final long serialVersionUID = 1L;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MonitorPanelTest frame = new MonitorPanelTest();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

private JButton btn_clear1;
private JButton btn_clear2;
private JButton btn_clear3;
private JButton btn_clear4;

private JButton btn_start2;
private JButton btn_start3;
private JButton btn_start4;

private JButton btn_stop1;
private JButton btn_stop2;
private JButton btn_stop3;
private JButton btn_stop4;

private JPanel contentPane;
private MonitorPanel mPanel1;
private MonitorPanel mPanel2;
private MonitorPanel mPanel3;
private MonitorPanel mPanel4;

private MonitorPanelModel mpModel1;
private MonitorPanelModel mpModel2;
private MonitorPanelModel mpModel3;
private MonitorPanelModel mpModel4;
private JPanel panel_1;
private JPanel panel_2;
private JPanel panel_2_btn;
private JPanel panel_3;
private JPanel panel_3_btn;
private JPanel panel_4;
private JPanel panel_4_btn;
private boolean runFlag1 = false;
private boolean runFlag2 = false;
private boolean runFlag3 = false;
private boolean runFlag4 = false;

/**
* Create the frame.
*/
public MonitorPanelTest() {
setTitle("监控面板测试");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1183, 681);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new GridLayout(2, 2, 0, 0));

createMonitorPanel1();

createMonitorPanel2();

createMonitorPanel3();

createMonitorPanel4();

}

private void createMonitorPanel1() {
panel_1 = new JPanel();
contentPane.add(panel_1);
panel_1.setLayout(new BorderLayout(0, 0));
mpModel1 = new MonitorPanelModel();
mPanel1 = new MonitorPanel(mpModel1);
panel_1.add(mPanel1);

mpModel1.setMaxCoordinateCount(200);

mPanel1.setGraphTitle("0到10000之间的随机数");

JPanel panel_1_btn = new JPanel();
panel_1.add(panel_1_btn, BorderLayout.SOUTH);

JButton btn_start1 = new JButton("启 动");
btn_start1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start1();
}
});
panel_1_btn.add(btn_start1);

btn_stop1 = new JButton("停 止");
btn_stop1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag1 = false;
}
});
panel_1_btn.add(btn_stop1);

btn_clear1 = new JButton("清 空");
btn_clear1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel1.clearCoordinate();
}
});
panel_1_btn.add(btn_clear1);
}

private void createMonitorPanel2() {
panel_2 = new JPanel();
contentPane.add(panel_2);
panel_2.setLayout(new BorderLayout(0, 0));

mpModel2 = new MonitorPanelModel();
mpModel2.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel2.setKeepMoveTimeInterval(10 * 60 * 1000L);

mpModel2.setMaxCoordinateCount(600);

mPanel2 = new MonitorPanel(mpModel2);

mPanel2.setGraphTitle("内存图测试");
mPanel2.setGraphBackgroundColor(new Color(38, 38, 38));
mPanel2.setGridLineColor(new Color(0, 225, 34));
mPanel2.setGraphLineColor(Color.YELLOW);

panel_2.add(mPanel2);

panel_2_btn = new JPanel();
panel_2.add(panel_2_btn, BorderLayout.SOUTH);

btn_start2 = new JButton("启 动");
btn_start2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start2();
}
});
panel_2_btn.add(btn_start2);

btn_stop2 = new JButton("停 止");
btn_stop2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag2 = false;
}
});
panel_2_btn.add(btn_stop2);

btn_clear2 = new JButton("清 空");
btn_clear2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel2.clearCoordinate();
}
});
panel_2_btn.add(btn_clear2);
}

private void createMonitorPanel3() {
panel_3 = new JPanel();
contentPane.add(panel_3);
panel_3.setLayout(new BorderLayout(0, 0));

mpModel3 = new MonitorPanelModel();
mpModel3.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel3.setKeepMoveTimeInterval(10 * 60 * 1000L);
mpModel3.setMaxCoordinateCount(1200);

mPanel3 = new MonitorPanel(mpModel3);
mPanel3.setGraphTitle("递增递减");

panel_3.add(mPanel3, BorderLayout.CENTER);

panel_3_btn = new JPanel();
panel_3.add(panel_3_btn, BorderLayout.SOUTH);

btn_start3 = new JButton("启 动");
btn_start3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start3();
}
});
panel_3_btn.add(btn_start3);

btn_stop3 = new JButton("停 止");
btn_stop3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag3 = false;
}
});
panel_3_btn.add(btn_stop3);

btn_clear3 = new JButton("清 空");
btn_clear3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel3.clearCoordinate();
}
});
panel_3_btn.add(btn_clear3);

}

private void createMonitorPanel4() {

panel_4 = new JPanel();
contentPane.add(panel_4);
panel_4.setLayout(new BorderLayout(0, 0));

mpModel4 = new MonitorPanelModel();
mpModel4.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel4.setKeepMoveTimeInterval(360 * 1000L);

mpModel4.setMaxCoordinateCount(720);

mpModel4.setyAxisMode(YAxisMode.FIXED);
mpModel4.setMaxYCoords(100L);
mpModel4.setMinYCoords(-100L);
mpModel4.setyAxisInterval(20L);

mPanel4 = new MonitorPanel(mpModel4);
panel_4.add(mPanel4, BorderLayout.CENTER);

mPanel4.setGraphTitle("正弦函数");
mPanel4.setGraphBackgroundColor(new Color(38, 38, 38));
mPanel4.setGridLineColor(new Color(0, 225, 34));
mPanel4.setGraphLineColor(Color.YELLOW);

panel_4_btn = new JPanel();
panel_4.add(panel_4_btn, BorderLayout.SOUTH);

btn_start4 = new JButton("启 动");
btn_start4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start4();
}
});
panel_4_btn.add(btn_start4);

btn_stop4 = new JButton("停 止");
btn_stop4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag4 = false;
}
});
panel_4_btn.add(btn_stop4);

btn_clear4 = new JButton("清 空");
btn_clear4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel4.clearCoordinate();
}
});
panel_4_btn.add(btn_clear4);

}

private void start1() {
runFlag1 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int rint;
Random r = new Random();
while (runFlag1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
rint = r.nextInt(10000);
mpModel1.addCoordinate(new Coordinate(System.currentTimeMillis(), rint + 1));
}
}
});
t.start();
}

private void start2() {
if (runFlag2) {
return;
}
runFlag2 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
Runtime rt = Runtime.getRuntime();

while (runFlag2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mpModel2.addCoordinate(new Coordinate(System.currentTimeMillis(), rt.freeMemory() / 1024 / 1024));
}
}
});
t.start();
}

private void start3() {

if (runFlag3) {
return;
}
runFlag3 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
boolean b = true;
int i = 0;
while (runFlag3) {
if (b) {
if (i < 100) {
i++;
} else {
b = !b;
}
} else {
if (i > 0) {
i--;
} else {
b = !b;
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
mpModel3.addCoordinate(new Coordinate(System.currentTimeMillis(), i));
}
}
});
t.start();

}

private void start4() {
if (runFlag4) {
return;
}
runFlag4 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
double d;
long l;
while (runFlag4) {
if (i == 360) {
i = 0;
}
d = Math.sin(Math.toRadians(i));
i++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
l = (long) (d * 100);
mpModel4.addCoordinate(new Coordinate(System.currentTimeMillis(), l));
}
}
});
t.start();
}
}

查看数据文件存放位置

  1. 通过命令查看

    1
    2
    3
    show variables like '%dir%'; 

    show global variables like '%datadir%';

    datadir 指数据文件存放位置

  2. 查看配置文件

    1
    cat /etc/my.cnf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    # For advice on how to change settings please see
    # http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html

    [mysqld]
    #
    # Remove leading # and set to the amount of RAM for the most important data
    # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
    # innodb_buffer_pool_size = 128M
    #
    # Remove leading # to turn on a very important data integrity option: logging
    # changes to the binary log between backups.
    # log_bin
    #
    # Remove leading # to set options mainly useful for reporting servers.
    # The server defaults are faster for transactions and fast SELECTs.
    # Adjust sizes as needed, experiment to find the optimal values.
    # join_buffer_size = 128M
    # sort_buffer_size = 2M
    # read_rnd_buffer_size = 2M
    datadir=/var/lib/mysql
    socket=/var/lib/mysql/mysql.sock

    # Disabling symbolic-links is recommended to prevent assorted security risks
    symbolic-links=0

    # Recommended in standard MySQL setup
    sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

    [mysqld_safe]
    log-error=/var/log/mysqld.log
    pid-file=/var/run/mysqld/mysqld.pid
    ~

修改数据文件位置

  1. 停止mysql服务
    1
    service mysqld stop  
  2. 创建新的数据库存放目录
    1
    mkdir /data/mysql  
  3. 移动/复制之前存放数据库目录文件,到新的数据库存放目录位置
    1
    cp -R /var/lib/mysql/* /data/mysql/ 
  4. 修改mysql数据库目录权限
    1
    chown mysql:mysql -R /data/mysql/
  5. 修改my.cnf配置文件
    1
    2
    vi /etc/my.cnf
    datadir=/data/mysql (指定为新的数据存放目录)
  6. 启动数据库服务
    1
    service mysqld start

https://dev.mysql.com/doc/refman/5.7/en/keywords.html#

9.3关键字和保留字

关键字是在SQL中具有重要意义的词。某些关键字,如SELECT, DELETE或 BIGINT,被保留,需要用作标识符,例如表和列名特殊待遇。对于内置函数的名称也是如此。

非保留关键字作为标识符而不引用。如第9.2节“架构对象名称”中所述,如果引用了保留字,则可以将其保留为标识符:

1
2
3
mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax ...
near 'interval (begin INT, end INT)'

BEGIN并且END是关键字但不保留,因此它们用作标识符不需要引用。INTERVAL是一个保留关键字,必须引用为标识符:

1
2
mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)

例外:在限定名称中的句点后面的单词必须是一个标识符,所以即使被保留,也不需要引用它:

1
2
mysql> CREATE TABLE mydb.interval (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)

允许内置函数的名称作为标识符,但可能需要谨慎使用。例如, COUNT作为列名可以接受。但是,默认情况下,在函数名和下一个( 字符之间的函数调用中不允许有空格。该要求使分析器能够区分名称是否在函数调用中使用,也可以在非功能上下文中使用。有关识别功能名称的更多详细信息,请参见 第9.2.4节“功能名称解析和分辨率”。

下表显示了MySQL 5.7中的关键字和保留字,以及从版本到版本的单个字的更改。保留关键字标有(R)。另外,_FILENAME是保留的。

在某些时候,您可能会升级到更高版本,所以看一下未来的保留字也是一个好主意。您可以在涵盖更高版本的MySQL的手册中找到这些。标准SQL作为列或表名称禁止表中的大多数保留字(例如, GROUP)。有一些是保留的,因为MySQL需要它们并使用yacc解析器。

表9.2 MySQL中的关键字和保留字5.7

ACCESSIBLE (R) ACCOUNT[a] ACTION
ADD (R) AFTER AGAINST
AGGREGATE ALGORITHM ALL (R)
ALTER (R) ALWAYS[b] ANALYSE
ANALYZE (R) AND (R) ANY
AS (R) ASC (R) ASCII
ASENSITIVE (R) AT AUTOEXTEND_SIZE
AUTO_INCREMENT AVG AVG_ROW_LENGTH
BACKUP BEFORE (R) BEGIN
BETWEEN (R) BIGINT (R) BINARY (R)
BINLOG BIT BLOB (R)
BLOCK BOOL BOOLEAN
BOTH (R) BTREE BY (R)
BYTE CACHE CALL (R)
CASCADE (R) CASCADED CASE (R)
CATALOG_NAME CHAIN CHANGE (R)
CHANGED CHANNEL[c] CHAR (R)
CHARACTER (R) CHARSET CHECK (R)
CHECKSUM CIPHER CLASS_ORIGIN
CLIENT CLOSE COALESCE
CODE COLLATE (R) COLLATION
COLUMN (R) COLUMNS COLUMN_FORMAT
COLUMN_NAME COMMENT COMMIT
COMMITTED COMPACT COMPLETION
COMPRESSED COMPRESSION[d] CONCURRENT
CONDITION (R) CONNECTION CONSISTENT
CONSTRAINT (R) CONSTRAINT_CATALOG CONSTRAINT_NAME
CONSTRAINT_SCHEMA CONTAINS CONTEXT
CONTINUE (R) CONVERT (R) CPU
CREATE (R) CROSS (R) CUBE
CURRENT CURRENT_DATE (R) CURRENT_TIME (R)
CURRENT_TIMESTAMP (R) CURRENT_USER (R) CURSOR (R)
CURSOR_NAME DATA DATABASE (R)
DATABASES (R) DATAFILE DATE
DATETIME DAY DAY_HOUR (R)
DAY_MICROSECOND (R) DAY_MINUTE (R) DAY_SECOND (R)
DEALLOCATE DEC (R) DECIMAL (R)
DECLARE (R) DEFAULT (R) DEFAULT_AUTH
DEFINER DELAYED (R) DELAY_KEY_WRITE
DELETE (R) DESC (R) DESCRIBE (R)
DES_KEY_FILE DETERMINISTIC (R) DIAGNOSTICS
DIRECTORY DISABLE DISCARD
DISK DISTINCT (R) DISTINCTROW (R)
DIV (R) DO DOUBLE (R)
DROP (R) DUAL (R) DUMPFILE
DUPLICATE DYNAMIC EACH (R)
ELSE (R) ELSEIF (R) ENABLE
ENCLOSED (R) ENCRYPTION[e] END
ENDS ENGINE ENGINES
ENUM ERROR ERRORS
ESCAPE ESCAPED (R) EVENT
EVENTS EVERY EXCHANGE
EXECUTE EXISTS (R) EXIT (R)
EXPANSION EXPIRE EXPLAIN (R)
EXPORT EXTENDED EXTENT_SIZE
FALSE (R) FAST FAULTS
FETCH (R) FIELDS FILE
FILE_BLOCK_SIZE[f] FILTER[g] FIRST
FIXED FLOAT (R) FLOAT4 (R)
FLOAT8 (R) FLUSH FOLLOWS[h]
FOR (R) FORCE (R) FOREIGN (R)
FORMAT FOUND FROM (R)
FULL FULLTEXT (R) FUNCTION
GENERAL GENERATED[i] (R) GEOMETRY
GEOMETRYCOLLECTION GET (R) GET_FORMAT
GLOBAL GRANT (R) GRANTS
GROUP (R) GROUP_REPLICATION[j] HANDLER
HASH HAVING (R) HELP
HIGH_PRIORITY (R) HOST HOSTS
HOUR HOUR_MICROSECOND (R) HOUR_MINUTE (R)
HOUR_SECOND (R) IDENTIFIED IF (R)
IGNORE (R) IGNORE_SERVER_IDS IMPORT
IN (R) INDEX (R) INDEXES
INFILE (R) INITIAL_SIZE INNER (R)
INOUT (R) INSENSITIVE (R) INSERT (R)
INSERT_METHOD INSTALL INSTANCE[k]
INT (R) INT1 (R) INT2 (R)
INT3 (R) INT4 (R) INT8 (R)
INTEGER (R) INTERVAL (R) INTO (R)
INVOKER IO IO_AFTER_GTIDS (R)
IO_BEFORE_GTIDS (R) IO_THREAD IPC
IS (R) ISOLATION ISSUER
ITERATE (R) JOIN (R) JSON[l]
KEY (R) KEYS (R) KEY_BLOCK_SIZE
KILL (R) LANGUAGE LAST
LEADING (R) LEAVE (R) LEAVES
LEFT (R) LESS LEVEL
LIKE (R) LIMIT (R) LINEAR (R)
LINES (R) LINESTRING LIST
LOAD (R) LOCAL LOCALTIME (R)
LOCALTIMESTAMP (R) LOCK (R) LOCKS
LOGFILE LOGS LONG (R)
LONGBLOB (R) LONGTEXT (R) LOOP (R)
LOW_PRIORITY (R) MASTER MASTER_AUTO_POSITION
MASTER_BIND (R) MASTER_CONNECT_RETRY MASTER_DELAY
MASTER_HEARTBEAT_PERIOD MASTER_HOST MASTER_LOG_FILE
MASTER_LOG_POS MASTER_PASSWORD MASTER_PORT
MASTER_RETRY_COUNT MASTER_SERVER_ID MASTER_SSL
MASTER_SSL_CA MASTER_SSL_CAPATH MASTER_SSL_CERT
MASTER_SSL_CIPHER MASTER_SSL_CRL MASTER_SSL_CRLPATH
MASTER_SSL_KEY MASTER_SSL_VERIFY_SERVER_CERT (R) MASTER_TLS_VERSION[m]
MASTER_USER MATCH (R) MAXVALUE (R)
MAX_CONNECTIONS_PER_HOUR MAX_QUERIES_PER_HOUR MAX_ROWS
MAX_SIZE MAX_STATEMENT_TIME[n] MAX_UPDATES_PER_HOUR
MAX_USER_CONNECTIONS MEDIUM MEDIUMBLOB (R)
MEDIUMINT (R) MEDIUMTEXT (R) MEMORY
MERGE MESSAGE_TEXT MICROSECOND
MIDDLEINT (R) MIGRATE MINUTE
MINUTE_MICROSECOND (R) MINUTE_SECOND (R) MIN_ROWS
MOD (R) MODE MODIFIES (R)
MODIFY MONTH MULTILINESTRING
MULTIPOINT MULTIPOLYGON MUTEX
MYSQL_ERRNO NAME NAMES
NATIONAL NATURAL (R) NCHAR
NDB NDBCLUSTER NEVER[o]
NEW NEXT NO
NODEGROUP NONBLOCKING[p] NONE
NOT (R) NO_WAIT NO_WRITE_TO_BINLOG (R)
NULL (R) NUMBER NUMERIC (R)
NVARCHAR OFFSET OLD_PASSWORD[q]
ON (R) ONE ONLY
OPEN OPTIMIZE (R) OPTIMIZER_COSTS[r] (R)
OPTION (R) OPTIONALLY (R) OPTIONS
OR (R) ORDER (R) OUT (R)
OUTER (R) OUTFILE (R) OWNER
PACK_KEYS PAGE PARSER
PARSE_GCOL_EXPR[s] PARTIAL PARTITION (R)
PARTITIONING PARTITIONS PASSWORD
PHASE PLUGIN PLUGINS
PLUGIN_DIR POINT POLYGON
PORT PRECEDES[t] PRECISION (R)
PREPARE PRESERVE PREV
PRIMARY (R) PRIVILEGES PROCEDURE (R)
PROCESSLIST PROFILE PROFILES
PROXY PURGE (R) QUARTER
QUERY QUICK RANGE (R)
READ (R) READS (R) READ_ONLY
READ_WRITE (R) REAL (R) REBUILD
RECOVER REDOFILE REDO_BUFFER_SIZE
REDUNDANT REFERENCES (R) REGEXP (R)
RELAY RELAYLOG RELAY_LOG_FILE
RELAY_LOG_POS RELAY_THREAD RELEASE (R)
RELOAD REMOVE RENAME (R)
REORGANIZE REPAIR REPEAT (R)
REPEATABLE REPLACE (R) REPLICATE_DO_DB[u]
REPLICATE_DO_TABLE[v] REPLICATE_IGNORE_DB[w] REPLICATE_IGNORE_TABLE[x]
REPLICATE_REWRITE_DB[y] REPLICATE_WILD_DO_TABLE[z] REPLICATE_WILD_IGNORE_TABLE[aa]
REPLICATION REQUIRE (R) RESET
RESIGNAL (R) RESTORE RESTRICT (R)
RESUME RETURN (R) RETURNED_SQLSTATE
RETURNS REVERSE REVOKE (R)
RIGHT (R) RLIKE (R) ROLLBACK
ROLLUP ROTATE[ab] ROUTINE
ROW ROWS ROW_COUNT
ROW_FORMAT RTREE SAVEPOINT
SCHEDULE SCHEMA (R) SCHEMAS (R)
SCHEMA_NAME SECOND SECOND_MICROSECOND (R)
SECURITY SELECT (R) SENSITIVE (R)
SEPARATOR (R) SERIAL SERIALIZABLE
SERVER SESSION SET (R)
SHARE SHOW (R) SHUTDOWN
SIGNAL (R) SIGNED SIMPLE
SLAVE SLOW SMALLINT (R)
SNAPSHOT SOCKET SOME
SONAME SOUNDS SOURCE
SPATIAL (R) SPECIFIC (R) SQL (R)
SQLEXCEPTION (R) SQLSTATE (R) SQLWARNING (R)
SQL_AFTER_GTIDS SQL_AFTER_MTS_GAPS SQL_BEFORE_GTIDS
SQL_BIG_RESULT (R) SQL_BUFFER_RESULT SQL_CACHE
SQL_CALC_FOUND_ROWS (R) SQL_NO_CACHE SQL_SMALL_RESULT (R)
SQL_THREAD SQL_TSI_DAY SQL_TSI_HOUR
SQL_TSI_MINUTE SQL_TSI_MONTH SQL_TSI_QUARTER
SQL_TSI_SECOND SQL_TSI_WEEK SQL_TSI_YEAR
SSL (R) STACKED START
STARTING (R) STARTS STATS_AUTO_RECALC
STATS_PERSISTENT STATS_SAMPLE_PAGES STATUS
STOP STORAGE STORED[ac] (R)
STRAIGHT_JOIN (R) STRING SUBCLASS_ORIGIN
SUBJECT SUBPARTITION SUBPARTITIONS
SUPER SUSPEND SWAPS
SWITCHES TABLE (R) TABLES
TABLESPACE TABLE_CHECKSUM TABLE_NAME
TEMPORARY TEMPTABLE TERMINATED (R)
TEXT THAN THEN (R)
TIME TIMESTAMP TIMESTAMPADD
TIMESTAMPDIFF TINYBLOB (R) TINYINT (R)
TINYTEXT (R) TO (R) TRAILING (R)
TRANSACTION TRIGGER (R) TRIGGERS
TRUE (R) TRUNCATE TYPE
TYPES UNCOMMITTED UNDEFINED
UNDO (R) UNDOFILE UNDO_BUFFER_SIZE
UNICODE UNINSTALL UNION (R)
UNIQUE (R) UNKNOWN UNLOCK (R)
UNSIGNED (R) UNTIL UPDATE (R)
UPGRADE USAGE (R) USE (R)
USER USER_RESOURCES USE_FRM
USING (R) UTC_DATE (R) UTC_TIME (R)
UTC_TIMESTAMP (R) VALIDATION[ad] VALUE
VALUES (R) VARBINARY (R) VARCHAR (R)
VARCHARACTER (R) VARIABLES VARYING (R)
VIEW VIRTUAL[ae] (R) WAIT
WARNINGS WEEK WEIGHT_STRING
WHEN (R) WHERE (R) WHILE (R)
WITH (R) WITHOUT[af] WORK
WRAPPER WRITE (R) X509
XA XID[ag] XML
XOR (R) YEAR YEAR_MONTH (R)
ZEROFILL (R)

[a]ACCOUNT:添加在5.7.6(非保留)

[b]ALWAYS:加入5.7.6(非保留)

[c]CHANNEL:加入5.7.6(非保留)

[d]COMPRESSION:加入5.7.8(非保留)

[e]ENCRYPTION:加入5.7.11(非保留)

[f]FILE_BLOCK_SIZE:加入5.7.6(非保留)

[g]FILTER:加入5.7.3(非保留)

[h]FOLLOWS:加入5.7.2(非保留)

[i]GENERATED:加入5.7.6(保留)

[j]GROUP_REPLICATION:加入5.7.6(非保留)

[k]INSTANCE:加入5.7.11(非保留)

[l]JSON:加入5.7.8(非保留)

[m]MASTER_TLS_VERSION:加入5.7.10(非保留)

[n]MAX_STATEMENT_TIME:加入5.7.4(非保留); 在5.7.8中删除

[o]NEVER:加入5.7.4(非保留)

[p]NONBLOCKING:在5.7.6中删除

[q]OLD_PASSWORD:在5.7.5中删除

[r]OPTIMIZER_COSTS:加入5.7.5(保留)

[s]PARSE_GCOL_EXPR:加入5.7.6(保留); 在5.7.8中没有保留

[t]PRECEDES:添加在5.7.2(非保留)

[u]REPLICATE_DO_DB:添加在5.7.3(非保留)

[v]REPLICATE_DO_TABLE:添加在5.7.3(非保留)

[w]REPLICATE_IGNORE_DB:加入5.7.3(非保留)

[x]REPLICATE_IGNORE_TABLE:添加在5.7.3(非保留)

[y]REPLICATE_REWRITE_DB:添加在5.7.3(非保留)

[z]REPLICATE_WILD_DO_TABLE:添加在5.7.3(非保留)

[aa]REPLICATE_WILD_IGNORE_TABLE:添加在5.7.3(非保留)

[ab]ROTATE:添加在5.7.11(非保留)

[ac]STORED:添加在5.7.6(保留)

[ad]VALIDATION:加入5.7.5(非保留)

[ae]VIRTUAL:加入5.7.6(保留)

[af]WITHOUT:加入5.7.5(非保留)

[ag]XID:加入5.7.5(非保留)

下表显示了MySQL 5.7中添加的关键字和保留字。保留关键字标有(R)。

表9.3 MySQL中添加的关键字和保留字5.7与MySQL 5.6相比

ACCOUNT ALWAYS CHANNEL
COMPRESSION ENCRYPTION FILE_BLOCK_SIZE
FILTER FOLLOWS GENERATED (R)
GROUP_REPLICATION INSTANCE JSON
MASTER_TLS_VERSION NEVER OPTIMIZER_COSTS (R)
PARSE_GCOL_EXPR PRECEDES REPLICATE_DO_DB
REPLICATE_DO_TABLE REPLICATE_IGNORE_DB REPLICATE_IGNORE_TABLE
REPLICATE_REWRITE_DB REPLICATE_WILD_DO_TABLE REPLICATE_WILD_IGNORE_TABLE
ROTATE STACKED STORED (R)
VALIDATION VIRTUAL (R) WITHOUT
XID

下表显示了MySQL 5.7中删除的关键字和保留字。保留关键字标有(R)。

表9.4 MySQL 5.7中删除的关键字和保留字与MySQL 5.6相比

| |
—|—|—
OLD_PASSWORD| |

ES 全文搜索

1. 全文搜索

1
2
3
4
5
6
7
8
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": "BROWN DOG!"
}
}
}

使用了match查询的多词查询只是简单地将生成的term查询包含在了一个bool查询中。通过默认的or操作符,每个term查询都以一个语句被添加,所以至少一个should语句需要被匹配。以下两个查询是等价的:

1
2
3
4
5
6
7
8
9
10
11
{
"match": { "title": "brown fox"}
}
{
"bool": {
"should": [
{ "term": { "title": "brown" }},
{ "term": { "title": "fox" }}
]
}
}

2. 提高查询精度

match查询接受一个operator参数,该参数的默认值是”or”。你可以将它改变为”and”来要求所有的词条都需要被匹配:

1
2
3
4
5
6
7
8
9
10
11
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": {
"query": "BROWN DOG!",
"operator": "and"
}
}
}
}

使用and操作符时,所有的term查询都以must语句被添加,因此所有的查询都需要匹配。以下两个查询是等价的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"match": {
"title": {
"query": "brown fox",
"operator": "and"
}
}
}
{
"bool": {
"must": [
{ "term": { "title": "brown" }},
{ "term": { "title": "fox" }}
]
}
}

3. 控制查询精度

match查询支持minimum_should_match参数,它能够让你指定有多少词条必须被匹配才会让该文档被当做一个相关的文档。尽管你能够指定一个词条的绝对数量,但是通常指定一个百分比会更有意义,因为你无法控制用户会输入多少个词条:

1
2
3
4
5
6
7
8
9
10
11
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": {
"query": "quick brown dog",
"minimum_should_match": "75%"
}
}
}
}

如果指定了minimum_should_match参数,它会直接被传入到bool查询中,因此下面两个查询是等价的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "75%"
}
}
}
{
"bool": {
"should": [
{ "term": { "title": "brown" }},
{ "term": { "title": "fox" }},
{ "term": { "title": "quick" }}
],
"minimum_should_match": 2
}
}

4. 合并查询

bool查询通过must,must_not以及should参数来接受多个查询。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /my_index/my_type/_search
{
"query": {
"bool": {
"must": { "match": { "title": "quick" }},
"must_not": { "match": { "title": "lazy" }},
"should": [
{ "match": { "title": "brown" }},
{ "match": { "title": "dog" }}
]
}
}
}

5. 控制精度

正如可以控制match查询的精度,也能够通过minimum_should_match参数来控制should语句需要匹配的数量,该参数可以是一个绝对数值或者一个百分比:

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /my_index/my_type/_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "brown" }},
{ "match": { "title": "fox" }},
{ "match": { "title": "dog" }}
],
"minimum_should_match": 2
}
}
}

6. 提升查询子句(Boosting Query Clause)

假设我们需要搜索和”full-text search”相关的文档,但是我们想要给予那些提到了”Elasticsearch”或者”Lucene”的文档更多权重。更多权重的意思是,对于提到了”Elasticsearch”或者”Lucene”的文档,它们的相关度_score会更高,即它们会出现在结果列表的前面。
一个简单的bool查询能够让我们表达较为复杂的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /_search
{
"query": {
"bool": {
"must": {
"match": {
"content": {
"query": "full text search",
"operator": "and"
}
}
},
"should": [
{ "match": { "content": "Elasticsearch" }},
{ "match": { "content": "Lucene" }}
]
}
}
}

7. 多个查询字符串(Multiple Query Strings)

1
2
3
4
5
6
7
8
9
10
11
GET /_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "War and Peace" }},
{ "match": { "author": "Leo Tolstoy" }}
]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GET /_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "War and Peace" }},
{ "match": { "author": "Leo Tolstoy" }},
{ "bool": {
"should": [
{ "match": { "translator": "Constance Garnett" }},
{ "match": { "translator": "Louise Maude" }}
]
}}
]
}
}
}

8. 设置子句优先级

通过boost参数,增加字段的权重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
GET /_search
{
"query": {
"bool": {
"should": [
{ "match": {
"title": {
"query": "War and Peace",
"boost": 2
}}},
{ "match": {
"author": {
"query": "Leo Tolstoy",
"boost": 2
}}},
{ "bool": {
"should": [
{ "match": { "translator": "Constance Garnett" }},
{ "match": { "translator": "Louise Maude" }}
]
}}
]
}
}
}

9. 多字段查询

1
2
3
4
5
6
7
8
9
{
"multi_match": {
"query": "Quick brown fox",
"type": "best_fields",
"fields": [ "title", "body" ],
"tie_breaker": 0.3,
"minimum_should_match": "30%"
}
}

注意到以上的type属性为best_fields、minimum_should_match和operator参数会被传入到生成的match查询中。
在字段名中使用通配符

1
2
3
4
5
6
{
"multi_match": {
"query": "Quick brown fox",
"fields": "*_title"
}
}

提升个别字段
个别字段可以通过caret语法(^)进行提升:仅需要在字段名后添加^boost,其中的boost是一个浮点数:

1
2
3
4
5
6
{
"multi_match": {
"query": "Quick brown fox",
"fields": [ "*_title", "chapter_title^2" ]
}
}

同一个字段使用了不同的解析器的情况

1
2
3
4
5
6
7
8
9
10
GET /my_index/_search
{
"query": {
"multi_match": {
"query": "jumping rabbits",
"type": "most_fields",
"fields": [ "title", "title.std" ]
}
}
}

命令行指令

Git 全局设置

1
2
git config --global user.name "wwh"
git config --global user.email "wwh@xxxx.com"

创建新版本库

1
2
3
4
5
6
git clone http://gitlab.xxxx.com:8100/tools/demo.git
cd demo
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master

已存在的文件夹

1
2
3
4
5
6
cd existing_folder
git init
git remote add origin http://gitlab.xxxx.com:8100/tools/demo.git
git add .
git commit -m "Initial commit"
git push -u origin master

已存在的 Git 版本库

1
2
3
4
5
cd existing_repo
git remote rename origin old-origin
git remote add origin http://gitlab.xxxx.com:8100/tools/demo.git
git push -u origin --all
git push -u origin --tags

关于认证

SSH 协议

需要配置SSH 密钥
SSH 密钥用于在您的电脑和 GitLab 建立安全连接。

1、先检查本地目录中是否已经有了SSH 秘钥对

1
%userprofile%\.ssh\id_rsa.pub

2、如果没有就需要生成一个

1
2
ssh-keygen -t rsa -C "your.email@example.com" -b 4096

3、复制公钥,到 github、gitLab 中进行设置即可

配置了sshkey 还是需要输入密码的问题

检查项目的 .git/config 文件

1
2
[remote "origin"]
url = 192.168.1.91:/data/git/dap.git

修改为使用git协议:

1
2
[remote "origin"]
url = git@192.168.1.91:/data/git/dap.git

http 协议

需要记住用户名密码

1
git config --global credential.helper store

会在 ~/.gitconfig 文件下增加以下内容:

1
2
[credential]  
helper = store

查看

1
2
3
4
5
6
7
$ git config --global -l

user.name=wwh
user.email=wwh@xxxx.com
core.autocrlf=false
credential.helper=store
gui.recentrepo=E:/git/xxxx/doc

会在home文件下生成 .git-credentials 文件(如无法自动创建需要手动创建),第一次输入完之后就会记录下来

文件内容如下:

1
2
3
4
http://wwh:123456@220.231.228.87%3a8100

# 格式
# https://{username}:{password}@github.com

注意!是明文存储

Elasticsearch HTTP API

https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html

文档

Index API

添加或更新JSON文档到指定的索引

1
2
3
4
5
curl -XPUT 'http://192.168.1.213:9200/twitter/tweet/1' -d '{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'

Get API

从索引中获取JSON文档根据ID

1
2
curl -XGET 'http://192.168.1.213:9200/twitter/tweet/1'

Delete API

从索引中删除JSON文档根据ID

1
2
curl -XDELETE 'http://192.168.1.213:9200/twitter/tweet/1'

查询

请求体查询

1
2
3
4
5
6
curl -XGET 'http://192.168.1.213:9200/twitter/tweet/_search' -d '{
"query" : {
"term" : { "user" : "kimchy" }
}
}'

URI查询

1
curl -XGET 'http://192.168.1.213:9200/twitter/tweet/_search?q=user:kimchy'

Query DSL

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html#query-dsl

Elasticsearch提供了基于JSON来定义查询完整的查询DSL。查询DSL看作查询的AST,由两种类型的子句:

  • 叶查询子句

    叶查询子句寻找一个特定的值在某一特定领域,如匹配(match),期限(term)或范围(range)查询。这些查询可以自行使用。

  • 复合查询子句

    复合查询包含其他叶查询或复合的查询,并用于多个查询以逻辑方式(如 bool 或 dis_max 查询)结合,或者改变它们的行为(如 not 或 constant_score 查询)

聚合

取出现次数最多的前20个

1
2
3
4
5
6
7
8
9
10
11
12
POST http://192.168.1.91:9200/_search?search_type=count 

{
"aggs": {
"topLocation": {
"terms": {
"field": "location.raw",
"size": 20
}
}
}
}
查询结果高亮

只有针对字段查询的时候才会高亮,对 _all 进行查询时是不会高亮的。

如:

1
2
3
4
5
6
7
8
9
10
11
12
{
"query": {
"match": {
"commandReply": "USER ftpuser"
}
},
"highlight": {
"fields": {
"commandReply": {}
}
}
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
...
"frontNodeId": 0,
"routeIp": "192.168.1.1"
}
},
"highlight": {
"commandReply": [
"220 (vsFTPd 3.0.2) <em>USER</em> <em>ftpuser</em> 331 Please specify the password. PASS <em>ftpuser</em> 230 Login"
,
" successful. ### ### Login successful UserName: <em>ftpuser</em> Password: <em>ftpuser</em> ### SYST 215 UNIX Type: L8"
]
}
}

集群

Cluster Health

获取简单的集群状态

1
curl -XGET 'http://192.168.1.213:9200/_cluster/health?pretty=true'

该API还可以针对一个或多个索引执行以只获得指定索引的健康状态

1
curl -XGET 'http://192.168.1.213:9200/_cluster/health/wwh_test?pretty'

Cluster State

群集状态API允许获得整个集群的综合状态信息

1
2
3
4
5
6
curl -XGET 'http://192.168.1.213:9200/_cluster/state'
curl -XGET 'http://192.168.1.213:9200/_cluster/stats?human&pretty'

#过滤
curl -XGET 'http://localhost:9200/_cluster/state/{metrics}/{indices}'


Cat API

  • 查看主节点

http://192.168.1.213:9200/_cat/master?v

curl ‘192.168.1.213:9200/_cat/master?v’

  • 查看集群是否健康

http://192.168.1.213:9200/_cat/health?v

curl ‘192.168.1.213:9200/_cat/health?v’

  • 查看节点列表

http://192.168.1.213:9200/_cat/nodes?v

curl ‘192.168.1.213:9200/_cat/nodes?v’

  • 列出所有索引

http://192.168.1.213:9200/_cat/indices?v

curl ‘192.168.1.213:9200/_cat/indices?v’

0%