-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
622 lines (337 loc) · 130 KB
/
atom.xml
File metadata and controls
622 lines (337 loc) · 130 KB
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
618
619
620
621
622
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>He WU</title>
<subtitle>stay hungry, stay foolish, never give up</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://wuhewuhe.github.io/"/>
<updated>2021-01-31T12:02:52.757Z</updated>
<id>https://wuhewuhe.github.io/</id>
<author>
<name>WU He</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>blazor</title>
<link href="https://wuhewuhe.github.io/2021/01/31/blazor/"/>
<id>https://wuhewuhe.github.io/2021/01/31/blazor/</id>
<published>2021-01-31T12:01:45.000Z</published>
<updated>2021-01-31T12:02:52.757Z</updated>
<content type="html"><![CDATA[<p>my first time to try blazor webassemlble</p>]]></content>
<summary type="html">
<p>my first time to try blazor webassemlble</p>
</summary>
</entry>
<entry>
<title>graph</title>
<link href="https://wuhewuhe.github.io/2020/03/18/graph/"/>
<id>https://wuhewuhe.github.io/2020/03/18/graph/</id>
<published>2020-03-18T15:02:24.000Z</published>
<updated>2020-03-19T17:54:15.246Z</updated>
<summary type="html">
</summary>
</entry>
<entry>
<title>microservices</title>
<link href="https://wuhewuhe.github.io/2020/03/18/microservices/"/>
<id>https://wuhewuhe.github.io/2020/03/18/microservices/</id>
<published>2020-03-18T14:44:34.000Z</published>
<updated>2020-03-18T14:44:34.648Z</updated>
<summary type="html">
</summary>
</entry>
<entry>
<title>jackon</title>
<link href="https://wuhewuhe.github.io/2020/03/18/jackon/"/>
<id>https://wuhewuhe.github.io/2020/03/18/jackon/</id>
<published>2020-03-18T14:44:16.000Z</published>
<updated>2020-03-18T14:44:16.698Z</updated>
<summary type="html">
</summary>
</entry>
<entry>
<title>ASCII, UNICODE, UTF-8来龙去脉</title>
<link href="https://wuhewuhe.github.io/2020/03/10/asciiHistory/"/>
<id>https://wuhewuhe.github.io/2020/03/10/asciiHistory/</id>
<published>2020-03-10T22:02:15.000Z</published>
<updated>2020-03-10T22:05:46.087Z</updated>
<content type="html"><![CDATA[<p>将人在键盘上敲入的字符(数字、字母、特殊符号等)转换成机器能够识别的二进制数,并且每个字符唯一确定一个ASCII码,形象地说,它就是人跟计算机交流时使用的键盘语言通过“翻译”转换成的计算机能够识别的语言。</p><p><strong>ASCII 码</strong><br>我们知道,计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。</p><p>上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。</p><p>ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0。</p><p><strong>非 ASCII 编码</strong><br>英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用 ASCII 码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。</p><p>但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0–127表示的符号是一样的,不一样的只是128–255的这一段。</p><p>至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是 GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示 256 x 256 = 65536 个符号。</p><p>中文编码的问题需要专文讨论,这篇笔记不涉及。这里只指出,虽然都是用多个字节表示一个符号,但是GB类的汉字编码与后文的 Unicode 和 UTF-8 是毫无关系的。</p><p><strong>Unicode</strong><br>正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。</p><p>可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。</p><p>Unicode 当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字严。具体的符号对应表,<a href="http://xn--unicode-hc5kp88abk4csz4e.org" target="_blank" rel="noopener">可以查询unicode.org</a>,或者专门的汉字对应表。</p><p><strong>Unicode 的问题</strong><br>需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。</p><p>比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。</p><p>这里就有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。</p><p>它们造成的结果是:1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。2)Unicode 在很长一段时间内无法推广,直到互联网的出现。</p><p><strong>UTF-8</strong><br>互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。</p><p>UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。</p><p>UTF-8 的编码规则很简单,只有二条:</p><p>1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。</p><p>2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。</p><p>下表总结了编码规则,字母x表示可用编码的位。</p><p>Unicode符号范围 | UTF-8编码方式<br>(十六进制) | (二进制)<br>----------------------±--------------------------------------------<br>0000 0000-0000 007F | 0xxxxxxx<br>0000 0080-0000 07FF | 110xxxxx 10xxxxxx<br>0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx<br>0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx<br>跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。</p><p>下面,还是以汉字严为例,演示如何实现 UTF-8 编码。</p><p>严的 Unicode 是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此严的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,严的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5。</p>]]></content>
<summary type="html">
<p>将人在键盘上敲入的字符(数字、字母、特殊符号等)转换成机器能够识别的二进制数,并且每个字符唯一确定一个ASCII码,形象地说,它就是人跟计算机交流时使用的键盘语言通过“翻译”转换成的计算机能够识别的语言。</p>
<p><strong>ASCII 码</strong><br
</summary>
<category term="ASCII" scheme="https://wuhewuhe.github.io/categories/ASCII/"/>
<category term="UNICODE" scheme="https://wuhewuhe.github.io/categories/ASCII/UNICODE/"/>
<category term="UTF-8" scheme="https://wuhewuhe.github.io/categories/ASCII/UNICODE/UTF-8/"/>
</entry>
<entry>
<title>制表符</title>
<link href="https://wuhewuhe.github.io/2020/03/10/tabAndVertical/"/>
<id>https://wuhewuhe.github.io/2020/03/10/tabAndVertical/</id>
<published>2020-03-10T21:44:46.000Z</published>
<updated>2020-03-10T21:46:14.733Z</updated>
<content type="html"><![CDATA[<p>HT (Horizontal Tab)水平制表符<br>VT (Vertical Tab)垂直制表符</p><p>水平制表符(‘\t’)</p><pre><code> 相信大家对‘\t’还是比较熟悉的。一般来说,其在终端和文件中的输出显示相当于按下键盘TAB键效果。一般系统中,显示水平制表符将占8列。同时水平制表符开始占据的初始位</code></pre><p>置是第8*n列(第一列的下标为0)。例如:</p><pre><code> puts("0123456\txx"); puts("0123456t\txx");</code></pre><p>在终端的输出为<img src="https://pic2.zhimg.com/50/v2-183e3f5127e5f5445085b7161f6632ca_hd.jpg" data-rawwidth="332" data-rawheight="45" class="content_image" width="332"><br>垂直制表符(‘\v’)</p><pre><code> 垂直制表符不常用。它的作用是让‘\v’后面的字符从下一行开始输出,且开始的列数为“\v”前一个字符所在列后面一列。例如: puts("01\v2345");</code></pre><p>在终端输出为<img src="https://pic4.zhimg.com/50/v2-f77575ddf7648e9307d577a83fca041f_hd.jpg" data-rawwidth="265" data-rawheight="45" class="content_image" width="265"></p>]]></content>
<summary type="html">
<p>HT (Horizontal Tab) 水平制表符<br>
VT (Vertical Tab) 垂直制表符</p>
<p>水平制表符(‘\t’)</p>
<pre><code> 相信大家对‘\t’还是比较熟悉的。一般来说,其在终端和文件中的输出显示相当于按下键盘TAB键
</summary>
<category term="ASCII" scheme="https://wuhewuhe.github.io/categories/ASCII/"/>
<category term="vertical" scheme="https://wuhewuhe.github.io/tags/vertical/"/>
<category term="horizontal" scheme="https://wuhewuhe.github.io/tags/horizontal/"/>
</entry>
<entry>
<title>换行与回车</title>
<link href="https://wuhewuhe.github.io/2020/03/10/carriagereturn/"/>
<id>https://wuhewuhe.github.io/2020/03/10/carriagereturn/</id>
<published>2020-03-10T21:38:53.000Z</published>
<updated>2020-03-10T21:52:02.998Z</updated>
<content type="html"><![CDATA[<p>会车英语carriage return, 法语 retour chariot</p><p>换行英语new line or feed line,法语 ligne d’alimentaion</p><p>关于换行和回车其实平时我们不太在意,所以关于两者的区别也不太清楚,在平时开发时可能会遇到一些文件处理的问题,放到不同的操作系统上出现各种坑。那么回车和换行到底有哪些区别呢?今天咱们就来总结一下。</p><h3 id="1-由来">1. 由来</h3><p>在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的机械打字机,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。</p><p>于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界,不卷动滚筒;另一个叫做“换行”,告诉打字机把滚筒卷一格,不改变水平位置。</p><p>这就是“换行”和“回车”的由来。</p><h3 id="2-使用">2. 使用</h3><p>后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。</p><p>回车 \r 本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即Carriage Return</p><p>换行 \n 本义是光标往下一行(不一定到下一行行首),n的英文newline,控制字符可以写成LF,即Line Feed</p><p>符号 ASCII码 意义</p><p>\n 10 换行NL</p><p>\r 13 回车CR</p><p>在不同的操作系统这几个字符表现不同,比如在WIN系统下,这两个字符就是表现的本义,在UNIX类系统,换行\n就表现为光标下一行并回到行首,在MAC上,\r就表现为回到本行开头并往下一行,至于ENTER键的定义是与操作系统有关的。通常用的Enter是两个加起来。</p><p>不同操作系统下的含义:</p><p>\n: UNIX 系统行末结束符</p><p>\r\n: window 系统行末结束符</p><p>\r: MAC OS 系统行末结束符</p><p>我们经常遇到的一个问题就是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。</p><h3 id="3-软回车和硬回车">3. 软回车和硬回车</h3><p>再扩展一下回车的一些知识。</p><p>硬回车就是普通我们按回车产生的,它在换行的同时也起着段落分隔的作用。</p><p>软回车是用 Shift + Enter 产生的,它换行,但是并不换段,即前后两段文字在 Word 中属于同一“段”。在应用格式时你会体会到这一点。</p><p>软回车能使前后两行的行间距大幅度缩小,因为它不是段落标记,要和法定的段落标记——硬回车区别出来。硬回车的html代码是</p><p>…</p>,段落的内容就夹在里面,而软回车的代码很精悍:<br>。网页的文字如果复制到word中,则硬回车变为弯曲的箭头,软回车变为向下的箭头。<p></p>]]></content>
<summary type="html">
<p>会车英语carriage return, 法语 retour chariot</p>
<p>换行英语new line or feed line,法语 ligne d’alimentaion</p>
<p>关于换行和回车其实平时我们不太在意,所以关于两者的区别也不太清楚,在平
</summary>
<category term="OS" scheme="https://wuhewuhe.github.io/categories/OS/"/>
<category term="ASCII" scheme="https://wuhewuhe.github.io/categories/OS/ASCII/"/>
<category term="carriageReturn" scheme="https://wuhewuhe.github.io/tags/carriageReturn/"/>
<category term="newLine" scheme="https://wuhewuhe.github.io/tags/newLine/"/>
</entry>
<entry>
<title>ASCII表</title>
<link href="https://wuhewuhe.github.io/2020/03/10/ascii/"/>
<id>https://wuhewuhe.github.io/2020/03/10/ascii/</id>
<published>2020-03-10T21:33:50.000Z</published>
<updated>2020-03-10T21:54:01.451Z</updated>
<content type="html"><![CDATA[<p>ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。</p><p>ASCII 规范于 1967 年第一次发布,最后一次更新是在 1986 年,它包含了 33 个控制字符(具有某些特殊功能但是无法显示的字符)和 95 个可显示字符。</p><p>ASCII 码对照表<br>二进制十进制十六进制缩写/字符解释<br>00000000000NUL (NULL)空字符<br>00000001101SOH (Start Of Headling)标题开始<br>00000010202STX (Start Of Text)正文开始<br>00000011303ETX (End Of Text)正文结束<br>00000100404EOT (End Of Transmission)传输结束<br>00000101505ENQ (Enquiry)请求<br>00000110606ACK (Acknowledge)回应/响应/收到通知<br>00000111707BEL (Bell)响铃<br>00001000808BS (Backspace)退格<br>00001001909HT (Horizontal Tab)水平制表符<br>00001010100ALF/NL(Line Feed/New Line)换行键<br>00001011110BVT (Vertical Tab)垂直制表符<br>00001100120CFF/NP (Form Feed/New Page)换页键<br>00001101130DCR (Carriage Return)回车键<br>00001110140ESO (Shift Out)不用切换<br>00001111150FSI (Shift In)启用切换<br>000100001610DLE (Data Link Escape)数据链路转义<br>000100011711DC1/XON (Device Control 1/Transmission On)设备控制1/传输开始<br>000100101812DC2 (Device Control 2)设备控制2<br>000100111913DC3/XOFF (Device Control 3/Transmission Off)设备控制3/传输中断<br>000101002014DC4 (Device Control 4)设备控制4<br>000101012115NAK (Negative Acknowledge)无响应/非正常响应/拒绝接收<br>000101102216SYN (Synchronous Idle)同步空闲<br>000101112317ETB (End of Transmission Block)传输块结束/块传输终止<br>000110002418CAN (Cancel)取消<br>000110012519EM (End of Medium)已到介质末端/介质存储已满/介质中断<br>00011010261ASUB (Substitute)替补/替换<br>00011011271BESC (Escape)逃离/取消<br>00011100281CFS (File Separator)文件分割符<br>00011101291DGS (Group Separator)组分隔符/分组符<br>00011110301ERS (Record Separator)记录分离符<br>00011111311FUS (Unit Separator)单元分隔符<br>001000003220(Space)空格<br>001000013321!<br>001000103422"<br>001000113523#<br>001001003624$<br>001001013725%<br>001001103826&<br>001001113927’<br>001010004028(<br>001010014129)<br>00101010422A*<br>00101011432B+<br>00101100442C, <br>00101101452D-<br>00101110462E.<br>00101111472F/<br>0011000048300<br>0011000149311<br>0011001050322<br>0011001151333<br>0011010052344<br>0011010153355<br>0011011054366<br>0011011155377<br>0011100056388<br>0011100157399<br>00111010583A:<br>00111011593B; <br>00111100603C<<br>00111101613D=<br>00111110623E><br>00111111633F?<br>010000006440@<br>010000016541A<br>010000106642B<br>010000116743C<br>010001006844D<br>010001016945E<br>010001107046F<br>010001117147G<br>010010007248H<br>010010017349I<br>01001010744AJ<br>01001011754BK<br>01001100764CL<br>01001101774DM<br>01001110784EN<br>01001111794FO<br>010100008050P<br>010100018151Q<br>010100108252R<br>010100118353S<br>010101008454T<br>010101018555U<br>010101108656V<br>010101118757W<br>010110008858X<br>010110018959Y<br>01011010905AZ<br>01011011915B[<br>01011100925C\<br>01011101935D]<br>01011110945E^<br>01011111955F_<br>011000009660`<br>011000019761a<br>011000109862b<br>011000119963c<br>0110010010064d<br>0110010110165e<br>0110011010266f<br>0110011110367g<br>0110100010468h<br>0110100110569i<br>011010101066Aj<br>011010111076Bk<br>011011001086Cl<br>011011011096Dm<br>011011101106En<br>011011111116Fo<br>0111000011270p<br>0111000111371q<br>0111001011472r<br>0111001111573s<br>0111010011674t<br>0111010111775u<br>0111011011876v<br>0111011111977w<br>0111100012078x<br>0111100112179y<br>011110101227Az<br>011110111237B{<br>011111001247C|<br>011111011257D}<br>011111101267E~<br>011111111277FDEL (Delete)删除<br>对控制字符的解释<br>ASCII 编码中第 0~31 个字符(开头的 32 个字符)以及第 127 个字符(最后一个字符)都是不可见的(无法显示),但是它们都具有一些特殊功能,所以称为控制字符( Control Character)或者功能码(Function Code)。</p><p>这 33 个控制字符大都与通信、数据存储以及老式设备有关,有些在现代电脑中的含义已经改变了。</p><p>但是作为一个开发人员,需要我们对ASCII有个烂熟于心的了解,比如从48-57对应数字0-9,65-92对应大写字母A-Z,95-122对应小写字母a-z</p><p>下面列出了部分控制字符的具体功能:<br>NUL (0)<br>NULL,空字符。空字符起初本意可以看作为 NOP(中文意为空操作,就是啥都不做的意思),此位置可以忽略一个字符。</p><p>之所以有这个空字符,主要是用于计算机早期的记录信息的纸带,此处留个 NUL 字符,意思是先占这个位置,以待后用,比如你哪天想起来了,在这个位置在放一个别的啥字符之类的。</p><p>后来呢,NUL 被用于C语言中,表示字符串的结束,当一个字符串中间出现 NUL 时,就意味着这个是一个字符串的结尾了。这样就方便按照自己需求去定义字符串,多长都行,当然只要你内存放得下,然后最后加一个\0,即空字符,意思是当前字符串到此结束。<br>SOH (1)<br>Start Of Heading,标题开始。如果信息沟通交流主要以命令和消息的形式的话,SOH 就可以用于标记每个消息的开始。</p><p>1963年,最开始 ASCII 标准中,把此字符定义为 Start of Message,后来又改为现在的 Start Of Heading。</p><p>现在,这个 SOH 常见于主从(master-slave)模式的 RS232 的通信中,一个主设备,以 SOH 开头,和从设备进行通信。这样方便从设备在数据传输出现错误的时候,在下一次通信之前,去实现重新同步(resynchronize)。如果没有一个清晰的类似于 SOH 这样的标记,去标记每个命令的起始或开头的话,那么重新同步,就很难实现了。<br>STX (2) 和 ETX (3)<br>STX 表示 Start Of Text,意思是“文本开始”;ETX 表示 End Of Text,意思是“文本结束”。</p><p>通过某种通讯协议去传输的一个数据(包),称为一帧的话,常会包含一个帧头,包含了寻址信息,即你是要发给谁,要发送到目的地是哪里,其后跟着真正要发送的数据内容。</p><p>而 STX,就用于标记这个数据内容的开始。接下来是要传输的数据,最后是 ETX,表明数据的结束。</p><p>而中间具体传输的数据内容,ASCII 并没有去定义,它和你所用的传输协议有关。<br>帧头数据或文本内容<br>SOH(表明帧头开始)… (帧头信息,比如包含了目的地址,表明你发送给谁等等)STX(表明数据开始)… (真正要传输的数据)ETX(表明数据结束<br>BEL (7)<br>BELl,响铃。在 ASCII 编码中,BEL 是个比较有意思的东西。BEL 用一个可以听得见的声音来吸引人们的注意,既可以用于计算机,也可以用于周边设备(比如打印机)。</p><p>注意,BEL 不是声卡或者喇叭发出的声音,而是蜂鸣器发出的声音,主要用于报警,比如硬件出现故障时就会听到这个声音,有的计算机操作系统正常启动也会听到这个声音。蜂鸣器没有直接安装到主板上,而是需要连接到主板上的一种外设,现代很多计算机都不安装蜂鸣器了,即使输出 BEL 也听不到声音,这个时候 BEL 就没有任何作用了。<br>BS (8)<br>BackSpace,退格键。退格键的功能,随着时间变化,意义也变得不同了。</p><p>退格键起初的意思是,在打印机和电传打字机上,往回移动一格光标,以起到强调该字符的作用。比如你想要打印一个 a,然后加上退格键后,就成了 aBS^。在机械类打字机上,此方法能够起到实际的强调字符的作用,但是对于后来的 CTR 下时期来说,就无法起到对应效果了。</p><p>而现代所用的退格键,不仅仅表示光标往回移动了一格,同时也删除了移动后该位置的字符。<br>HT (9)<br>Horizontal Tab,水平制表符,相当于 Table/Tab 键。</p><p>水平制表符的作用是用于布局,它控制输出设备前进到下一个表格去处理。而制表符 Table/Tab 的宽度也是灵活不固定的,只不过在多数设备上制表符 Tab 都预定义为 4 个空格的宽度。</p><p>水平制表符 HT 不仅能减少数据输入者的工作量,对于格式化好的文字来说,还能够减少存储空间,因为一个Tab键,就代替了 4 个空格。<br>LF (10)<br>Line Feed,直译为“给打印机等喂一行”,也就是“换行”的意思。LF 是 ASCII 编码中常被误用的字符之一。</p><p>LF 的最原始的含义是,移动打印机的头到下一行。而另外一个 ASCII 字符,CR(Carriage Return)才是将打印机的头移到最左边,即一行的开始(行首)。很多串口协议和 MS-DOS 及 Windows 操作系统,也都是这么实现的。</p><p>而C语言和 Unix 操作系统将 LF 的含义重新定义为“新行”,即 LF 和 CR 的组合效果,也就是回车且换行的意思。</p><p>从程序的角度出发,C语言和 Unix 对 LF 的定义显得更加自然,而 MS-DOS 的实现更接近于 LF 的本意。</p><p>现在人们常将 LF 用做“新行(newline)”的功能,大多数文本编辑软件也都可以处理单个 LF 或者 CR/LF 的组合了。<br>VT (11)<br>Vertical Tab,垂直制表符。它类似于水平制表符 Tab,目的是为了减少布局中的工作,同时也减少了格式化字符时所需要存储字符的空间。VT 控制符用于跳到下一个标记行。</p><p>说实话,还真没看到有些地方需要用 VT,因为一般在换行的时候都是用 LF 代替 VT 了。<br>FF (12)<br>Form Feed,换页。设计换页键,是用来控制打印机行为的。当打印机收到此键码的时候,打印机移动到下一页。</p><p>不同的设备的终端对此控制符所表现的行为各不同,有些会清除屏幕,有些只是显示^L字符,有些只是新换一行而已。例如,Unix/Linux 下的 Bash Shell 和 Tcsh 就把 FF 看做是一个清空屏幕的命令。<br>CR (13)<br>Carriage return,回车,表示机器的滑动部分(或者底座)返回。</p><p>CR 回车的原意是让打印头回到左边界,并没有移动到下一行的意思。随着时间的流逝,后来人们把 CR 的意思弄成了 Enter 键,用于示意输入完毕。</p><p>在数据以屏幕显示的情况下,人们按下 Enter 的同时,也希望把光标移动到下一行,因此C语言和 Unix 重新定义了 CR 的含义,将其表示为移动到下一行。当输入 CR 时,系统也常常隐式地将其转换为LF。<br>SO (14) 和 SI (15)<br>SO,Shift Out,不用切换;SI,Shift In,启用切换。</p><p>早在 1960s 年代,设计 ASCII 编码的美国人就已经想到了,ASCII 编码不仅仅能用于英文,也要能用于外文字符集,这很重要,定义 Shift In 和 Shift Out 正是考虑到了这点。</p><p>最开始,其意为在西里尔语和拉丁语之间切换。西里尔语 ASCII(也即 KOI-7 编码)将 Shift 作为一个普通字符,而拉丁语 ASCII(也就是我们通常所说的 ASCII)用 Shift 去改变打印机的字体,它们完全是两种含义。</p><p>在拉丁语 ASCII 中,SO 用于产生双倍宽度的字符(类似于全角),而用 SI 打印压缩的字体(类似于半角)。<br>DLE (16)<br>Data Link Escape,数据链路转义。</p><p>有时候我们需要在通信过程中发送一些控制字符,但是总有一些情况下,这些控制字符被看成了普通的数据流,而没有起到对应的控制效果,ASCII 编码引入 DLE 来解决这类问题。</p><p>如果数据流中检测到了 DLE,数据接收端会对数据流中接下来的字符另作处理。但是具体如何处理,ASCII 规范中并没有定义,只是弄了个 DLE 去打断正常的数据流,告诉接下来的数据要特殊对待。<br>DC1 (17)<br>Device Control 1,或者 XON – Transmission on。</p><p>这个 ASCII 控制符尽管原先定义为 DC1, 但是现在常表示为 XON,用于串行通信中的软件流控制。其主要作用为,在通信被控制符 XOFF 中断之后,重新开始信息传输。</p><p>用过串行终端的人应该还记得,当有时候数据出错了,按 Ctrl+Q(等价于XON)有时候可以起到重新传输的效果。这是因为,此 Ctrl+Q 键盘序列实际上就是产生 XON 控制符,它可以将那些由于终端或者主机方面,由于偶尔出现的错误的 XOFF 控制符而中断的通信解锁,使其正常通信。<br>DC3 (19)<br>Device Control 3,或者 XOFF(Transmission off,传输中断)。<br>EM (25)<br>End of Medium,已到介质末端,介质存储已满。</p><p>EM 用于,当数据存储到达串行存储介质末尾的时候,就像磁带或磁头滚动到介质末尾一样。其用于表述数据的逻辑终点,即不必非要是物理上的达到数据载体的末尾。<br>FS(28)<br>File Separator,文件分隔符。FS 是个很有意思的控制字符,它可以让我们看到 1960s 年代的计算机是如何组织的。</p><p>我们现在习惯于随机访问一些存储介质,比如 RAM、磁盘等,但是在设计 ASCII 编码的那个年代,大部分数据还是顺序的、串行的,而不是随机访问的。此处所说的串行,不仅仅指的是串行通信,还指的是顺序存储介质,比如穿孔卡片、纸带、磁带等。</p><p>在串行通信的时代,设计这么一个用于表示文件分隔的控制字符,用于分割两个单独的文件,是一件很明智的事情。<br>GS(29)<br>Group Separator,分组符。</p><p>ASCII 定义控制字符的原因之一就是考虑到了数据存储。</p><p>大部分情况下,数据库的建立都和表有关,表包含了多条记录。同一个表中的所有记录属于同一类型,不同的表中的记录属于不同的类型。</p><p>而分组符 GS 就是用来分隔串行数据存储系统中的不同的组。值得注意的是,当时还没有使用 Excel 表格,ASCII 时代的人把它叫做组。<br>RS(30)<br>Record Separator,记录分隔符,用于分隔一个组或表中的多条记录。<br>US(31)<br>Unit Separator,单元分隔符。</p><p>在 ASCII 定义中,数据库中所存储的最小的数据项叫做单元(Unit)。而现在我们称其字段(Field)。单元分隔符 US 用于分割串行数据存储环境下的不同单元。</p><p>现在的数据库实现都要求大部分类型都拥有固定的长度,尽管有时候可能用不到,但是对于每一个字段,却都要分配足够大的空间,用于存放最大可能的数据。</p><p>这种做法的弊端就是占用了大量的存储空间,而 US 控制符允许字段具有可变的长度。在 1960s 年代,数据存储空间很有限,用 US 将不同单元分隔开,能节省很多空间。<br>DEL (127)<br>Delete,删除。</p><p>有人也许会问,为何 ASCII 编码中其它控制字符的值都很小(即 0~31),而 DEL 的值却很大呢(为 127)?</p><p>这是由于这个特殊的字符是为纸带而定义的。在那个年代,绝大多数的纸带都是用7个孔洞去编码数据的。而 127 这个值所对应的二进制值为111 1111(所有 7 个比特位都是1),将 DEL 用在现存的纸带上时,所有的洞就都被穿孔了,就把已经存在的数据都擦除掉了,就起到了删除的作用</p>]]></content>
<summary type="html">
<p>ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。</p>
<p>A
</summary>
<category term="ASCII" scheme="https://wuhewuhe.github.io/categories/ASCII/"/>
<category term="nul" scheme="https://wuhewuhe.github.io/tags/nul/"/>
<category term="soh" scheme="https://wuhewuhe.github.io/tags/soh/"/>
<category term="stx" scheme="https://wuhewuhe.github.io/tags/stx/"/>
<category term="tex" scheme="https://wuhewuhe.github.io/tags/tex/"/>
</entry>
<entry>
<title>hiberntae Cache</title>
<link href="https://wuhewuhe.github.io/2020/03/04/hiberntaeCache/"/>
<id>https://wuhewuhe.github.io/2020/03/04/hiberntaeCache/</id>
<published>2020-03-04T05:44:52.000Z</published>
<updated>2020-03-04T05:45:41.740Z</updated>
<content type="html"><![CDATA[<p>Caching is a mechanism to enhance the performance of a system. It is a buffer memorythat lies between the application and the database. Cache memory stores recently used data items in order to reduce the number of database hits as much as possible.</p><p>Caching is important to Hibernate as well. It utilizes a multilevel caching scheme as explained below</p><p><img src="https://www.tutorialspoint.com/hibernate/images/hibernate_cache.jpg" alt="Hibernate Caching"></p><h2 id="First-level-Cache">First-level Cache</h2><p>The first-level cache is the Session cache and is a mandatory cache through which all requests must pass. The Session object keeps an object under its own power before committing it to the database.</p><p>If you issue multiple updates to an object, Hibernate tries to delay doing the update as long as possible to reduce the number of update SQL statements issued. If you close the session, all the objects being cached are lost and either persisted or updated in the database.</p><h2 id="Second-level-Cache">Second-level Cache</h2><p>Second level cache is an optional cache and first-level cache will always be consulted before any attempt is made to locate an object in the second-level cache. The second level cache can be configured on a per-class and per-collection basis and mainly responsible for caching objects across sessions.</p><p>Any third-party cache can be used with Hibernate. An <strong>org.hibernate.cache. CacheProvider</strong> interface is provided, which must be implemented to provide Hibernate with a handle to the cache implementation.</p><h2 id="Query-level-Cache">Query-level Cache</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><property name = "hibernate.cache.region.factory_calss">org</property></span><br><span class="line"></span><br><span class="line">hbm.cfg.xml</span><br><span class="line">basic connect information </span><br><span class="line">dialect show_sql format ddl2auto jdbc.batch_size second_level_cache</span><br><span class="line">mapping entity</span><br><span class="line">class cache</span><br></pre></td></tr></table></figure><p>Hibernate also implements a cache for query resultsets that integrates closely with the second-level cache.</p><p>This is an optional feature and requires two additional physical cache regions that hold the cached query results and the timestamps when a table was last updated. This is only useful for queries that are run frequently with the same parameters.</p><h2 id="The-Second-Level-Cache">The Second Level Cache</h2><p>Hibernate uses first-level cache by default and you have nothing to do to use first-level cache. Let’s go straight to the optional second-level cache. Not all classes benefit from caching, so it’s important to be able to disable the second-level cache.</p><p>The Hibernate second-level cache is set up in two steps. First, you have to decide which concurrency strategy to use. After that, you configure cache expiration and physical cache attributes using the cache provider.</p><h2 id="Concurrency-Strategies">Concurrency Strategies</h2><p>A concurrency strategy is a mediator, which is responsible for storing items of data in the cache and retrieving them from the cache. If you are going to enable a second-level cache, you will have to decide, for each persistent class and collection, which cache concurrency strategy to use.</p><ul><li><strong>Transactional</strong> − Use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions, in the rare case of an update.</li><li><strong>Read-write</strong> − Again use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions, in the rare case of an update.</li><li><strong>Nonstrict-read-write</strong> − This strategy makes no guarantee of consistency between the cache and the database. Use this strategy if data hardly ever changes and a small likelihood of stale data is not of critical concern.</li><li><strong>Read-only</strong> − A concurrency strategy suitable for data, which never changes. Use it for reference data only.</li></ul><p>If we are going to use second-level caching for our <strong>Employee</strong> class, let us add the mapping element required to tell Hibernate to cache Employee instances using read-write strategy.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><?xml version = "1.0" encoding = "utf-8"?></span><br><span class="line"><!DOCTYPE hibernate-mapping PUBLIC </span><br><span class="line">"-//Hibernate/Hibernate Mapping DTD//EN"</span><br><span class="line">"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> </span><br><span class="line"><hibernate-mapping></span><br><span class="line"> <class name = "Employee" table = "EMPLOYEE"></span><br><span class="line"> </span><br><span class="line"> <meta attribute = "class-description"></span><br><span class="line"> This class contains the employee detail. </span><br><span class="line"> </meta></span><br><span class="line"> </span><br><span class="line"> <cache usage = "read-write"/></span><br><span class="line"> </span><br><span class="line"> <id name = "id" type = "int" column = "id"></span><br><span class="line"> <generator class="native"/></span><br><span class="line"> </id></span><br><span class="line"> </span><br><span class="line"> <property name = "firstName" column = "first_name" type = "string"/></span><br><span class="line"> <property name = "lastName" column = "last_name" type = "string"/></span><br><span class="line"> <property name = "salary" column = "salary" type = "int"/></span><br><span class="line"> </span><br><span class="line"> </class></span><br><span class="line"></hibernate-mapping></span><br></pre></td></tr></table></figure><p>The usage=“read-write” attribute tells Hibernate to use a read-write concurrency strategy for the defined cache.</p><p>Now, you need to specify the properties of the cache regions. EHCache has its own configuration file, <strong>ehcache.xml</strong>, which should be in the CLASSPATH of the application. A cache configuration in ehcache.xml for the Employee class may look like this −</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><diskStore path="java.io.tmpdir"/></span><br><span class="line"></span><br><span class="line"><defaultCache</span><br><span class="line">maxElementsInMemory = "1000"</span><br><span class="line">eternal = "false"</span><br><span class="line">timeToIdleSeconds = "120"</span><br><span class="line">timeToLiveSeconds = "120"</span><br><span class="line">overflowToDisk = "true"</span><br><span class="line">/></span><br><span class="line"></span><br><span class="line"><cache name = "Employee"</span><br><span class="line">maxElementsInMemory = "500"</span><br><span class="line">eternal = "true"</span><br><span class="line">timeToIdleSeconds = "0"</span><br><span class="line">timeToLiveSeconds = "0"</span><br><span class="line">overflowToDisk = "false"</span><br><span class="line">/></span><br></pre></td></tr></table></figure><p>That’s it, now we have second-level caching enabled for the Employee class and Hibernate, now hits the second-level cache whenever you navigate to an Employee or when you load an Employee by identifier.</p><p>You should analyze your all the classes and choose appropriate caching strategy for each of the classes. Sometime, second-level caching may downgrade the performance of the application. So, it is recommended to benchmark your application first, without enabling caching and later on enable your well suited caching and check the performance. If caching is not improving system performance, then there is no point in enabling any type of caching.</p><h2 id="The-Query-level-Cache">The Query-level Cache</h2><p>To use the query cache, you must first activate it using the <strong>hibernate.cache.use_query_cache=“true”</strong> property in the configuration file. By setting this property to true, you make Hibernate create the necessary caches in memory to hold the query and identifier sets.</p><p>Next, to use the query cache, you use the setCacheable(Boolean) method of the Query class. For example −</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Session session = SessionFactory.openSession();</span><br><span class="line">Query query = session.createQuery("FROM EMPLOYEE");</span><br><span class="line">query.setCacheable(true);</span><br><span class="line">List users = query.list();</span><br><span class="line">SessionFactory.closeSession();</span><br></pre></td></tr></table></figure><p>Hibernate also supports very fine-grained cache support through the concept of a cache region. A cache region is part of the cache that’s given a name.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Session session = SessionFactory.openSession();</span><br><span class="line">Query query = session.createQuery("FROM EMPLOYEE");</span><br><span class="line">query.setCacheable(true);</span><br><span class="line">query.setCacheRegion("employee");</span><br><span class="line">List users = query.list();</span><br><span class="line">SessionFactory.closeSession();</span><br></pre></td></tr></table></figure><p>This code uses the method to tell Hibernate to store and look for the query in the employee area of the cache.</p><h4 id="class-collection-query-second-cache">class collection query second cache</h4><p>configuring in xml</p><p>ehcache : stock location; maxelement; external; timeToIdle; timeToLive; overFlow</p><p>query : timestamp</p>]]></content>
<summary type="html">
<p>Caching is a mechanism to enhance the performance of a system. It is a buffer memorythat lies between the application and the database. C
</summary>
<category term="Hibernate" scheme="https://wuhewuhe.github.io/categories/Hibernate/"/>
<category term="class" scheme="https://wuhewuhe.github.io/tags/class/"/>
<category term="first level" scheme="https://wuhewuhe.github.io/tags/first-level/"/>
<category term="second level" scheme="https://wuhewuhe.github.io/tags/second-level/"/>
<category term="query" scheme="https://wuhewuhe.github.io/tags/query/"/>
</entry>
<entry>
<title>hibernate tutorial</title>
<link href="https://wuhewuhe.github.io/2020/03/04/hinernateTuto/"/>
<id>https://wuhewuhe.github.io/2020/03/04/hinernateTuto/</id>
<published>2020-03-04T05:42:13.000Z</published>
<updated>2020-03-10T21:53:47.645Z</updated>
<content type="html"><![CDATA[<p>hibernate is persistance and ORM framework</p><p>class - > table</p><p>object -> record</p><p>field -> column</p><ul><li>hibernate.cfg.xml</li></ul><p>connection basic information url, user, pwd, driver, url</p><ul><li>set configuration</li></ul><p>show_sql, dialect, format, hbmdd2.auto</p><p>spring.jpa.hibernate.ddl-auto,其属性值作用区别介绍如下:</p><p>create:<br>每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。<br>create-drop :<br>每次加载hibernate时根据model类生成表,但是sessionFactory一关闭, 表就自动删除。<br>update:<br>最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。<br>validate :<br>每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。</p><h3 id="hibernate-实现">hibernate 实现</h3><p>SessionFactory, Configuration, Session, transaction, transaction.commit(), session.close, sessionfactory.close()</p><h3 id="how-to-manipulate-object-by-session">how to manipulate object by session</h3><p>session is like a cache who map to a record in database</p><p>session has 4 state : transient object, persistent object, detached object, remove object</p><h5 id="session-cache">session cache</h5><p>reduce connection to database, improve performance</p><ul><li>session.flush() : session cache与数据库是否一致, 若不是一致, transaction.commit() 之前调用flush 可能会更新数据库</li><li>未提交commit or session.flush</li><li>hibernate query language or query by critere</li></ul><p>transient object : oid is null not in session</p><p>persistent : oid is null but in session</p><p>removed : app not used</p><p>detached : 游离</p><h4 id="method">method</h4><ul><li>save</li></ul><p>transient object to persistence object, object will get ID, can not modify</p><ul><li>persist</li></ul><p>like insert, if before persist, object has id, who will not change</p><ul><li>get</li></ul><p>charge object immediately and print; return null;</p><ul><li>load</li></ul><p>lazy delock, return delegate; return exception; lazyinitialexception</p><ul><li>update</li></ul><p>update transient object and change it to persistent</p><ul><li>saveOrUpdate</li></ul><p>oid is null</p><ul><li>merge</li><li>delete</li></ul><h4 id="hibernate-fetch-strategic">hibernate fetch strategic</h4><p>class level : set lazy</p><p>set</p><h3 id="Hibernate-Query-Language">Hibernate Query Language</h3><p>1 create sql</p><p>2 set parameter</p><p>3 query</p><p>We can also use <code>addEntity()</code> and <code>addJoin()</code> methods to fetch the data from associated table using tables join. For example, above data can also be retrieved as below.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">//Join example with addEntity and addJoin</span><br><span class="line">query = session.createSQLQuery("select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id")</span><br><span class="line">.addEntity("e",Employee.class)</span><br><span class="line">.addJoin("a","e.address");</span><br><span class="line">rows = query.list();</span><br><span class="line">for (Object[] row : rows) {</span><br><span class="line"> for(Object obj : row) {</span><br><span class="line"> System.out.print(obj + "::");</span><br><span class="line"> }</span><br><span class="line"> System.out.println("\n");</span><br><span class="line">}</span><br><span class="line">//Above join returns both Employee and Address Objects in the array</span><br><span class="line">for (Object[] row : rows) {</span><br><span class="line">Employee e = (Employee) row[0];</span><br><span class="line">System.out.println("Employee Info::"+e);</span><br><span class="line">Address a = (Address) row[1];</span><br><span class="line">System.out.println("Address Info::"+a);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Query-hibernate-Criteria">Query hibernate Criteria</h3><p>1 create a criteriabuilder</p><p>2 add restriction to builder</p><p>3 construct creteria by criteriaQuery</p><p>4 get result</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">CriteriaBuilder builder = session.getCriteriaBuilder();</span><br><span class="line"> <span class="comment">// Using FROM and JOIN</span></span><br><span class="line"> CriteriaQuery<Object[]> criteriaQuery = builder.createQuery(Object[]<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"> Root<Employee> empRoot = criteriaQuery.from(Employee<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"> Root<Department> deptRoot = criteriaQuery.from(Department<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"> criteriaQuery.multiselect(empRoot, deptRoot);</span><br><span class="line"> criteriaQuery.where(builder.equal(empRoot.get(<span class="string">"department"</span>), deptRoot.get(<span class="string">"id"</span>)));</span><br><span class="line"></span><br><span class="line"> Query<Object[]> query=session.createQuery(criteriaQuery);</span><br><span class="line"> List<Object[]> list=query.getResultList();</span><br></pre></td></tr></table></figure><h3 id="use-native-sql">use native sql</h3><p>1 sql</p><p>2 Query query = session.createSqlQuery(sql)</p><p>3 setparameters and execute</p><h3 id="session-attach-JTA">session attach JTA</h3><p>plusieurs dao use one session</p><p>singlenton</p><p>hibernate utils{</p><p>}</p><p>if(sessionfactory == null){</p><p>configuation = new configuration.configure();</p><p>serviceregistry = serviceregistrybuilder().applysetting(configuration.getpropertites).buildserviceregistry()</p><p>configuration.buildsesssionfactory(serviceregistry)</p><p>}</p><p>public Session getSession(){</p><p>return getSessionFactory().getCurrentSession();</p><p>}</p><p>Session session = HibernateUtils.getInstance().getSession();</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hbm.cfg.xml </span><br><span class="line">hibernate.current_session_context = true</span><br></pre></td></tr></table></figure><h4 id="bulk-insert">bulk insert</h4><ul><li>jdbc origin</li></ul><p>session.doWork(() -> {</p><p>connection -> effiency, fast</p><p>})</p><ul><li>session use first level not good</li><li>hql interpert</li><li>stateless intepert</li></ul>]]></content>
<summary type="html">
<p>hibernate is persistance and ORM framework</p>
<p>class - &gt; table</p>
<p>object -&gt; record</p>
<p>field -&gt; column</p>
<ul>
<li
</summary>
<category term="hbm.cfg.xml" scheme="https://wuhewuhe.github.io/tags/hbm-cfg-xml/"/>
<category term="ddl2auto" scheme="https://wuhewuhe.github.io/tags/ddl2auto/"/>
<category term="fetch" scheme="https://wuhewuhe.github.io/tags/fetch/"/>
</entry>
<entry>
<title>范型</title>
<link href="https://wuhewuhe.github.io/2020/03/03/java-generic/"/>
<id>https://wuhewuhe.github.io/2020/03/03/java-generic/</id>
<published>2020-03-03T06:24:33.000Z</published>
<updated>2020-03-10T21:53:47.663Z</updated>
<content type="html"><![CDATA[<p>java geneircs</p><p>1Java中的泛型是什么 ? 使用泛型的好处是什么?</p><p>集合中存储对象并在使用前进行类型转换是多么的不方便</p><p>它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。</p><ol start="2"><li>Java的泛型是如何工作的 ? 什么是类型擦除 ?</li></ol><p>这是一道更好的泛型面试题。泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List<String>在运行时仅用一个List来表示。这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型</String></p><ol start="3"><li>什么是泛型中的限定通配符和非限定通配符 ?</li></ol><p>这是另一个非常流行的Java泛型面试题。限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>它通过确保类型必须是T的子类来设定类型的上界,另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面<?>表示了非限定通配符,因为<?>可以用任意类型来替代</p><ol start="4"><li>List<? extends T>和List <? super T>之间有什么区别 ?</li></ol><p>这和上一个面试题有联系,有时面试官会用这个问题来评估你对泛型的理解,而不是直接问你什么是限定通配符和非限定通配符。这两个List的声明都是限定通配符的例子,List<? extends T>可以接受任何继承自T的类型的List,而List<? super T>可以接受任何T的父类构成的List。例如List<? extends Number>可以接受List<Integer>或List<Float></Float></Integer></p><ol start="5"><li>你可以把List<String>传递给一个接受List<Object>参数的方法吗?</Object></String></li></ol><p>对任何一个不太熟悉泛型的人来说,这个Java泛型题目看起来令人疑惑,因为乍看起来String是一种Object,所以List<String>应当可以用在需要List<Object>的地方,但是事实并非如此。真这样做的话会导致编译错误。如果你再深一步考虑,你会发现Java这样做是有意义的,因为List<Object>可以存储任何类型的对象包括String, Integer等等,而List<String>却只能用来存储Strings。</String></Object></Object></String></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">List<Object> objectList;</span><br><span class="line">List<String> stringList;</span><br><span class="line">objectList = stringList; //compilation error incompatible types</span><br></pre></td></tr></table></figure><ol start="7"><li>Array中可以用泛型吗?</li></ol><p>这可能是Java泛型面试题中最简单的一个了,当然前提是你要知道Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。</p><ol start="8"><li>如何阻止Java中的类型未检查的警告?</li></ol><p>如果你把泛型和原始类型混合起来使用,例如下列代码,Java 5的javac编译器会产生类型未检查的警告,例如</p><p>List<String> rawList = new ArrayList()</String></p>]]></content>
<summary type="html">
<p>java geneircs</p>
<p>1Java中的泛型是什么 ? 使用泛型的好处是什么?</p>
<p>集合中存储对象并在使用前进行类型转换是多么的不方便</p>
<p>它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCas
</summary>
<category term="Generic" scheme="https://wuhewuhe.github.io/categories/Generic/"/>
</entry>
<entry>
<title>Hibernate Interview</title>
<link href="https://wuhewuhe.github.io/2020/03/03/hibernateInterview/"/>
<id>https://wuhewuhe.github.io/2020/03/03/hibernateInterview/</id>
<published>2020-03-03T06:16:10.000Z</published>
<updated>2020-03-04T05:41:59.172Z</updated>
<content type="html"><![CDATA[<p><img src="https://pic3.zhimg.com/80/v2-4552ce098693b9221474a8dd825a43ce_720w.jpg" alt="img"></p><p><img src="https://pic3.zhimg.com/80/v2-97558ff79de611a00eea8a3b07a3c35e_720w.jpg" alt="img"></p><p>大家好,这一期呢,我们谈一下Java hibernate相关的面试题。</p><p>第1题,什么是hibernate?</p><p>hibernate是一个架构, 用来对应Java对象数据库表对象。使用一个xml文件来配置。</p><p>第2题, 什么是orm?</p><p>object relational mapping。它是hibernate的基础概念。用来对应数据库表跟Java对象。</p><p>第3题, Java类属性是如何跟表的列进行对应的?</p><p>在定义这个Java类的时候要声明跟哪个表关联,然后在定义属性的时候,加上column注解。</p><p>第4题,如何创建session factory?</p><p>首先使用configuration加载xml文件。然后用configuration对象来创建session factory.</p><p>第5题,什么是pojos?</p><p>plain old Java objects. 指的是一个Java class中的每个成员都有getter, setter。</p><p>第6题, 什么是hql?</p><p>Hql是在hibernate中使用的查询语言。它是sql的扩展。不需要书写非常复杂的数据库查询语句,你就可以做很多事情。</p><p>第7题, 在hibernate中我们如何调用stored procedures?</p><p>你可以通过在xml中定义下面代码的方法来调用stored procedures.<sql-query … >… </p><p>第8题, 什么是criteria api?</p><p>Criteria api通过设定一些条件来获取数据库的数据的简单而又强大的API。</p><p>第9题,使用hibernate template的好处有什么?</p><p>Session的关闭是自动的。</p><p>简化了与session的交互。</p><p>异常处理是自动的。</p><p>在服务类中使用repository注解。</p><p>第10题,我们如何查看hibernate生成的sql语句?</p><p>在hibernate的配置文件中,添加下面这一行:</p><p><property name="show_sql">true</property>。</p><p>第11题,在hibernate中有哪两种Collections?</p><p>一种是sorted collection, 这个是运行在jvm上的,一种是order collection, 这个是运行在数据库上的。</p><p>第12题,session save method和save or update method的区别是什么?</p><p>Save负责插入一条不存在的记录。</p><p>Save or update, 如果记录不存在就插入,如果存在就更新。</p><p>第13题, 跟jdbc相比hibernate的优势在哪里?</p><p>hibernate你不需要再写具体的sql语句了。</p><p>行,jdbc的话,你可能会写很多sql语句,并且有可能会很复杂。</p><p>使用hinernate, 你不需要再关心数据库的连接池的问题。</p><p>第14题, 如何获取hibernate的statistics?</p><p>我们可以调用session factory 的 get statistics方法。</p><p>第15题, 什么是hibernate中的transient实例状态?</p><p>Trnaisent的实例状态是指没有任何关联性的上下文的状态。</p><p>第16题, 如何减少数据库写操作的时间?</p><p>Hibernate 有 dirty check这个机制,它可以减少数据库的写时间。</p><p>这个机制起作用时,就是只会更新那些被修改的域,而不会修改其他没有修改的域。</p><p>第17题,在hibernate中callback接口是干什么的?</p><p>从对象来接收事件信息,就使用call back接口。比如当一个对象的某个属性发生改变的时候,可以通过callback来通知调用者。</p><p>第18题,什么时候实例会处于解除状态?</p><p>如果实例跟一个表处于一种连接状态的时候,然后又断开,这种状态称为解除状态。</p><p>第19题,Hibernate中4种ORM的等级?</p><p>纯粹的关系型。</p><p>初级对象映射。</p><p>中级对象映射。</p><p>全对象映射</p><p>第20题,事务管理是怎么进行的?</p><p>事务管理是用来管理一系列的语句或者命令。在Hibernate中事务管理是通过事务接口来管理的。</p><p>第21题,Hibernate配置的两种方法?</p><p>一种是通过xml来配置。</p><p>一种是通过代码来配置。</p><p>第22题,缺省的二级缓冲服务是什么?</p><p>缺省的二级缓冲服务是ehcache, 此外还有oscache, swarmcache和treecache。</p><p>第23题, 有哪几种关系映射?</p><p>一种是1对1,一种1对多,一种是多对多。</p><p>第24题,hibernate中的qbc API是干什么用的?</p><p>Hibernate query by criteria api 用来在运行时创建使用criteria对象的查询.</p><p>第25题, 有几种从数据库获取数据的方法?</p><p>Hql.</p><p>Identifier.</p><p>Criteria api.</p><p>Standard sql.</p><p>第26题, 主键是怎么创建的?</p><p>数据库的主键在配置文件hbm.xml中指定. Generator也可以被用来指定主键的创建方式。</p><p>第27题,如何re attach已经解除的对象 ?</p><p>可以通过session merge方法来re attach已经解除的对象。</p><p>第28题, 有几种方法使hibernate二级cache失效?</p><p>set use_second_level_cache as false.</p><p>CACHEMODE. IGNORE</p><p>NOCACHEPROVIDER</p><p>第29题,什么是orm metadata?</p><p>所有的对应关系包括类和表之间,属性和列之间,Java类型和sql类型之间,都定义在orm的meta data中。</p><p>第30题, 缺省的事务factory是哪个?</p><p>jdbc transaction factory.</p><p>第31题,jmx的作用是什么?</p><p>jmx提供了开发有效和稳定的网络应用方案的工具。</p><p>第32题, 如何把session factory绑定到jndi上?</p><p>在hibernate config file里面。</p><p>第33题, 对象判断有几种方法?</p><p>用等号儿操作符。</p><p>用equals方法。</p><p>使用数据库标识。是不是在同一行?</p><p>第34题,有多少种获取策略?</p><p>Join获取,批量获取, 选择获取, 部分选择获取。</p><p>第35题,Java对象映射是怎么做的?</p><p>一种方法是用xml定义对应关系。</p><p>另一种方法是用注解。</p><p>第36题, 什么是派生属性?</p><p>派生属性是指没有任何数据列对应的属性。通常是一些类似表达式的,或者辅助性的属性。</p><p>第37题,那些有名字的sql查询是怎么回事?怎么使用它?</p><p>在映射文件中定义的那些查询,一般都有一个名字,这种查询被称为有名字的查询。</p><p>使用get named query.</p><p>第38题,方法load和get的区别是什么?</p><p>如果数据不存在的话, load会扔出一个异常, Get会返回空。</p><p>第39题, 版本属性的用处是什么?</p><p>完美属性的用处主要是来判断这个对象是短暂状态还是解除状态。</p><p>第40题,什么是面向属性的编程?</p><p>在hibernate中面向属性编程由xdoclet这个引擎来控制, 允许程序员向Java代码中添加meta data。</p><p>第41题, Session lock方法是干什么用的?</p><p>这个方法主要是为了re attach 一个已经解除的对象。这个方法不会检查数据的同步,所以有可能会出现数据不同步的现象。</p><p>第42题, Hibernate是否支持多态?</p><p>是的。多态查询和多态关联,在hibernate之中适用于所有的映射策略。</p><p>第43题, 有哪三种继承模型?</p><p>Tables per concrete class.</p><p>Tables per class hierarchy.</p><p>Tables per sub class.</p><p>第44题, 我们如何来映射一个不可修改的类?</p><p>设定mutable等于false。</p><p>第45题,在数据库管理系统中,通常的hibernate流程是怎样的?</p><p>加载配置文件,创建配置对象。</p><p>配置对象创建session factory对象。</p><p>从session factory获取一个session。</p><p>创建hql查询。</p><p>执行hql查询并返回结果。</p><p>结果会是一个列表。</p><p>第46题, 什么是light Object mapping?</p><p>使用手工的方式来映射Entity数据对象和表对象。</p><p>第47题,管理的关联和hibernate关联有什么区别?</p><p>管理的关联是双向的,而hinernate的关联是单向的。</p><p>第48题, Hibernate 架构中比较重要的接口有哪些?</p><p>Session factory.</p><p>Session.</p><p>Transaction.</p><p>第49题,在hibernate映射中有哪些重要的注解?</p><p>Entity. Table. Access. ID.embeddedID. Column. Generatedvalue. One to one. Cascade. Primary key join column.</p><p>第50题, Session factory是线程安全的吗?</p><p>是的。session factory是不可修改的,所以是线程安全的。</p><p>第51题,session是线程安全的吗?</p><p>不是。各自的线程,在使用完自己的session以后一定要关掉。</p><p>第52题,open session和get current session的区别是什么?</p><p>你需要在section factory的配置文件中配置才能够使用get current session. 它是跟当前的context相关联的。</p><p>Open session每次都会打开一个新的session,我们需要自己关闭它。</p><p>在多线程的环境中,对于每一个请求,我们应该使用open session。</p><p>还有一个方法叫open stateless session,会返回一个无状态的session。</p><p>第53题, 什么是hibernate的caching,解释一下,first level cache是什么。</p><p>Hibernate cash机制会使我们查询数据更快。First level cache是跟session对象关联的。这是缺省选项无法取消。但是我们有hibernate方法删除对象。</p><p>第54题,entity bean的不同状态有哪些?</p><p>Transient. 可以通过如下方法save, save or update, persistent 进入persistent状态, 通过delete,再返回到transient状态。</p><p>Persistent. 从get和load返回的就是persistent实例,与一个唯一的session相关联。</p><p>Detached. 之前曾经是presistent,但是现在没有关联任何session的状态叫做detached.</p><p>可以通过update,save or update, lock, replicate再转成persistent。</p><p>merge可以transient, detached转成一个新persistent实例。</p><p>第55题, Save, save or update和persist的区别是什么?</p><p>Save是添加一条新的记录。并快速返回ID.</p><p>Persist, 跟save的功能差不多,但是它不会立即返回生成的ID。</p><p>Save or update. 如果记录不存在,就添加一条记录,如果记录存在的话就更新该记录。</p><p>第56题,如果entity bean没有空构造函数, 会发生什么?</p><p>如果没有空构造的函数的话,会产生一个hibernate exception。</p><p>第57题,hibernate里面的collection类型有哪些?</p><p>Bag, set, list, array, map.</p><p>58题,在hibernate中如何使用joins?</p><p>有几种方法:</p><p>使用1 to 1, 或者one to many关联。</p><p>在hql中使用join关键字。John fetch使用eager loading, 不是lazy loading。</p><p>或者直接使用标准的sql查询语句,加上join关键字。</p><p>第59题,为什么我们不应该让Entity class变成final?</p><p>Lazy loading是通过扩展现有的Entity class来做到的。</p><p>如果entity class变成final, lazy loading就不可能实现了。性能上会大打折扣。</p><p>第60题, 什么是cascading?有几种类型的cascading?</p><p>当我们处理两个Entity之间的关系的时候,我们需要来定义,他们之间的操作是怎么互相影响的。这个方面是通过cascading来定义的。</p><p>有如下类型:</p><p>None</p><p>all</p><p>save_update</p><p>delete</p><p>detach, merge, persist, refresh, remove</p><p>lock</p><p>replicate</p><p>第61题, 如何集成log4j?</p><p>添加log4j的依赖。</p><p>创建xml配置文件,或者log4j的properties文件,并放到class path里面。</p><p>。</p><p>在standalone工程里面用dom configurator, property configurator。</p><p>在网络应用中, 使用servlet context listener去配置它。</p><p>第62题, 如何集成hibernate和spring框架?</p><p>添加hibernate Entity manager,hibernate core, spring orm依赖。</p><p>创建模型类和对应的dao实现类来操作数据库。</p><p>Dao实现类用来操作session factory。</p><p>local session factory bean需要被配置。</p><p>如果我们用transactional注解的话,我们就不需要关心事务管理了。</p><p>第63题, Hibernate如何跟servlet或者struts2进行集成?</p><p>通过servlet context listener.</p><p>第64题,hibernate框架使用了哪些design patterns?</p><p>Domain model pattern, 模型中包含行为和数据.</p><p>Data mapper. 提供数据类跟数据库表对象的关联。</p><p>Proxy pattern. 用来做lazy loading。</p><p>Factory pattern. 比如session factory.</p><p>第65题, Hibernate的最好的实践有哪些?</p><p>. 始终检查主键的访问, 如果是数据库自动生成的,那么就不应该有setter。</p><p>. 缺省的, hibernate是直接对域进行设置的,如果你想使用setter的话,要加access注解.</p><p>. 不要同时在成员变量和get方法上加注解。</p><p>. 除非hql做不到才使用标准的sql。</p><p>. 要使用order list,而不是使用sorted list.</p><p>. Named的query,只用于通用的情况。特别的query仅限于Entity本身。</p><p>. 对网络应用来说,要使用jndi,而不是直接去配置数据库连接。</p><p>. 避免多对多的关系。使用一对多和多对一来化解。</p><p>. 只用collection时,使用list,maps和sets,尽量不用array, 因为array不能做lazy loading。</p><p>. 当发生exception时,回退事务,关掉session。</p><p>. 尽量使用lazy fetching.</p>]]></content>
<summary type="html">
<p><img src="https://pic3.zhimg.com/80/v2-4552ce098693b9221474a8dd825a43ce_720w.jpg" alt="img"></p>
<p><img src="https://pic3.zhimg.com/80/v
</summary>
<category term="Hibernate" scheme="https://wuhewuhe.github.io/categories/Hibernate/"/>
<category term="ORM" scheme="https://wuhewuhe.github.io/categories/Hibernate/ORM/"/>
<category term="hql" scheme="https://wuhewuhe.github.io/tags/hql/"/>
<category term="qbc" scheme="https://wuhewuhe.github.io/tags/qbc/"/>
<category term="cache" scheme="https://wuhewuhe.github.io/tags/cache/"/>
<category term="state" scheme="https://wuhewuhe.github.io/tags/state/"/>
</entry>
<entry>
<title>transaction and data pool</title>
<link href="https://wuhewuhe.github.io/2020/03/03/transactionDB/"/>
<id>https://wuhewuhe.github.io/2020/03/03/transactionDB/</id>
<published>2020-03-03T06:15:28.000Z</published>
<updated>2020-03-03T06:23:40.963Z</updated>
<content type="html"><![CDATA[<h3 id="database-Transaction">database Transaction</h3><p>A B, but is has web exception when A transfer 100 euro to B</p><p>事物是一组逻辑操作 比如增删改查,把数据从一个状态变为另外一个状态</p><p>事物two state : commit or rollback</p><p>garante the data consistance</p><ul><li><p>définition ddl : commit (include drop, alter, create, rename, turncate)</p></li><li><p>manipulation dml: insert, update, delete, lock, merge (par default commit)</p><p>but we can setAutoCommit(false);</p></li></ul><p>commit when close the connection</p><h3 id="resolution">résolution</h3><p>one connexion can finish transfer money from A to B, which means connection A doesn’t close after reduce 100 euros</p><p>try</p><p>con.setAutoCommit(false);</p><p>jdbcUtils.closeResource(null, ps) in connection A</p><p>jdbcUtils.closeResource(con, null) in connection B</p><p>con.commit();</p><p>catch con.rollback();</p><p>finally con.setAutoCommit(true); //avoiding database pooling problem</p><h4 id="ACID">ACID</h4><ul><li>Atomic</li></ul><p>can not separate, operation occur or nothing</p><ul><li>consistance</li></ul><p>transaction change from one state to another state</p><ul><li>Isolation</li></ul><p>one tranaction will not distract another transaction</p><ul><li>Durabilité</li></ul><p>when commit, can not roll back</p><h4 id="database-transaction-concurrent-probleme">database transaction concurrent probleme</h4><ul><li><p>dirty read : T1, T2, T2 modify data, but not commit, T1 read but t2 rollback, no solution</p></li><li><p>repeat read: T1, T2, t1 read data, t2 modify, t1 read agin, the data are not the same</p><p>: update</p></li><li><p>fantom read : T1, T2, t1 read data, t2 insert data, t1 found the result are different :insert</p></li></ul><p>we always use <strong>read commited</strong> isolation in your reallife for avoiding dirty read</p><p>isolation level more(consisten better), performance will weak(concurrent)</p><p>oracle : sérialisation and read commit</p><p>mysql : read repeated, repeated, sérialisation</p><h3 id="java-how-to-set-isolation-by-code">java how to set isolation by code</h3><p>con.setTransactionIsolation(CONNECTION. Transaction_read_committed);</p><h3 id="Database-statement-pool">Database statement pool</h3><hr><p>when we develop the web app with database, in tradition mode :</p><p>servelt, beans create a connection</p><p>do sql opertions</p><p>close connection</p><h3 id="probleme">probleme</h3><ul><li>ressource not make advantage</li><li>memory leak, not close well, it will can not garage collector</li><li>can not control connexion number</li></ul><p>database pool, create some connection in to the pool, surpass the maximum connection, wait in queue.conn will switch free or busy</p><p>prons:</p><ul><li>reuse ressources</li><li>fast reaction</li><li>control connection in a center</li></ul><p>statement pooling, connection poolingjavax. DataSource are always realised by web server(tomcat, websphere)</p><p>initialPoolsize; maxPoolsize, acquireIncresetment; Statement(sql query)</p><ul><li>dbcp databse connection pooling</li><li>c3p0</li></ul><p>使用配置配置文件</p><ul><li>Druid</li></ul><p>quick start</p><p>ApacheDB-Utils</p><p>class QueryRunner</p><p>QueryRunner run = new QueryRunner();</p><p>run.update(sql);</p><p>QueryRunner : search</p><p>interface ResultSetHandler</p><p>ResultSetHandler <Customer> bean = new BeanHanlder<Customer></Customer></Customer></p><p>ResultSetHandler <Customer> bean = new BeanListHanlder<Customer></Customer></Customer></p><p>ResultSetHandler map = new MapHanlder</p><p>ResultSetHandler map = new MapListHanlder</p><p>ResultSetHandler map = new ScalaHanlder //查询特殊值</p><p><strong>customer resultset handler</strong></p><p>DBUtils manage ressources</p><p>close or closequietly</p>]]></content>
<summary type="html">
<h3 id="database-Transaction">database Transaction</h3>
<p>A B, but is has web exception when A transfer 100 euro to B</p>
<p>事物是一组逻辑操作 比如增删
</summary>
<category term="Transaction" scheme="https://wuhewuhe.github.io/categories/Transaction/"/>
<category term="Data pool" scheme="https://wuhewuhe.github.io/categories/Transaction/Data-pool/"/>
<category term="c3p0" scheme="https://wuhewuhe.github.io/tags/c3p0/"/>
<category term="bpcp" scheme="https://wuhewuhe.github.io/tags/bpcp/"/>
<category term="druid" scheme="https://wuhewuhe.github.io/tags/druid/"/>
<category term="acid" scheme="https://wuhewuhe.github.io/tags/acid/"/>
</entry>
<entry>
<title>Java Driver Base Connection</title>
<link href="https://wuhewuhe.github.io/2020/03/01/jdbc/"/>
<id>https://wuhewuhe.github.io/2020/03/01/jdbc/</id>
<published>2020-03-01T21:18:25.000Z</published>
<updated>2020-03-03T06:21:51.572Z</updated>
<content type="html"><![CDATA[<p>database connection is like a socket</p><blockquote><p>jdbc is programming fact to interface, who has principal ide is ORM object relation mapping who can search, all of things are object.techno : getResultMetaData, reflect get dynamic class</p></blockquote><p>start; import sql package; connection; prepareStatement; ResultSet; Close; end;</p><p>connection -> prepareStatement -> result</p><p>sql will prepare compiler and save by object, it is more efficiency</p><p>1 fake code of database connection</p><p>String url = “”</p><p>String user = “”</p><p>String pwd = “”</p><p>driver =classforname()</p><p>try</p><p>connection con = DriverManager.getConnection(url, user, pwd, driver)</p><p>catch</p><p>e.printStack()</p><p><strong>why we not use statement?</strong></p><p>1 we must contact sql, more difficile write</p><p>2 sql injection, for ex and will become to or</p><p><strong>example of preparestatement</strong></p><p>try</p><p>InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(“jdbc.propertites”);</p><p>Propertites pros = new Propertites();</p><p>pros.load(is);</p><p>String user = pros.getProperty(“user”);</p><p>String pwd = pros.getProperty(“pwd”)</p><p>String url = pros.getproperty(“url”);</p><p>String driver = pros.getProperty(“driverclass”);</p><p>class.forName(driverClass);</p><p>Conncection con = DriverManager.getConnection(url, user, pwd);</p><p>String sql = “insert into customer(name, id, birth) valus(?, ?, ?)”;</p><p>PrepareStatement ps = con.prepareStatement(sql);</p><p>ps.setString(1, “name”);</p><p>ps.setString(2, “id”);</p><p>SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-mm-yy”);</p><p>Date d = sdf.parse(“2000-2-2”);</p><p>ps.setDate(3, new Date(d.getTime()));</p><p>ps.execute();</p><p>catch{}</p><p>finally{</p><p>try ps.close</p><p>catch</p><p>try con.close</p><p>catch</p><p>}</p><p><strong>jdbcUtils</strong></p><p>create two method : connection and close</p><ul><li>modify</li></ul><p>String sql = “update customer set name = ? where id = ?”</p><p>PreparedStatement ps = conn.prepareStatement(sql);</p><p>//fill placeholder</p><p>ps.setObject(1, “name”);</p><p>ps.setObject(2, “10”);</p><p>ps.execute;</p><p>try closeResource(conn, ps) catch</p><ul><li>general modify method include add delete update</li></ul><p>public void update(String sql, Object … args) throw Exception{</p><p>try</p><p>Connection con = jdbcUtils.getConncetion();</p><p>PrepareStatement ps = new PrepareStatement(sql);</p><p>for(int i = 0; i<args.length; i++)</p><p>ps.setObject(i+1, args[i]); //i+1</p><p>}</p><p>ps.execute()</p><p>catch e.prinStackTrace();</p><p>finally jdbcUtils.closeResource(con, ps);</p><p><strong>table name use ‘’ for avoiding sql syntax exception</strong></p><h4 id="search-preparestatement">search preparestatement</h4><ul><li>customer table search</li></ul><p>try</p><p>Connection con = jdbcUtils.getConnection();</p><p>String sql = "select * from ‘customer’ wher id = ? ";</p><p>PrepareStatement ps= new PrepareStatement(sql);</p><p>ps.setObject(1);</p><p>ResultSet rs = ps.executeQuery();</p><p>if(rs.next()){</p><p>int id = rs.getInt(1);</p><p>String name = rs.getString(2);</p><p>Date birth = rs.getDate(3);</p><p>//Object[] data = new Object[]{id, name, date};</p><p>customer c = new customer(id, name, date);</p><p>catch e.printstack();</p><p>finally closeresource();</p><p>}</p><p><strong>create a java bean ORM</strong></p><p>(object relation mapping, one table one class, one record one object, one field one attribute)</p><hr><p>boolean bit</p><p>byte tinyint</p><p>shpry smallint</p><p>int integer</p><p>long bigint</p><p>string varchar, char, longchar</p><p>sql date, time, timestamp</p><hr><p>public class Customer{</p><p>String name;</p><p>int id;</p><p>Date birth;</p><p>}</p><p><strong>general search to special table</strong></p><p>ResultMetaData rsmd = rs.getMetaData();</p><p>int count = rsmd.getColumnCount();</p><p>if(rs.hasnext()){</p><p>Customer cs = new Customer();</p><p>for(int i = 0; i< count; i++){</p><p>Object value = rs.getObject(i+1);</p><p>//get column name</p><p>String columnName = rsmd.getColumnName(i+1);</p><p>//intial value</p><p>Field field = Customer.getDeclaredField(columnName);</p><p>field.setAccessiable;</p><p>field.set(cs, value);</p><p>}</p><p>return cs</p><p>}</p><p>return null;</p><h3 id="preparestatement-general-search-to-different-table">preparestatement general search to different table</h3><ul><li>one record</li></ul><p>public generalQuery(){</p><p>public <T> T object getInstance(class<T> class, String sql, Object… args){</T></T></p><p>Connection con = null;</p><p>PrepareStatement ps= null;</p><p>ResultSet rs = null;</p><p>try{</p><p>con = jdbcUtils.getConnection();</p><p>ps = new PrepareStatement(sql);</p><p>for(int i = 0; i< args.length; i++){</p><p>ps.setObject(i+1, args[i]);</p><p>}</p><p>rs = ps.executeQuery();</p><p>ResultMetaData rsmd = rs.getMetaData();</p><p>int columnCount = rsmd.getColumnCount();</p><p>if(rs.next()){</p><p>T t = class.newInstance();</p><p>for(int i = 0; i<columnCount; i++){</p><p>Object value = rs.getObject(i+1);</p><p>String columnLable = rsmd.getColumnLabel(i+1);</p><p>Field field = class.getDeclardField(columnLabel);</p><p>fied.setAccessibl(true);</p><p>field.set(t, value);</p><p>}</p><p>return t;</p><p>}</p><p>}</p><p>catch(){ e.printStack()}</p><p>finally{jdbcUtils.closeResource; }</p><p>}</p><p>return null;</p><ul><li>return multi record</li></ul><p>public <T> List<T> getForList(Class<T> class, String sql, Object … args){</T></T></T></p><p>List<T> list = new ArrayList();</T></p><p>ResultMetaData rsmd = rs.getMetaData();</p><p>int columnCount = rsmd .getColumnCount();</p><p>while(rs.hasNext()){</p><p>T t = class.newInstance();</p><p>for(int i = 0; i<columnCount ; i++){</p><p>Object value = rs.getObject(i+1);</p><p>String columnValue = rsmd.getColumnValue(i+1);</p><p>Field field = class.getDecalreField(columnValue );</p><p>field.setAccessible(true);</p><p>feild.set(t, columnValue);</p><p>}</p><p>list.add(t);</p><p>}</p><p>return list;</p><p>}</p><p><strong>preparestatement can realise bulk insert more effiency</strong></p><p><strong>how to manipulate video, file image</strong></p><ul><li>blob two byte long, max blob, tiny</li></ul><h5 id="add-delete-and-updtae-blob">add delete and updtae blob</h5><p>performance will down, if we save more blob</p><p>PrepareStatement ps = conn.prepareStatement(sql);</p><p>FileInputStream fs = new FileInputStream(new File(“jpg”));</p><p>ps.setBlob(4, is);</p><p>ps.execute();</p><h5 id="search-blob">search blob</h5><p>PrepareStatement ps = conn.prepareStatement(sql);</p><p>Blob photo = rs.getBlob(“photo”);</p><p>InputStream is = photo.getBinaryStream();</p><p>FileOutputStream fos = new FileOutPutStream(“jpg”);</p><p>byte[] buffer = neww Byte[1024];</p><p>int len;</p><p>while(len = buffer.read() != -1){</p><p>fos.write(buffer, 0 , len);</p><p>}</p><p>is.close();</p><p>fos.close();</p><p><strong>blob exception pack too big exception</strong></p><p>my.ini set max_allowed_packet = 16M</p><p>add ?rewriteBatchedStatedments= true;</p><ul><li>bulk insert</li></ul><p>reduce i/o, reduce insert,</p><p>ps.executeBatch();</p><p>ps.clearBatch();</p><p>conn.setAutoCommit();</p><p>conn.commit();</p><h3 id="preparestatemenr-vs-statement">preparestatemenr vs statement</h3><p>preparestatement is subinterface of statament</p><p>preparestatemen can improve performance because of precompile, resolve sql injection, placeholder problem</p><p>preparestatemen not need string contact</p><p>preparestatement can treat image, video,</p><h3 id="DAO">DAO</h3><p>BaseDAO is abstract class</p><p>data access object E <E> getValue() return res.getObject(1);</E></p><p>interface CustomerDAO{</p><p>void insert(connection, customer)</p><p>void deleteById(connection, id)</p><p>void update(connection, customer)</p><p>customer getCustomerById(connection, id)</p><p>List<Customers> getAll(connection)</Customers></p><p>int count(connection)</p><p>Date getMaxBirth(connection)</p><p>}</p><p>class CustomerDAOImplements extends BaseDAO implements CustomerDAO{</p><p>}</p><p>DAO layer is interact layer, we write our sql code in here</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">//get basedao generic class for its parent class</span><br><span class="line">Type t = IntegerClass.class.getGenericSuperclass();</span><br><span class="line"> System.out.println(t); </span><br><span class="line"> </span><br><span class="line"> ParameterizedType p = (ParameterizedType)t;</span><br><span class="line"> System.out.println(p.getActualTypeArguments()[0]);</span><br></pre></td></tr></table></figure><p>baoClass<T></T></p>]]></content>
<summary type="html">
<p>database connection is like a socket</p>
<blockquote>
<p>jdbc is programming fact to interface, who has principal ide is ORM object relat
</summary>
<category term="JDBC" scheme="https://wuhewuhe.github.io/categories/JDBC/"/>
<category term="DBUtils" scheme="https://wuhewuhe.github.io/categories/JDBC/DBUtils/"/>
<category term="Connection" scheme="https://wuhewuhe.github.io/categories/JDBC/DBUtils/Connection/"/>
<category term="Query" scheme="https://wuhewuhe.github.io/categories/JDBC/DBUtils/Connection/Query/"/>
<category term="preparedStatement" scheme="https://wuhewuhe.github.io/tags/preparedStatement/"/>
<category term="statement" scheme="https://wuhewuhe.github.io/tags/statement/"/>
<category term="blob" scheme="https://wuhewuhe.github.io/tags/blob/"/>
<category term="resultSet" scheme="https://wuhewuhe.github.io/tags/resultSet/"/>
<category term="resultMetaData" scheme="https://wuhewuhe.github.io/tags/resultMetaData/"/>
</entry>
<entry>
<title>zookeeper 集群</title>
<link href="https://wuhewuhe.github.io/2020/03/01/zookeeper/"/>
<id>https://wuhewuhe.github.io/2020/03/01/zookeeper/</id>
<published>2020-03-01T20:50:30.000Z</published>
<updated>2020-03-01T21:19:39.576Z</updated>
<content type="html"><![CDATA[<p>How it works</p><p>It uses <a href="http://zookeeper.apache.org/" target="_blank" rel="noopener">Apache ZooKeeper</a> to coordinate which node in the cluster becomes the master. The elected master broker node starts and accepts client connections. The other nodes go into slave mode and connect the the master and synchronize their persistent state /w it. The slave nodes do not accept client connections. All persistent operations are replicated to the connected slaves. If the master dies, the slaves with the latest update gets promoted to become the master. The failed node can then be brought back online and it will go into slave mode.</p><p>All messaging operations which require a sync to disk will wait for the update to be replicated to a quorum of the nodes before completing. So if you configure the store with <code>replicas="3"</code> then the quorum size is <code>(3/2+1)=2</code> . The master will store the update locally and wait for 1 other slave to store the update before reporting success. Another way to think about it is that store will do synchronous replication to a quorum of the replication nodes and asynchronous replication replication to any additional nodes.</p><p>When a new master is elected, you also need at least a quorum of nodes online to be able to find a node with the lastest updates. The node with the lastest updates will become the new master. Therefore, it’s recommend that you run with at least 3 replica nodes so that you can take one down without</p><hr><p>one master two slaves, when master is down, elected a new master</p><p>1 jdk, apache, linux</p><p>2 close firewall</p><p>3 zookeeper cluster : zk01, zk02, zk03</p><p>4 集群部署规划表</p><p>Hostname : 1361 1362 1363</p><p>Zookeeper port : 2191 2192 2193</p><p>Amq bind : 63631 63632 63633</p><p>amqtcp : 61616 61617 61618</p><p>Console port: 8161 8162 8163</p><p>5 设置节点</p><p>Node1 2 3, 修改配置对应的端口号</p><p>hostname reflect.</p><p>set brokername, 三个节点的持久化配置</p><p>6 修改 persistantadapter</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><persistenceAdapter></span><br><span class="line"> <replicatedLevelDB</span><br><span class="line"> directory="activemq-data"</span><br><span class="line"> replicas="3"</span><br><span class="line"> bind="tcp://0.0.0.0:0"</span><br><span class="line"> zkAddress="zoo1.example.org:2181,zoo2.example.org:2181,zoo3.example.org:2181"</span><br><span class="line"> zkPassword="password"</span><br><span class="line"> zkPath="/activemq/leveldb-stores"</span><br><span class="line"> hostname="broker1.example.org"</span><br><span class="line"> /></span><br><span class="line"> </persistenceAdapter></span><br></pre></td></tr></table></figure><p>7 批处理启动</p><p>Execute a bash script for starting booker machine with ordering</p><p><strong>Cluster failover and verification</strong></p><p>failover 多节点 主从集群 故障迁移</p>]]></content>
<summary type="html">
<p>How it works</p>
<p>It uses <a href="http://zookeeper.apache.org/" target="_blank" rel="noopener">Apache ZooKeeper</a> to coordinate whic
</summary>
<category term="Zookeeper" scheme="https://wuhewuhe.github.io/categories/Zookeeper/"/>
<category term="ActiveMq" scheme="https://wuhewuhe.github.io/categories/Zookeeper/ActiveMq/"/>
<category term="master" scheme="https://wuhewuhe.github.io/tags/master/"/>
<category term="slave" scheme="https://wuhewuhe.github.io/tags/slave/"/>
<category term="failover" scheme="https://wuhewuhe.github.io/tags/failover/"/>
</entry>
<entry>
<title>IO 面试</title>
<link href="https://wuhewuhe.github.io/2020/03/01/io/"/>
<id>https://wuhewuhe.github.io/2020/03/01/io/</id>
<published>2020-03-01T20:47:56.000Z</published>
<updated>2020-03-01T20:49:37.482Z</updated>
<content type="html"><![CDATA[<ol><li>什么是比特(Bit), 什么是字节(Byte), 什么是字符(Char), 它们长度是多少, 各有什么区别</li></ol><p>答案</p><p>Bit最小的二进制单位 ,是计算机的操作部分 取值0或者1<br>Byte是计算机操作数据的最小单位由8位bit组成 取值(-128-127)<br>Char是用户的可读写的最小单位,在Java里面由16位bit组成 取值(0-65535)</p><p>Bit 是最小单位 计算机 只能认识 0或者1</p><p>8个字节 是给计算机看的<br>字符 是看到的东西 一个字符=二个字节</p><p>2. 什么是流, 按照传输的单位, 分成哪两种流, 并且他们的父类叫什么流是指数据的传输</p><p>答案</p><p>字节流,字符流 <br>字节流:InputStream OutputStream<br>字符流:Reader Writer</p><ol start="3"><li>流按照传输的方向可以分为哪两种, 分别举例说明</li></ol><p>答案</p><p>输入输出相对于程序<br>输入流InputStream<br>,输出流OutputStream</p><ol start="4"><li>按照实现功能分为哪两种, 分别举例说明</li></ol><p>答案</p><p>节点流,处理流<br>节点流:OutputStream<br>处理流: OutputStreamWriter</p><p>5. BufferedReader属于哪种流, 它主要是用来做什么的, 它里面有那些经典的方法</p><p>答案</p><p>属于处理流中的缓冲流,可以将读取的内容存在内存里面,有readLine()方法</p><p>6. 什么是节点流, 什么是处理流, 它们各有什么用处, 处理流的创建有什么特征</p><p>答案</p><p>节点流 直接与数据源相连,用于输入或者输出<br>处理流:在节点流的基础上对之进行加工,进行一些功能的扩展<br>处理流的构造器必须要 传入节点流的子类</p><p>7. 如果我要对字节流进行大量的从硬盘读取, 要用那个流, 为什么</p><p>答案</p><p>BufferedInputStream 使用缓冲流能够减少对硬盘的损伤</p><p>8. 如果我要打印出不同类型的数据到数据源, 那么最适合的流是那个流, 为什么</p><p>答案</p><p>Printwriter 可以打印各种数据类型</p><p>9. 怎么样把我们控制台的输出改成输出到一个文件里面, 这个技术叫什么</p><p>答案</p><p>SetOut(printWriter, printStream)重定向</p><p>11. 怎么样把输出字节流转换成输出字符流, 说出它的步骤</p><p>答案</p><p>使用 转换处理流OutputStreamWriter 可以将字节流转为字符流<br>New OutputStreamWriter(new FileOutputStream(File file));</p><p>12. 把包括基本类型在内的数据和字符串按顺序输出到数据源,或者按照顺序从数据源读入,一般用哪两个流</p><p>答案</p><p>DataInputStream DataOutputStream</p><p>13. 把一个对象写入数据源或者从一个数据源读出来, 用哪两个流</p><p>答案</p><p>ObjectInputStream ObjectOutputStream</p><p>14. 什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作</p><p>答案</p><p>对象序列化,将对象以二进制的形式保存在硬盘上<br>反序列化;将二进制的文件转化为对象读取<br>实现serializable接口</p><p>不想让字段放在硬盘上就加transient</p><p>15. 如果在对象序列化的时候不想给一个字段的数据保存在硬盘上面, 采用那个关键字?</p><p>答案</p><p>transient关键字</p><p>16. 在实现序列化接口是时候一般要生成一个serialVersionUID字段, 它叫做什么, 一般有什么用</p><p>答案</p><p>是版本号,要保持版本号的一致 来进行序列化</p><p>为了防止序列化出错</p><ol start="17"><li>InputStream里的read()返回的是什么, read(byte[] data)是什么意思, 返回的是什么值</li></ol><p>答案</p><p>返回的是所读取的字节的int型(范围0-255)<br>read(byte [ ] data)将读取的字节储存在这个数组<br>返回的就是传入数组参数个数</p><p>Read 字节读取字节 字符读取字符</p><p>18. OutputStream里面的write()是什么意思, write(byte b[], int off, int len)这个方法里面的三个参数分别是什么意思</p><p>答案</p><p>write将指定字节传入数据源<br>Byte b[ ]是byte数组<br>b[off]是传入的第一个字符<br>b[off+len-1]是传入的最后的一个字符 <br>len是实际长度</p><p>19. 流一般需要不需要关闭, 如果关闭的话在用什么方法, 一般要在那个代码块里面关闭比较好,处理流是怎么关闭的,如果有多个流互相调用传入是怎么关闭的?</p><p>答案</p><p>流一旦打开就必须关闭,使用close方法<br>放入finally语句块中(finally 语句一定会执行)<br>调用的处理流就关闭处理流<br>多个流互相调用只关闭最外层的流</p><p>20. Java中的所有的流可以分为几大类, 它们的名字是什么, 各代表什么</p><p>答案</p><p>分为 字节输入流 InputStream <br>字节输出流 OutputStream<br>字符输入流 Reader<br>字符输出流 Writer<br>所有流都是这四个流的子类</p><p>说下常用的io流</p><p>Icon<br>InputStream, OutputStream,<br>FileInputStream, FileOutputStream,<br>BufferedInputStream, BufferedOutputStream<br>Reader, Writer<br>BufferedReader, BufferedWriter</p><p>21 写一段代码读取一个序列化的对象一般使用哪种Stream?</p><p>Icon<br>A、InputStream B、FileReader C、DataInputStream D、ObjectStream</p><p>22 io流怎样读取文件的?</p><p>Icon<br>使用File对象获取文件路径,通过字符流Reader加入文件,使用字符缓存流BufferedReader处理Reader,再定义一个字符串,循环遍历出文件。代码如下:<br>File file = new File(“d:/spring.txt”);<br>try {<br>Reader reader = new FileReader(file);<br>BufferedReader buffered = new BufferedReader(reader);<br>String data = null;<br>while((data = buffered.readLine())!=null){<br>System.out.println(data);<br>}<br>} catch (FileNotFoundException e) {<br>e.printStackTrace();<br>} catch (IOException e) {<br>e.printStackTrace();<br>}</p><p>23 说说你对io流的理解</p><p>Icon<br>Io流主要是用来处理输入输出问题,常用的io流有InputStream,OutputStream,Reader,Writer等</p><p>24 JAVA的IO流和readLine方法</p><p>Icon<br>Java的io流用来处理输入输出问题,readLine是BufferedReader里的一个方法,用来读取一行。</p><p>25 用什么把对象动态的写入磁盘中,写入要实现什么接口。</p><p>Icon<br>ObjectInputStream,需要实现Serializable接口<br>26 FileInputStream 创建详情,就是怎样的创建不报错,它列出了几种形式!</p><p>Icon<br>FileInputStream是InputStream的子类,通过接口定义,子类实现创建FileInputStream,</p><p>27 用io流中的技术,指定一个文件夹的目录,获取此目录下的所有子文件夹路径</p><p>28 请问你在什么情况下会在你得java代码中使用可序列化? 如何实现java序列化?</p><p>Icon<br>把一个对象写入数据源或者从一个数据源读出来,使用可序列化,需要实现Serializable接口</p><p>28 PrintStream、BufferedWriter、PrintWriter的比较? <br>PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream<br>BufferedWriter: 将文本写入字符输出流,缓冲各个字符从而提供单个字符,数组和字符串的高效写入。通过write()方法可以将获取到的字符输出,然后通过newLine()进行换行操作。BufferedWriter中的字符流必须通过调用flush方法才能将其刷出去。并且BufferedWriter只能对字符流进行操作。如果要对字节流操作,则使用BufferedInputStream。<br> PrintWriter的println方法自动添加换行,不会抛异常,若关心异常,需要调用checkError方法看是否有异常发生,PrintWriter构造方法可指定参数,实现自动刷新缓存(autoflush);</p>]]></content>
<summary type="html">
<ol>
<li>什么是比特(Bit), 什么是字节(Byte), 什么是字符(Char), 它们长度是多少, 各有什么区别</li>
</ol>
<p>答案</p>
<p>Bit最小的二进制单位 ,是计算机的操作部分 取值0或者1<br>
Byte是计算机操作数据的最小单位由8
</summary>
<category term="InputStream" scheme="https://wuhewuhe.github.io/categories/InputStream/"/>
<category term="byteinputstream" scheme="https://wuhewuhe.github.io/tags/byteinputstream/"/>
<category term="filterinput" scheme="https://wuhewuhe.github.io/tags/filterinput/"/>
<category term="datainputstream" scheme="https://wuhewuhe.github.io/tags/datainputstream/"/>
<category term="bufferinputstream" scheme="https://wuhewuhe.github.io/tags/bufferinputstream/"/>
</entry>
<entry>
<title>数据持久话</title>
<link href="https://wuhewuhe.github.io/2020/03/01/persistance/"/>
<id>https://wuhewuhe.github.io/2020/03/01/persistance/</id>
<published>2020-03-01T17:00:59.000Z</published>
<updated>2020-03-01T20:45:43.746Z</updated>
<content type="html"><![CDATA[<p>MQ realibiltity and high available</p><p>1 transaction</p><p>2 persistance ->. Mq 自身携带</p><p>3 acknowledge</p><p>4 可持久化</p><p>mq服务器和数据库服务器不在同一个机器,但是我们可以将mq的数据备份存储到一个特定的db</p><p>实现: jdbc,kahadb in default, jdbc message store with activemq journal</p><p>activemq将消息发送出去后,首先保存在本地数据文件,内存数据库,远程数据库,再试图将消息发送给接收者,否者存储中删除,失败继续尝试发送</p><p>消息中心启动后,首先要检查存储位置。</p><h4 id="kahadb-基于日志的存储">kahadb 基于日志的存储</h4><p>KahaDB is a file based persistence database that is local to the message broker that is using it. It has been optimized for fast persistence. It is the the default storage mechanism since <strong>ActiveMQ 5.4</strong>. KahaDB uses less file descriptors and provides faster recovery than its predecessor, the <a href="https://activemq.apache.org/amq-message-store" target="_blank" rel="noopener">AMQ Message Store</a>.</p><h2 id="Configuration">Configuration</h2><p>To use KahaDB as the broker’s persistence adapter configure ActiveMQ as follows (example):</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><broker brokerName="broker"></span><br><span class="line"> <persistenceAdapter></span><br><span class="line"> <kahaDB directory="activemq-data" journalMaxFileLength="32mb"/></span><br><span class="line"> </persistenceAdapter></span><br><span class="line"></broker></span><br></pre></td></tr></table></figure><p><strong>kahadb 存储原理</strong></p><p>数据存储在datalog文件中,数据不需要时删除或者归档</p><p>事务日志和索引</p><p>1 db-number.log存储消息记录到文件中,当到达32mb时创建一个新的文件</p><p>binary tree index。 redo用于恢复索引 lock写读</p><h4 id="JDBC-消息存储">JDBC 消息存储</h4><p>1 mq+mysql</p><p>2 lib + jdbc driver</p><p>3 configuration of jdbc</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><persistenceAdapter> </span><br><span class="line"> <jdbcPersistenceAdapter dataSource="#my-ds"createTableOnStartup =true/> </span><br><span class="line"></persistenceAdapter></span><br></pre></td></tr></table></figure><p>4 database pool configuration</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><bean id="mysql-ds" class="org.apache.commons.dbcp.Basi cDataSource" destroy-method="close"></span><br><span class="line"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/></span><br><span class="line"> <property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true"/></span><br><span class="line"> <property name="username" value="root"/></span><br><span class="line"> <property name="password" value="156324_Julien"/></span><br><span class="line"> <property name="poolPreparedStatements" value="true"/></span><br><span class="line"></bean></span><br></pre></td></tr></table></figure><p>5 建仓库建table</p><p>create database activemq</p><p>Activemq_msgs:</p><p>Id, container, msgid_prod, msg_seq, expiration, msg, proprity</p><p>Activemq_acks</p><p>activemq_ack, container, sub_dest, client_id, subname, selector, last_acked_id</p><p>Activemq_lock</p><p>id, broker</p><p>6 代码运行验证</p><p>deliverymode.persistent</p><ul><li><p>queue : 开启持久化,否则不会写到数据库</p></li><li><p>Topic : 先启动consumer</p></li></ul><p>7 database</p><ul><li>queue</li></ul><p>Producer : activemq_msg stock to mysql</p><p>Consumer: activemq_msg release message</p><ul><li>topic</li></ul><p>Producer: active_mgs存储所有消息,不会释放</p><p>Consumer: 有一个人activer subscriber</p><p>8 开发注意</p><ul><li><p>jar包 数据库驱动</p></li><li><p>createTableOnStartup 启动时创建表</p></li><li><p>Java.lang.illegalStateException: beanfactory not initialed or already closed can not contains _</p></li></ul><p>9 high perform journal</p><p>o achieve high performance of durable messaging in ActiveMQ V4.x we strongly recommend you use our high performance journal - which is enabled by default. This works rather like a database; messages (and transcation commits/rollbacks and message acknowledgements) are written to the journal as fast as is humanly possible - then at intervals we checkpoint the journal to the long term persistence storage (in this case JDBC).</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><beans xmlns="http://www.springframework.org/schema/beans" </span><br><span class="line"> xmlns:amq="http://activemq.apache.org/schema/core" </span><br><span class="line"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </span><br><span class="line"> xsi:schemaLocation="http://www.springframework.org/schema/beans </span><br><span class="line"> http://www.springframework.org/schema/beans/spring-beans-2.0.xsd </span><br><span class="line"> http://activemq.apache.org/schema/core </span><br><span class="line"> http://activemq.apache.org/schema/core/activemq-core.xsd"> </span><br><span class="line"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> </span><br><span class="line"> <broker useJmx="true" xmlns="http://activemq.apache.org/schema/core"> </span><br><span class="line"> <networkConnectors> </span><br><span class="line"> <!-- <networkConnector uri="multicast://default?initialReconnectDelay=100" /> <networkConnector uri="static://(tcp://localhost:61616)" /> --> </span><br><span class="line"> </networkConnectors> </span><br><span class="line"> <persistenceFactory></span><br><span class="line"> <journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/target" /> </span><br><span class="line"> <!-- To use a different dataSource, use the following syntax : --> </span><br><span class="line"> <!-- <journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/activemq-data" dataSource="#mysql-ds"/> --> </span><br><span class="line"> </persistenceFactory> </span><br><span class="line"> <transportConnectors> </span><br><span class="line"> <transportConnector uri="tcp://localhost:61636" /> </span><br><span class="line"> </transportConnectors> </span><br><span class="line"> </broker> </span><br><span class="line"> <!-- MySql DataSource Sample Setup --> </span><br><span class="line"> <!-- </span><br><span class="line"> <bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> </span><br><span class="line"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> </span><br><span class="line"> <property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/> </span><br><span class="line"> <property name="username" value="activemq"/> </span><br><span class="line"> <property name="password" value="activemq"/> </span><br><span class="line"> <property name="poolPreparedStatements" value="true"/> </span><br><span class="line"> </bean> </span><br><span class="line"> --> </span><br><span class="line"></beans></span><br></pre></td></tr></table></figure><p>日志不会立刻同步到数据库中,如果1000条消息,消费900条,则日志仅仅同步剩余100条到数据库</p><h4 id="总结">总结</h4><p>持久化消息: when server is down, the message will not be losted</p><p>Mq : high perform journal, kahadb, levelDB + zookeeper可复制存储的集群方案</p>]]></content>
<summary type="html">
<p>MQ realibiltity and high available</p>
<p>1 transaction</p>
<p>2 persistance -&gt;. Mq 自身携带</p>
<p>3 acknowledge</p>
<p>4 可持久化</p>
<
</summary>
<category term="persistance" scheme="https://wuhewuhe.github.io/categories/persistance/"/>
<category term="kahadb" scheme="https://wuhewuhe.github.io/tags/kahadb/"/>
<category term="jdbc" scheme="https://wuhewuhe.github.io/tags/jdbc/"/>
<category term="jounaling" scheme="https://wuhewuhe.github.io/tags/jounaling/"/>
</entry>
<entry>
<title>JMS protocol</title>
<link href="https://wuhewuhe.github.io/2020/03/01/jms-contract/"/>
<id>https://wuhewuhe.github.io/2020/03/01/jms-contract/</id>
<published>2020-03-01T16:25:56.000Z</published>
<updated>2020-03-01T16:58:35.424Z</updated>
<content type="html"><![CDATA[<p>ActiveMQ is designed to support mutliple different <a href="https://activemq.apache.org/topologies" target="_blank" rel="noopener">topologies</a> and protocols. Which one you use depends on your messaging requirements, quality of service and network topology.</p><p>Protocol : TCP; NIO; UDP; SSL; Http(s); VM</p><p>传输协议不一样,配置和性能也不一样</p><p>1 how to modify</p><p>open activemq.xml</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><transportConnectors></span><br><span class="line"> <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB --></span><br><span class="line"> <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/></span><br><span class="line"> <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/></span><br><span class="line"> <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/></span><br><span class="line"> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/></span><br><span class="line"> <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/></span><br><span class="line"> </transportConnectors></span><br></pre></td></tr></table></figure><p>activemq in default is open write means tcp ip</p><p>and it has others protocol like amqp, stomp, ws</p><ul><li>transmission control protocol</li></ul><p>默认broker配置,监听端口号61616,在网络传输数据前必须要序列化数据,消息是通过一个write ptotocol来序列化成字节流</p><p>url like tcp://hostanme; port?key=value&value=value</p><ul><li>NIO new io protocol</li></ul><p>Which may have better performance</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><transportConnectors></span><br><span class="line"> <transportConnector name="nio" uri="nio://0.0.0.0:61616"/> </span><br><span class="line"> </<transportConnectors></span><br></pre></td></tr></table></figure><p>Trying to use nio transport url on the client side will instantiate the regular TCP transport</p><p>he difference is that it is implemented using NIO API which can help with performance and scalability. NIO is a server side transport option only. Trying to use it on the client side will instantiate the regular TCP transport.</p><ul><li>modify activemq.xml</li></ul><p>backup modify transport protocol</p><ul><li>modify producer and consumer code</li></ul><p>NIO 61618</p><ul><li>Nio 增强</li></ul><p>One of the main advantages of using NIO instead of the regular versions of the transport is that it can scale better and support larger number of connections. The main limit in this scenario is the number of threads the system in using. In blocking implementations of the transports, one thread is used per connection. In the NIO implementation, there’s a shared pool of threads that will take the load, so that number of connections are not directly related to the number of threads used in the system.</p><p>Origin is BIO + TCP = NIO + TCP</p><p><strong>如何让nio支持所有的协议?</strong></p><p>enable : auto</p><ul><li>AMPQ advance message queue protocol</li><li>stmop streaming text orient messaging protocol</li><li>mqtt IBM message queue templating transport</li></ul>]]></content>
<summary type="html">
<p>ActiveMQ is designed to support mutliple different <a href="https://activemq.apache.org/topologies" target="_blank" rel="noopener">topolo
</summary>
<category term="Transport" scheme="https://wuhewuhe.github.io/categories/Transport/"/>
<category term="nio" scheme="https://wuhewuhe.github.io/tags/nio/"/>
<category term="tcp" scheme="https://wuhewuhe.github.io/tags/tcp/"/>
</entry>
<entry>
<title>Broker Spring and Springboot 整合</title>
<link href="https://wuhewuhe.github.io/2020/03/01/broker/"/>
<id>https://wuhewuhe.github.io/2020/03/01/broker/</id>
<published>2020-03-01T15:12:08.000Z</published>
<updated>2020-03-01T16:24:58.510Z</updated>
<content type="html"><![CDATA[<p>Broker</p><p>用代码的形式启动activemq,将mq嵌入到代码里,以便随时的启动,在用的时候启动节省资源,保证可靠性</p><p>instance a server activemq in java</p><p>嵌入式broker</p><p>BrokerService brokerservice = new BrokerService :</p><p>brokerservice.setUseJms(true);</p><p>brokerservice.addConnector(buildadress “tcp/ip//localhost:61616”)</p><p>brokerservice.start()</p><p>Spring整合activemq</p><p>1 Add dependency to spring pom.xml</p><p>2 modify applicationContext.xml: configuarion producer,</p><ul><li><p><strong>property</strong> url</p></li><li><p>Destination : queue</p></li><li><p>jms template</p></li></ul><p>3 queue</p><p>spring producer</p><p>@service</p><p>@AutoWired jmstemplate</p><p>getbean(spring_producer)</p><p>Produce.jmsTemplate.send(Messagecreator{</p><p>Session -> text message = session.createTextmessage(“sss”);</p><p>})</p><p>spring consumer</p><p>@Service</p><p>@AutoWired jmstemplate</p><p>getbean(spring_consumer)</p><p>Consumer.jmstemplate.receiveAndConvert()</p><p>4 topic</p><p>change destination from queue to topic</p><p>start consumer then start producer</p><p>5 listener</p><p>Modify configuration : add jmscontainer bean who has propertity message listener, connectionfactory and destination</p><p>on message try catch</p><p>Add component</p><p>消费者不启动直接通过配置监听完成</p><p>springboot 如何整合activemq</p><ul><li>queue</li></ul><p><strong>Producer</strong></p><p>1 new maven project</p><p>2 add dependency to pom.xml 2.1.5 springboot, activemq</p><p>3 application.yml</p><p>server port;</p><p>spring: activemq: broker-url, user, password,</p><p>Jms pub-sub-domain: false = queue true = topic</p><p>My queue : customize name</p><p>4 configuration bean</p><p>Component.instance myqueue</p><p>5 queue produce</p><p>@Component</p><p>@EnableJMS</p><p>@autowired</p><p>jmstemplate, queue</p><p>producemsg{</p><p>Jmstemplate.convertandsend(queue, “text”)}</p><p>6 main app</p><p>@springbootapplication</p><p>7 test unit</p><p>@SpringbootTest(class = main app_produce.calss)</p><p>@runwith(springJunit4Classrunner.class)</p><p>@webappConfiguration</p><p>Produce_msg()</p><p><strong>springboot producer 隔定投</strong></p><p>每间隔三秒钟,往mq发送一条消息</p><p>@schduled(fixedDelay = 3000)</p><p>@enableschduling</p><p>start main app</p><p><strong>consumer</strong></p><p>同理可见producer</p><p>1 queue Consume</p><p>@Component</p><p>@jmslistener destination (queue)</p><p>@receive sychrono</p><ul><li>topic</li></ul><p>modify</p><p>pub-sub-domain: true</p><p>1 topic bean</p><p>@Component</p><p>@vlalue(my topic)</p><p>@Bean</p><p>new activemqTopic(topic name)</p><p>2 topic</p><ul><li>producer</li></ul><p>@component</p><p>@autowired</p><p>@jmstemplate</p><p>@schduled(fixdelay = 3000)</p><p>Jmstemplate.convertandsend("")</p><p>3 main app</p><ul><li>consumer</li></ul><p>consumer topic</p><p>@component</p><p>@jmslistener (topic)</p><p>Receive();</p><p>2 simulate 2 subscriber</p><p>mainapp 5555 5566</p>]]></content>
<summary type="html">
<p>Broker</p>
<p>用代码的形式启动activemq,将mq嵌入到代码里,以便随时的启动,在用的时候启动节省资源,保证可靠性</p>
<p>instance a server activemq in java</p>
<p>嵌入式broker</p>
<p>Brok
</summary>
<category term="Broker" scheme="https://wuhewuhe.github.io/categories/Broker/"/>
<category term="Spring" scheme="https://wuhewuhe.github.io/categories/Broker/Spring/"/>
<category term="SpringBoot" scheme="https://wuhewuhe.github.io/categories/Broker/Spring/SpringBoot/"/>
<category term="queue" scheme="https://wuhewuhe.github.io/tags/queue/"/>
<category term="topic" scheme="https://wuhewuhe.github.io/tags/topic/"/>
<category term="bean" scheme="https://wuhewuhe.github.io/tags/bean/"/>
<category term="producer" scheme="https://wuhewuhe.github.io/tags/producer/"/>
<category term="consumer" scheme="https://wuhewuhe.github.io/tags/consumer/"/>
</entry>
<entry>
<title>redis</title>
<link href="https://wuhewuhe.github.io/2020/03/01/redis/"/>
<id>https://wuhewuhe.github.io/2020/03/01/redis/</id>
<published>2020-03-01T14:38:52.000Z</published>
<updated>2020-03-01T15:12:02.138Z</updated>
<content type="html"><![CDATA[<p>二者的区别<br>RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是 fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储</p><p>AOF 持久化以日志的形式记录服务器所处理的每一个增删改操作,以文本的方式记录,可以打开文件看到详细的操作记录</p><p>二者优缺点<br>RDB 优势<br>RDB 会生成多个数据文件,每个数据文件都代表了某一个时刻中 Redis 的数据,这种多个数据文件的方式。比如,可能打算每个小时归档一次最近 24 小时的数据,同时还要每天归档一次最近 30 天的数据。通过这样的备份策略,一旦系统出现灾难性故障,可以非常容易的进行恢复。同时,可以将这种完整的数据文件压缩后发送到一些远程的安全存储上去。适合做冷备</p><p>直接基于 RDB 数据文件来重启和恢复 Redis 进程,恢复效率会更高</p><p>RDB 对 Redis 对外提供的读写服务,影响非常小,可以让 Redis 保持高性能,因为 Redis 主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化</p><p>RDB 劣势<br>如果想保证数据的高可用性,即最大限度的避免数据丢失,那么 RDB 将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失</p><p>由于 RDB 是通过 fork 子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是 1 秒钟<br>一般不要让 RDB 的间隔太长,否则每次生成的 RDB 文件太大了,对 Redis 本身的性能也会有影响</p><p>AOF 优势<br>该机制可以带来更高的数据安全性。Redis 提供了 3 种同步策略:每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言</p><p>由于该机制对日志文件的写入操作采用的是 append 模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半数据就出现了系统崩溃问题,在 Redis 下一次启动之前,可以通过 redis-check-aof 工具来帮助解决数据一致性的问题</p><p>如果日志过大,Redis 可以自动启用 rewrite 机制(后台重写,不影响客户端的读写)。即 Redis 以 append 模式不断的将修改数据写入到老的磁盘文件中,同时 Redis 还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行 rewrite 切换时可以更好的保证数据安全性</p><p>AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用 flushall 命令清空了所有数据,只要这个时候后台 rewrite 还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条 flushall 命令给删了,然后再将该 AOF 文件放回去,就可以通过恢复机制,自动恢复所有数据</p><p>AOF 劣势<br>对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大,靠重写来弥补</p><p>AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低,因为要将命令写到 AOF 缓冲区。此外,还要定时 fsync 一次日志文件</p><p>通过回放 AOF 日志中的写入指令来重新构建整个数据集,数据恢复速度比较慢</p><p>定期的备份需要自己手写脚本去做,做冷备不太合适</p><p>以前 AOF 发生过 bug,就是通过 AOF 记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以,类似 AOF 这种较为复杂的基于命令日志回放的方式,比基于 RDB 每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有 bug。不过 AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多</p><p>二者选择的标准<br>不要仅仅使用 RDB,因为那样会导致丢失数据<br>也不要仅仅使用 AOF,因为那样有两个问题,第一,通过 AOF 做冷备,没有 RDB 做冷备,恢复速度快;第二,RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug<br>综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择;用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复</p>]]></content>
<summary type="html">
<p>二者的区别<br>
RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是 fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储</p>
<p>AOF 持久化以日志的形式记录服务器所处理的每一个增删改操作,以
</summary>
<category term="Redis" scheme="https://wuhewuhe.github.io/categories/Redis/"/>
<category term="RDB" scheme="https://wuhewuhe.github.io/tags/RDB/"/>
<category term="AOF" scheme="https://wuhewuhe.github.io/tags/AOF/"/>
</entry>
</feed>