-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
1074 lines (741 loc) · 596 KB
/
atom.xml
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
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Awebone's Blog</title>
<subtitle>见多方能识广,进而才可以融会贯通;取他人之所长,谦而才可以为我所用。</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://www.awebone.com/"/>
<updated>2020-08-03T07:15:57.507Z</updated>
<id>https://www.awebone.com/</id>
<author>
<name>Awebone</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Docker和K8S容器监控</title>
<link href="https://www.awebone.com/posts/194a5065/"/>
<id>https://www.awebone.com/posts/194a5065/</id>
<published>2020-07-31T07:00:00.000Z</published>
<updated>2020-08-03T07:15:57.507Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文记录Docker容器和K8S集群中一些监控命令。</p></blockquote><h1 id="Docker基本监控"><a href="#Docker基本监控" class="headerlink" title="Docker基本监控"></a>Docker基本监控</h1><p><strong>自带常用命令</strong></p><ul><li><code>docker ps -a</code>:查看进程</li><li><code>docker top 容器id</code>:查看容器资源利用</li><li><code>docker status</code>:实时查看容器资源</li></ul><p><strong>图形化工具weavescope</strong></p><p>部署</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo curl -L git.io/scope -o /usr/<span class="built_in">local</span>/bin/scope</div><div class="line">sudo chmod +x /usr/<span class="built_in">local</span>/bin/scope</div><div class="line">scope launch 本机ip</div></pre></td></tr></tbody></table></figure><a id="more"></a><p><br></p><h1 id="K8S监控"><a href="#K8S监控" class="headerlink" title="K8S监控"></a>K8S监控</h1><h2 id="计算资源分析与监控工具:heapster-dashboard-grafana"><a href="#计算资源分析与监控工具:heapster-dashboard-grafana" class="headerlink" title="计算资源分析与监控工具:heapster + dashboard + grafana"></a>计算资源分析与监控工具:heapster + dashboard + grafana</h2><p>部署:下载heapster 包,进入deploy目录,修改相关yaml文件,启动。</p><h2 id="集群自动伸缩设置"><a href="#集群自动伸缩设置" class="headerlink" title="集群自动伸缩设置"></a>集群自动伸缩设置</h2><p>集群cpu或内存达到一定峰值,自动扩容pod</p><p><img src="/images/Docker和K8S容器监控/1596177920787.png" alt="1596177920787"></p><p>启用heapster,然后在集群启动时获取cpu利用率等情况,运行以下命令:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">minikube addons <span class="built_in">enable</span> heapster</div><div class="line">minikube addons list</div><div class="line">minikube start --extra-config=controller-manager.HorizontalPodAutoscalerUseRESTClients=<span class="literal">false</span></div></pre></td></tr></tbody></table></figure><p><img src="/images/Docker和K8S容器监控/1596179129619.png" alt="1596179129619"></p><p>然后按照官方文档设置水平扩展,cpu利用率超过50%即扩展,机器最少1台,最多10台</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80</div><div class="line">kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10</div><div class="line">kubectl get deployment php-apache</div><div class="line">kubectl get horizontalpodautoscaler</div></pre></td></tr></tbody></table></figure><p><br></p><h2 id="log采集和展示:ELK-Fluentd"><a href="#log采集和展示:ELK-Fluentd" class="headerlink" title="log采集和展示:ELK+Fluentd"></a>log采集和展示:ELK+Fluentd</h2><p>部署</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">kubectl get node</div><div class="line">kubectl label node --all beta.kubernetes.io/fluentd-ds-ready=<span class="literal">true</span></div><div class="line">kubectl create <span class="_">-f</span> logging/</div><div class="line">kubectl get svc --namespace=kube-system</div></pre></td></tr></tbody></table></figure><p><br></p><h2 id="K8S集群监控方案:婆罗米修斯Prometheus"><a href="#K8S集群监控方案:婆罗米修斯Prometheus" class="headerlink" title="K8S集群监控方案:婆罗米修斯Prometheus"></a>K8S集群监控方案:婆罗米修斯Prometheus</h2><p>部署</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">kubectl get node</div><div class="line">kubectl create <span class="_">-f</span> prometheus/</div><div class="line">kubectl get svc</div><div class="line">kubectl get pod -o wide</div></pre></td></tr></tbody></table></figure><p><br></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文记录Docker容器和K8S集群中一些监控命令。</p>
</blockquote>
<h1 id="Docker基本监控"><a href="#Docker基本监控" class="headerlink" title="Docker基本监控"></a>Docker基本监控</h1><p><strong>自带常用命令</strong></p>
<ul>
<li><code>docker ps -a</code>:查看进程</li>
<li><code>docker top 容器id</code>:查看容器资源利用</li>
<li><code>docker status</code>:实时查看容器资源</li>
</ul>
<p><strong>图形化工具weavescope</strong></p>
<p>部署</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo curl -L git.io/scope -o /usr/<span class="built_in">local</span>/bin/scope</div><div class="line">sudo chmod +x /usr/<span class="built_in">local</span>/bin/scope</div><div class="line">scope launch 本机ip</div></pre></td></tr></tbody></table></figure>
</summary>
<category term="Linux" scheme="https://www.awebone.com/categories/Linux/"/>
<category term="Docker" scheme="https://www.awebone.com/tags/Docker/"/>
</entry>
<entry>
<title>数据结构与算法JavaScript版(一)</title>
<link href="https://www.awebone.com/posts/742c7f0a/"/>
<id>https://www.awebone.com/posts/742c7f0a/</id>
<published>2020-07-18T07:00:00.000Z</published>
<updated>2020-07-18T12:58:51.723Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用JavaScript实现基础数据结构:数组、链表、栈、队列、树</p></blockquote><h1 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h1><ul><li>在数组的<strong>末尾插入/删除</strong>、<strong>更新</strong>、<strong>获取</strong>某个位置的元素,都是 O(1) 的时间复杂度</li><li>在数组的任何其它地方<strong>插入/删除</strong>元素,都是 O(n) 的时间复杂度</li><li>空间复杂度:O(n)</li></ul><h2 id="数组创建"><a href="#数组创建" class="headerlink" title="数组创建"></a>数组创建</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> arr = <span class="keyword">new</span> <span class="built_in">Array</span>(element0, element1, ..., elementN);</div><div class="line"><span class="keyword">var</span> arr = <span class="built_in">Array</span>(element0, element1, ..., elementN);</div><div class="line"><span class="keyword">var</span> arr = [element0, element1, ..., elementN];</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr = <span class="keyword">new</span> <span class="built_in">Array</span>(arrayLength);</div><div class="line"><span class="keyword">var</span> arr = <span class="built_in">Array</span>(arrayLength);</div></pre></td></tr></tbody></table></figure><a id="more"></a><h2 id="常用数组方法"><a href="#常用数组方法" class="headerlink" title="常用数组方法"></a>常用数组方法</h2><h3 id="增加与删除"><a href="#增加与删除" class="headerlink" title="增加与删除"></a>增加与删除</h3><ul><li><p><code>push()</code>:在数组末尾添加一个或多个元素,并返回数组操作后的长度</p></li><li><p><code>unshift()</code>:在数组开头添加一个或多个元素,并返回数组的新长度</p></li><li><p><code>pop()</code>:从数组移出最后一个元素,并返回该元素</p></li><li><p><code>shift()</code>:从数组移出第一个元素,并返回该元素</p></li><li><p><code>splice(start_index, upto_index)</code>从数组提取一个片段,并作为一个新数组返回</p></li><li><p><code>splice(index, count_to_remove, addElement1, addElement2, ...)</code>从数组移出一些元素,(可选)并替换它们</p><p><code>number.splice(2,2)</code>删除从数组索引2开始2个元素</p><p><code>number.splice(2,0,1,2,3)</code>从数组索引5开始增加3个元素2,3,4</p></li></ul><p><img src="/images/js数据结构与算法1/1595052302829.png" alt="1595052302829"></p><h3 id="合并"><a href="#合并" class="headerlink" title="合并"></a>合并</h3><ul><li><code>concat()</code>:连接两个数组并返回一个新的数组</li></ul><p><img src="/images/js数据结构与算法1/1595053505788.png" alt="1595053505788"></p><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><ul><li><code>reverse()</code>:颠倒数组元素的顺序,第一个变成最后一个,最后一个变成第一个</li><li><code>sort()</code>:数组元素排序,也可以带一个回调函数来决定怎么比较数组元素</li></ul><p><img src="/images/js数据结构与算法1/1595053659661.png" alt="1595053659661"></p><p><img src="/images/js数据结构与算法1/1595053814196.png" alt="1595053814196"></p><h3 id="搜索"><a href="#搜索" class="headerlink" title="搜索"></a>搜索</h3><ul><li><code>indexOf(searchElement[, fromIndex])</code>:在数组中搜索<code>searchElement</code> 并返回第一个匹配的索引</li><li><code>lastIndexOf(searchElement[, fromIndex]</code>:和 <code>indexOf</code>差不多,但这是从结尾开始,并且是反向搜索</li></ul><p><img src="/images/js数据结构与算法1/1595054114155.png" alt="1595054114155"></p><h3 id="输出字符串"><a href="#输出字符串" class="headerlink" title="输出字符串"></a>输出字符串</h3><ul><li><code>toString()</code>:把数组里所有元素输出为一个字符串,默认逗号分隔</li><li><code>join(deliminator = ',')</code>:用指定分隔符把元素隔开,将数组的所有元素连接成一个字符串,默认逗号分隔</li></ul><p><img src="/images/js数据结构与算法1/1595054159709.png" alt="1595054159709"></p><h3 id="迭代器函数"><a href="#迭代器函数" class="headerlink" title="迭代器函数"></a>迭代器函数</h3><ul><li><p><code>forEach(callback[, thisObject])</code>:在数组每个元素项上执行<code>callback</code></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>];</div><div class="line">a.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">element</span>) </span>{ <span class="built_in">console</span>.log(element);} );</div></pre></td></tr></tbody></table></figure></li></ul><ul><li><p><code>map(callback[, thisObject])</code>:遍历数组,并通过<code>callback</code>对数组元素进行操作,并将所有操作结果放入数组中并返回该数组</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a1 = [<span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>];</div><div class="line"><span class="keyword">var</span> a2 = a1.map(<span class="function"><span class="keyword">function</span>(<span class="params">item</span>) </span>{ <span class="keyword">return</span> item.toUpperCase(); });</div><div class="line"><span class="built_in">console</span>.log(a2); <span class="comment">// logs A,B,C</span></div></pre></td></tr></tbody></table></figure></li></ul><ul><li><p><code>filter(callback[, thisObject])</code>:返回一个包含所有在回调函数上返回为<code>true</code>的元素的新数组,<code>callback</code>在这里担任的是过滤器的角色,当元素符合条件,过滤器就返回<code>true</code>,而<code>filter</code>则会返回所有符合过滤条件的元素</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a1 = [<span class="string">'a'</span>, <span class="number">10</span>, <span class="string">'b'</span>, <span class="number">20</span>, <span class="string">'c'</span>, <span class="number">30</span>];</div><div class="line"><span class="keyword">var</span> a2 = a1.filter(<span class="function"><span class="keyword">function</span>(<span class="params">item</span>) </span>{ <span class="keyword">return</span> <span class="keyword">typeof</span> item == <span class="string">'number'</span>; });</div><div class="line"><span class="built_in">console</span>.log(a2); <span class="comment">// logs 10,20,30</span></div></pre></td></tr></tbody></table></figure></li></ul><ul><li><p><code>every(callback[, thisObject])</code>:当数组中每一个元素在<code>callback</code>上被返回<code>true</code>时就返回<code>true</code>,<code>every</code>其实类似<code>filter</code>,只不过它的功能是判断是不是数组中的所有元素都符合条件,并且返回的是布尔值</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">isNumber</span>(<span class="params">value</span>)</span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> value == <span class="string">'number'</span>;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> a1 = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</div><div class="line"><span class="built_in">console</span>.log(a1.every(isNumber)); <span class="comment">// logs true</span></div><div class="line"><span class="keyword">var</span> a2 = [<span class="number">1</span>, <span class="string">'2'</span>, <span class="number">3</span>];</div><div class="line"><span class="built_in">console</span>.log(a2.every(isNumber)); <span class="comment">// logs false</span></div></pre></td></tr></tbody></table></figure></li></ul><ul><li><p><code>some(callback[, thisObject])</code>:只要数组中有一项在<code>callback</code>上被返回<code>true</code>,就返回<code>true</code>,类似<code>every</code>,不过前者要求都符合筛选条件才返回<code>true</code>,后者只要有符合条件的就返回<code>true</code></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">isNumber</span>(<span class="params">value</span>)</span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> value == <span class="string">'number'</span>;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> a1 = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</div><div class="line"><span class="built_in">console</span>.log(a1.some(isNumber)); <span class="comment">// logs true</span></div><div class="line"><span class="keyword">var</span> a2 = [<span class="number">1</span>, <span class="string">'2'</span>, <span class="number">3</span>];</div><div class="line"><span class="built_in">console</span>.log(a2.some(isNumber)); <span class="comment">// logs true</span></div><div class="line"><span class="keyword">var</span> a3 = [<span class="string">'1'</span>, <span class="string">'2'</span>, <span class="string">'3'</span>];</div><div class="line"><span class="built_in">console</span>.log(a3.some(isNumber)); <span class="comment">// logs false</span></div></pre></td></tr></tbody></table></figure></li></ul><ul><li><p><code>reduce(callback[, initialValue])</code>:使用回调函数 <code>callback(firstValue, secondValue)</code> 把数组列表计算成一个单一值,对数组元素两两递归处理的方式把数组计算成一个值</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a = [<span class="number">10</span>, <span class="number">20</span>, <span class="number">30</span>];</div><div class="line"><span class="keyword">var</span> total = a.reduce(<span class="function"><span class="keyword">function</span>(<span class="params">first, second</span>) </span>{ <span class="keyword">return</span> first + second; }, <span class="number">0</span>);</div><div class="line"><span class="built_in">console</span>.log(total) <span class="comment">// Prints 60</span></div></pre></td></tr></tbody></table></figure></li></ul><ul><li><code>reduceRight(callback[, initalvalue])</code>:和 <code>reduce()</code>相似,但这从最后一个元素开始的,应该使用在那些需要把数组的元素两两递归处理,并最终计算成一个单一结果的算法</li></ul><p><br></p><h1 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h1><ul><li>在链表的<strong>首部插入/移除结点</strong>、获得<strong>链表首部的值</strong>,都是O(1)时间复杂度</li><li>获取/移除/插入任一结点、尾部结点,都是O(n)时间复杂度</li></ul><h2 id="单链表结构图"><a href="#单链表结构图" class="headerlink" title="单链表结构图"></a>单链表结构图</h2><p><img src="/images/js数据结构与算法1/1595061903035.png" alt="1595061903035"></p><p><img src="/images/js数据结构与算法1/1595062001664.png" alt="1595062001664"></p><h3 id="插入示意图"><a href="#插入示意图" class="headerlink" title="插入示意图"></a>插入示意图</h3><p><img src="/images/js数据结构与算法1/1595065003973.png" alt="1595065003973"></p><h3 id="删除示意图"><a href="#删除示意图" class="headerlink" title="删除示意图"></a>删除示意图</h3><p><img src="/images/js数据结构与算法1/1595065020710.png" alt="1595065020710"></p><h2 id="单链表实例"><a href="#单链表实例" class="headerlink" title="单链表实例"></a>单链表实例</h2><p><strong>ES5实现:</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//节点</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">LinkNode</span>(<span class="params">element</span>) </span>{</div><div class="line"> <span class="keyword">this</span>.element = element; <span class="comment">//当前节点的元素</span></div><div class="line"> <span class="keyword">this</span>.next = <span class="literal">null</span>; <span class="comment">//下一个节点链接</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//链表类</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">LinkList</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">this</span>.head = <span class="literal">null</span>; <span class="comment">//头节点</span></div><div class="line"> </div><div class="line"> <span class="comment">//查看链表长度</span></div><div class="line"> <span class="keyword">this</span>.length = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">var</span> count = <span class="number">0</span></div><div class="line"> <span class="keyword">while</span> (currNode) {</div><div class="line"> count += <span class="number">1</span>;</div><div class="line"> currNode = currNode.next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> count;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//打印链表</span></div><div class="line"> <span class="keyword">this</span>.display = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">var</span> res = []</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">while</span> (currNode) {</div><div class="line"> res.push(currNode.element);</div><div class="line"> currNode = currNode.next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> res;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//判断链表是否为空</span></div><div class="line"> <span class="keyword">this</span>.isEmpty = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.head == <span class="literal">null</span>){</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//查找节点</span></div><div class="line"> <span class="keyword">this</span>.find = <span class="function"><span class="keyword">function</span>(<span class="params">item</span>)</span>{</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">while</span>(currNode && currNode.element !== item) {</div><div class="line"> currNode = currNode.next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> currNode;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//查找前一个节点</span></div><div class="line"> <span class="keyword">this</span>.findPrev = <span class="function"><span class="keyword">function</span>(<span class="params">item</span>)</span>{</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">while</span>(currNode && currNode.next !== <span class="literal">null</span> && currNode.next.element !== item) {</div><div class="line"> currNode = currNode.next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> currNode;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//头部插入节点</span></div><div class="line"> <span class="keyword">this</span>.add = <span class="function"><span class="keyword">function</span>(<span class="params">newElement</span>)</span>{</div><div class="line"> <span class="keyword">var</span> newNode = <span class="keyword">new</span> LinkNode(newElement);</div><div class="line"> newNode.next = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">this</span>.head = newNode;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.head;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//尾部插入节点</span></div><div class="line"> <span class="keyword">this</span>.append = <span class="function"><span class="keyword">function</span>(<span class="params">newElement</span>)</span>{</div><div class="line"> <span class="keyword">var</span> newNode = <span class="keyword">new</span> LinkNode(newElement);</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.head == <span class="literal">null</span>){</div><div class="line"> <span class="keyword">this</span>.head = newNode;</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">while</span> (currNode.next){</div><div class="line"> currNode = currNode.next;</div><div class="line"> }</div><div class="line"> currNode.next = newNode;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//删除节点</span></div><div class="line"> <span class="keyword">this</span>.remove = <span class="function"><span class="keyword">function</span>(<span class="params">item</span>)</span>{</div><div class="line"> <span class="keyword">var</span> prevNode = <span class="keyword">this</span>.findPrev(item);</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.find(item);</div><div class="line"> <span class="keyword">if</span>(prevNode.next !== <span class="literal">null</span>) {</div><div class="line"> prevNode.next = prevNode.next.next;</div><div class="line"> currNode.next = <span class="literal">null</span>;</div><div class="line"> }</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//链表反转</span></div><div class="line"> <span class="keyword">this</span>.reverse = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">var</span> prevNode = <span class="literal">null</span>;</div><div class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</div><div class="line"> <span class="keyword">while</span>(currNode) {</div><div class="line"> <span class="keyword">var</span> tmpNode = currNode.next;</div><div class="line"> currNode.next = prevNode;</div><div class="line"> prevNode = currNode;</div><div class="line"> currNode = tmpNode;</div><div class="line"> }</div><div class="line"> <span class="keyword">this</span>.head = prevNode</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.head</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>用例测试:</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">ll = <span class="keyword">new</span> LinkList()</div><div class="line">ll.add(<span class="number">1</span>)</div><div class="line">ll.add(<span class="number">2</span>)</div><div class="line">ll.add(<span class="number">3</span>)</div><div class="line">ll.append(<span class="number">1</span>)</div><div class="line">ll.remove(<span class="number">1</span>)</div><div class="line">ll.reverse()</div><div class="line"><span class="built_in">console</span>.log(ll.display())</div></pre></td></tr></tbody></table></figure><h2 id="双向链表结构图"><a href="#双向链表结构图" class="headerlink" title="双向链表结构图"></a>双向链表结构图</h2><p>双向链表和普通链表的区别在于,在链表中,一个节点只有链向下一个节点的链接,而在双向链表中,链接是双向的:一个链向下一个元素,另一个链向前一个元素。</p><p><img src="/images/js数据结构与算法1/1595064780983.png" alt="1595064780983"></p><h3 id="插入示意图-1"><a href="#插入示意图-1" class="headerlink" title="插入示意图"></a>插入示意图</h3><p><img src="/images/js数据结构与算法1/1595064910440.png" alt="1595064910440"></p><h3 id="删除示意图-1"><a href="#删除示意图-1" class="headerlink" title="删除示意图"></a>删除示意图</h3><p><img src="/images/js数据结构与算法1/1595064937011.png" alt="1595064937011"></p><p><br></p><h1 id="栈"><a href="#栈" class="headerlink" title="栈"></a>栈</h1><ul><li>栈满足<strong>后进先出 LIFO</strong>的原则</li><li>时间复杂度:压栈、出栈都是 O(1)</li></ul><h2 id="栈实例"><a href="#栈实例" class="headerlink" title="栈实例"></a>栈实例</h2><p><strong>ES5实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">Stack</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> data = [];</div><div class="line"> </div><div class="line"> <span class="comment">//向栈顶添加元素</span></div><div class="line"> <span class="keyword">this</span>.push = <span class="function"><span class="keyword">function</span>(<span class="params">element</span>)</span>{</div><div class="line"> data.push(element);</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//弹出栈顶的元素,若栈为空则报错</span></div><div class="line"> <span class="keyword">this</span>.pop = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.pop();</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//返回栈顶的元素(但是不弹出),若栈为空则报错</span></div><div class="line"> <span class="keyword">this</span>.peek = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data[data.length - <span class="number">1</span>];</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//判断栈是否为空</span></div><div class="line"> <span class="keyword">this</span>.isEmpty = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.length === <span class="number">0</span>;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//返回栈的长度</span></div><div class="line"> <span class="keyword">this</span>.size = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.length;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//清空栈</span></div><div class="line"> <span class="keyword">this</span>.clear = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> data = [];</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//打印栈元素</span></div><div class="line"> <span class="keyword">this</span>.print = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(data.toString());</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>用例测试:</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">s = <span class="keyword">new</span> Stack()</div><div class="line">s.push(<span class="number">1</span>)</div><div class="line">s.push(<span class="number">2</span>)</div><div class="line">s.push(<span class="number">3</span>)</div><div class="line"><span class="built_in">console</span>.log(s.pop())</div><div class="line"><span class="built_in">console</span>.log(s.peek())</div><div class="line"><span class="built_in">console</span>.log(s.isEmpty())</div><div class="line"><span class="built_in">console</span>.log(s.size())</div></pre></td></tr></tbody></table></figure><p><strong>ES6语法:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Stack</span> </span>{</div><div class="line"> <span class="keyword">constructor</span> () {</div><div class="line"> <span class="keyword">this</span>.data = [];</div><div class="line"> }</div><div class="line"> push(element){</div><div class="line"> <span class="keyword">this</span>.data.push(element);</div><div class="line"> }</div><div class="line"> pop(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.pop();</div><div class="line"> }</div><div class="line"> peek(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data[data.length - <span class="number">1</span>];</div><div class="line"> }</div><div class="line"> isEmpty(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.length === <span class="number">0</span>;</div><div class="line"> }</div><div class="line"> size(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.length;</div><div class="line"> }</div><div class="line"> clear(){</div><div class="line"> <span class="keyword">this</span>.data = [];</div><div class="line"> }</div><div class="line"> print(){</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.data.toString());</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h1><ul><li>队列满足<strong>先进先出 FIFO</strong> 的原则</li><li>时间复杂度:出队列使用了数组的 <code>shift()</code> 方法,故时间复杂度为 O(n);入队列采用了列表的 <code>push()</code> 方法,故时间复杂度为 O(1)</li></ul><h2 id="队列实例"><a href="#队列实例" class="headerlink" title="队列实例"></a>队列实例</h2><p><strong>ES5实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">Queue</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> data = [];</div><div class="line"> </div><div class="line"> <span class="comment">//将一个元素入队(在队尾添加元素)</span></div><div class="line"> <span class="keyword">this</span>.enqueue = <span class="function"><span class="keyword">function</span>(<span class="params">element</span>)</span>{</div><div class="line"> data.push(element);</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//将队首的元素出队,若队列为空则报错</span></div><div class="line"> <span class="keyword">this</span>.dequeue = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.shift();</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//返回队首元素,不出队</span></div><div class="line"> <span class="keyword">this</span>.front = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data[<span class="number">0</span>];</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//判断队列是否为空</span></div><div class="line"> <span class="keyword">this</span>.isEmpty = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.length === <span class="number">0</span>;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//清空队列</span></div><div class="line"> <span class="keyword">this</span>.clear = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> data = [];</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//返回队列长度</span></div><div class="line"> <span class="keyword">this</span>.size = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> data.length;</div><div class="line"> };</div><div class="line"> </div><div class="line"> <span class="comment">//打印队列元素</span></div><div class="line"> <span class="keyword">this</span>.print = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(data.toString());</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>用例测试:</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">q = <span class="keyword">new</span> Queue()</div><div class="line">q.enqueue(<span class="number">1</span>)</div><div class="line">q.enqueue(<span class="number">2</span>)</div><div class="line">q.enqueue(<span class="number">3</span>)</div><div class="line"><span class="built_in">console</span>.log(q.dequeue())</div><div class="line"><span class="built_in">console</span>.log(q.front())</div><div class="line"><span class="built_in">console</span>.log(q.isEmpty())</div><div class="line"><span class="built_in">console</span>.log(q.size())</div><div class="line"><span class="built_in">console</span>.log(q.print())</div></pre></td></tr></tbody></table></figure><p><strong>ES6语法:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Queue</span> </span>{</div><div class="line"> <span class="keyword">constructor</span> () {</div><div class="line"> <span class="keyword">this</span>.data = [];</div><div class="line"> }</div><div class="line"> enqueue(element){</div><div class="line"> <span class="keyword">this</span>.data.push(element);</div><div class="line"> }</div><div class="line"> dequeue(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.shift();</div><div class="line"> }</div><div class="line"> front(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data[<span class="number">0</span>];</div><div class="line"> }</div><div class="line"> isEmpty(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.length === <span class="number">0</span>;</div><div class="line"> }</div><div class="line"> size(){</div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.data.length;</div><div class="line"> }</div><div class="line"> clear(){</div><div class="line"> <span class="keyword">this</span>.data = [];</div><div class="line"> }</div><div class="line"> print(){</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.data.toString());</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="循环队列"><a href="#循环队列" class="headerlink" title="循环队列"></a>循环队列</h2><ul><li>循环队列有一个最大长度<code>max_size</code>,仍然采用数组实现。两个成员变量<code>front</code>和<code>rear</code>分别为队首元素和下一个入队的元素在列表中的索引。为了区别队列为空和队列为满,列表大小应为<code>length = max_size + 1</code>,列表中最多只能有<code>max_size</code>个队列元素</li><li>当进行入队操作时,先<strong>判断队列是否已满</strong>:<strong>(rear + 1) % length == front</strong>,一种方法是已满直接报错,另一种是若队列已满则扩容为原来的两倍。入队时,<code>rear = (rear + 1) % max_size</code></li><li>进行出队操作时,先<strong>判断队列是否为空</strong>:<strong>front == rear</strong>,如果为空则报错。出队时,<code>front = (front + 1) % max_size</code></li><li>获得<strong>当前队列长度</strong>:<strong>(rear - front + length) % length</strong></li><li>使用循环队列的方法,由于入队和出队操作都是直接通过索引访问列表,所以时间复杂度都是 O(1)</li></ul><p><br></p><h1 id="树"><a href="#树" class="headerlink" title="树"></a>树</h1><ul><li>结点、父结点、子结点、兄弟结点</li><li>层数、深度、高度、结点的度:结点的子树个数</li><li>满二叉树:除了叶结点,其它所有结点都有两个子结点(国内定义:除最后一层全为叶结点外,其它的层的每个结点都有两个子结点)</li><li>完全二叉树:除最后一层外,其它层全满,最后一层的叶结点必须从左到右填满</li></ul><h2 id="二叉树实例"><a href="#二叉树实例" class="headerlink" title="二叉树实例"></a>二叉树实例</h2><p><strong>ES5实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//节点</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">treeNode</span>(<span class="params">val</span>) </span>{</div><div class="line"> <span class="keyword">this</span>.val = val; <span class="comment">//当前节点的元素</span></div><div class="line"> <span class="keyword">this</span>.left = <span class="literal">null</span>; <span class="comment">//左节点链接</span></div><div class="line"> <span class="keyword">this</span>.right = <span class="literal">null</span>; <span class="comment">//右节点链接</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//前序遍历</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">preorder</span>(<span class="params">root</span>) </span>{</div><div class="line"> <span class="keyword">if</span>(root === <span class="literal">null</span>){</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> [root.val] + preorder(root.left) + preorder(root.right);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//中序遍历</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">inorder</span>(<span class="params">root</span>) </span>{</div><div class="line"> <span class="keyword">if</span>(root === <span class="literal">null</span>){</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> inorder(root.left) + [root.val] + inorder(root.right);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//后序遍历</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">postorder</span>(<span class="params">root</span>) </span>{</div><div class="line"> <span class="keyword">if</span>(root === <span class="literal">null</span>){</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> postorder(root.left) + postorder(root.right) + [root.val];</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//层次遍历</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">levelorder</span>(<span class="params">root</span>) </span>{</div><div class="line"> <span class="keyword">if</span>(root === <span class="literal">null</span>){</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">var</span> res = [];</div><div class="line"> <span class="keyword">var</span> nodequeue = [root];</div><div class="line"> <span class="keyword">while</span> (nodequeue){</div><div class="line"> root = nodequeue.shift();</div><div class="line"> res.push(root.val)</div><div class="line"> <span class="keyword">if</span> (root.left){</div><div class="line"> nodequeue.push(root.left);</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (root.right){</div><div class="line"> nodequeue.push(root.right);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>用例测试:</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">a1 = treeNode(<span class="number">1</span>)</div><div class="line">a2 = treeNode(<span class="number">2</span>)</div><div class="line">a3 = treeNode(<span class="number">3</span>)</div><div class="line">a4 = treeNode(<span class="number">4</span>)</div><div class="line">a5 = treeNode(<span class="number">5</span>)</div><div class="line">a6 = treeNode(<span class="number">6</span>)</div><div class="line"></div><div class="line">a1.left = a2</div><div class="line">a1.right = a3</div><div class="line">a2.left = a4</div><div class="line">a2.right = a5</div><div class="line">a3.right = a6</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(<span class="string">"PreOrder: "</span>, preorder(a1))</div><div class="line"><span class="built_in">console</span>.log(<span class="string">"InOrder: "</span>, inorder(a1))</div><div class="line"><span class="built_in">console</span>.log(<span class="string">"PostOrder: "</span>, postorder(a1))</div><div class="line"><span class="built_in">console</span>.log(<span class="string">"LevelOrder: "</span>, levelorder(a1))</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Indexed_collections" target="_blank" rel="external">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Indexed_collections</a></p><p><a href="https://github.com/wolverinn/Iridescent/blob/master/Data%20Structure.md" target="_blank" rel="external">https://github.com/wolverinn/Iridescent/blob/master/Data%20Structure.md</a></p><p><a href="https://github.com/wolverinn/Iridescent/blob/master/Data%20Structure%20code%20complete.ipynb" target="_blank" rel="external">https://github.com/wolverinn/Iridescent/blob/master/Data%20Structure%20code%20complete.ipynb</a></p><p><a href="https://juejin.im/post/5b87c60c6fb9a019fa06495b" target="_blank" rel="external">https://juejin.im/post/5b87c60c6fb9a019fa06495b</a></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用JavaScript实现基础数据结构:数组、链表、栈、队列、树</p>
</blockquote>
<h1 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h1><ul>
<li>在数组的<strong>末尾插入/删除</strong>、<strong>更新</strong>、<strong>获取</strong>某个位置的元素,都是 O(1) 的时间复杂度</li>
<li>在数组的任何其它地方<strong>插入/删除</strong>元素,都是 O(n) 的时间复杂度</li>
<li>空间复杂度:O(n)</li>
</ul>
<h2 id="数组创建"><a href="#数组创建" class="headerlink" title="数组创建"></a>数组创建</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> arr = <span class="keyword">new</span> <span class="built_in">Array</span>(element0, element1, ..., elementN);</div><div class="line"><span class="keyword">var</span> arr = <span class="built_in">Array</span>(element0, element1, ..., elementN);</div><div class="line"><span class="keyword">var</span> arr = [element0, element1, ..., elementN];</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr = <span class="keyword">new</span> <span class="built_in">Array</span>(arrayLength);</div><div class="line"><span class="keyword">var</span> arr = <span class="built_in">Array</span>(arrayLength);</div></pre></td></tr></tbody></table></figure>
</summary>
<category term="前端" scheme="https://www.awebone.com/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>数据结构与算法JavaScript版(二)</title>
<link href="https://www.awebone.com/posts/db1de468/"/>
<id>https://www.awebone.com/posts/db1de468/</id>
<published>2020-07-18T07:00:00.000Z</published>
<updated>2020-07-18T12:59:20.829Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用JavaScript实现基础排序算法和搜索算法</p></blockquote><h1 id="排序算法"><a href="#排序算法" class="headerlink" title="排序算法"></a>排序算法</h1><p><img src="/images/js数据结构与算法2/1595068515953.png" alt="1595068515953"></p><h2 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="冒泡排序"></a>冒泡排序</h2><p>工作原理:冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。</p><p>算法描述:</p><ol><li>比较相邻的元素,如果第一个比第二个大,就交换它们两个</li><li>对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数</li><li>针对所有的元素重复以上的步骤,除了最后一个</li><li>重复步骤1~3,直到排序完成。</li></ol><a id="more"></a><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">bubbleSort</span>(<span class="params">arr</span>)</span>{</div><div class="line"> <span class="keyword">var</span> len = arr.length;</div><div class="line"> <span class="keyword">if</span> (len === <span class="number">0</span>){</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i < len; i++) {</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> j = <span class="number">0</span>; j < len - i; j++){</div><div class="line"> <span class="keyword">if</span>(arr[j - <span class="number">1</span>] > arr[j]){</div><div class="line"> <span class="keyword">var</span> tmp = arr[j - <span class="number">1</span>];</div><div class="line"> arr[j - <span class="number">1</span>] = arr[j];</div><div class="line"> arr[j] = tmp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> arr;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr = [<span class="number">5</span>,<span class="number">3</span>,<span class="number">6</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">9</span>,<span class="number">7</span>]</div><div class="line"><span class="built_in">console</span>.log(bubbleSort(arr))</div></pre></td></tr></tbody></table></figure><h2 id="选择排序"><a href="#选择排序" class="headerlink" title="选择排序"></a>选择排序</h2><p>工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。</p><p>算法描述如下:</p><ol><li>初始状态:无序区为R[1..n],有序区为空;</li><li>第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;</li><li>n-1趟结束,数组有序化了</li></ol><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">selectionSort</span>(<span class="params">arr</span>) </span>{</div><div class="line"> <span class="keyword">var</span> len = arr.length;</div><div class="line"> <span class="keyword">var</span> minIndex, temp;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < len - <span class="number">1</span>; i++) {</div><div class="line"> minIndex = i;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = i + <span class="number">1</span>; j < len; j++) {</div><div class="line"> <span class="keyword">if</span> (arr[j] < arr[minIndex]) { <span class="comment">//寻找最小的数</span></div><div class="line"> minIndex = j; <span class="comment">//将最小数的索引保存</span></div><div class="line"> }</div><div class="line"> }</div><div class="line"> temp = arr[i];</div><div class="line"> arr[i] = arr[minIndex];</div><div class="line"> arr[minIndex] = temp;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> arr;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> arr=[<span class="number">3</span>,<span class="number">44</span>,<span class="number">38</span>,<span class="number">5</span>,<span class="number">47</span>,<span class="number">15</span>,<span class="number">36</span>,<span class="number">26</span>,<span class="number">27</span>,<span class="number">2</span>,<span class="number">46</span>,<span class="number">4</span>,<span class="number">19</span>,<span class="number">50</span>,<span class="number">48</span>];</div><div class="line"><span class="built_in">console</span>.log(selectionSort(arr));</div></pre></td></tr></tbody></table></figure><h2 id="插入排序"><a href="#插入排序" class="headerlink" title="插入排序"></a>插入排序</h2><p>工作原理:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。</p><p>算法描述:</p><ol><li>从第一个元素开始,该元素可以认为已经被排序;</li><li>取出下一个元素,在已经排序的元素序列中从后向前扫描;</li><li>如果该元素(已排序)大于新元素,将该元素移到下一位置;</li><li>重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;</li><li>将新元素插入到该位置后;</li><li>重复步骤2~5</li></ol><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">insertionSort</span>(<span class="params">array</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(array).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span>) {</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">var</span> key = array[i];</div><div class="line"> <span class="keyword">var</span> j = i - <span class="number">1</span>;</div><div class="line"> <span class="keyword">while</span> (j >= <span class="number">0</span> && array[j] > key) {</div><div class="line"> array[j + <span class="number">1</span>] = array[j];</div><div class="line"> j--;</div><div class="line"> }</div><div class="line"> array[j + <span class="number">1</span>] = key;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">'array is not an Array!'</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>改进插入排序:</strong> 查找插入位置时使用二分查找的方式</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">binaryInsertionSort</span>(<span class="params">array</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(array).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span>) {</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">var</span> key = array[i], left = <span class="number">0</span>, right = i - <span class="number">1</span>;</div><div class="line"> <span class="keyword">while</span> (left <= right) {</div><div class="line"> <span class="keyword">var</span> middle = <span class="built_in">parseInt</span>((left + right) / <span class="number">2</span>);</div><div class="line"> <span class="keyword">if</span> (key < array[middle]) {</div><div class="line"> right = middle - <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> left = middle + <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = i - <span class="number">1</span>; j >= left; j--) {</div><div class="line"> array[j + <span class="number">1</span>] = array[j];</div><div class="line"> }</div><div class="line"> array[left] = key;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">'array is not an Array!'</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">3</span>,<span class="number">44</span>,<span class="number">38</span>,<span class="number">5</span>,<span class="number">47</span>,<span class="number">15</span>,<span class="number">36</span>,<span class="number">26</span>,<span class="number">27</span>,<span class="number">2</span>,<span class="number">46</span>,<span class="number">4</span>,<span class="number">19</span>,<span class="number">50</span>,<span class="number">48</span>];</div><div class="line"><span class="built_in">console</span>.log(binaryInsertionSort(arr));</div></pre></td></tr></tbody></table></figure><h2 id="归并排序"><a href="#归并排序" class="headerlink" title="归并排序"></a>归并排序</h2><p>工作原理:归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。</p><p>算法描述:</p><ol><li>把长度为n的输入序列分成两个长度为n/2的子序列;</li><li>对这两个子序列分别采用归并排序;</li><li>将两个排序好的子序列合并成一个最终的排序序列</li></ol><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">mergeSort</span>(<span class="params">arr</span>) </span>{ <span class="comment">//采用自上而下的递归方法</span></div><div class="line"> <span class="keyword">var</span> len = arr.length;</div><div class="line"> <span class="keyword">if</span>(len < <span class="number">2</span>) {</div><div class="line"> <span class="keyword">return</span> arr;</div><div class="line"> }</div><div class="line"> <span class="keyword">var</span> middle = <span class="built_in">Math</span>.floor(len / <span class="number">2</span>),</div><div class="line"> left = arr.slice(<span class="number">0</span>, middle),</div><div class="line"> right = arr.slice(middle);</div><div class="line"> <span class="keyword">return</span> merge(mergeSort(left), mergeSort(right));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">merge</span>(<span class="params">left, right</span>)</span>{</div><div class="line"> <span class="keyword">var</span> result = [];</div><div class="line"> <span class="keyword">while</span> (left.length && right.length) {</div><div class="line"> <span class="keyword">if</span> (left[<span class="number">0</span>] <= right[<span class="number">0</span>]) {</div><div class="line"> result.push(left.shift());</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> result.push(right.shift());</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (left.length)</div><div class="line"> result.push(left.shift());</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (right.length)</div><div class="line"> result.push(right.shift());</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">3</span>,<span class="number">44</span>,<span class="number">38</span>,<span class="number">5</span>,<span class="number">47</span>,<span class="number">15</span>,<span class="number">36</span>,<span class="number">26</span>,<span class="number">27</span>,<span class="number">2</span>,<span class="number">46</span>,<span class="number">4</span>,<span class="number">19</span>,<span class="number">50</span>,<span class="number">48</span>];</div><div class="line"><span class="built_in">console</span>.log(mergeSort(arr));</div></pre></td></tr></tbody></table></figure><h2 id="快速排序"><a href="#快速排序" class="headerlink" title="快速排序"></a>快速排序</h2><p>工作原理:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。</p><p>算法描述:</p><ol><li>从数列中挑出一个元素,称为 “基准”(pivot);</li><li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;</li><li>递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序</li></ol><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">quickSort</span>(<span class="params">array, left, right</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(array).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span> && <span class="keyword">typeof</span> left === <span class="string">'number'</span> && <span class="keyword">typeof</span> right === <span class="string">'number'</span>) {</div><div class="line"> <span class="keyword">if</span> (left < right) {</div><div class="line"> <span class="keyword">var</span> x = array[right], i = left - <span class="number">1</span>, temp;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = left; j <= right; j++) {</div><div class="line"> <span class="keyword">if</span> (array[j] <= x) {</div><div class="line"> i++;</div><div class="line"> temp = array[i];</div><div class="line"> array[i] = array[j];</div><div class="line"> array[j] = temp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> quickSort(array, left, i - <span class="number">1</span>);</div><div class="line"> quickSort(array, i + <span class="number">1</span>, right);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">'array is not an Array or left or right is not a number!'</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//更好理解的方法</span></div><div class="line"><span class="keyword">var</span> quickSort2 = <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (arr.length <= <span class="number">1</span>)</div><div class="line"> <span class="keyword">return</span> arr;</div><div class="line"> <span class="keyword">var</span> pivotIndex = <span class="built_in">Math</span>.floor(arr.length / <span class="number">2</span>);</div><div class="line"> <span class="keyword">var</span> pivot = arr.splice(pivotIndex, <span class="number">1</span>)[<span class="number">0</span>];</div><div class="line"> <span class="keyword">var</span> left = [];</div><div class="line"> <span class="keyword">var</span> right = [];</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < arr.length; i++){</div><div class="line"> <span class="keyword">if</span> (arr[i] < pivot) {</div><div class="line"> left.push(arr[i]);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> right.push(arr[i]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> quickSort2(left).concat([pivot], quickSort2(right));</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">3</span>,<span class="number">44</span>,<span class="number">38</span>,<span class="number">5</span>,<span class="number">47</span>,<span class="number">15</span>,<span class="number">36</span>,<span class="number">26</span>,<span class="number">27</span>,<span class="number">2</span>,<span class="number">46</span>,<span class="number">4</span>,<span class="number">19</span>,<span class="number">50</span>,<span class="number">48</span>];</div><div class="line"><span class="built_in">console</span>.log(quickSort(arr,<span class="number">0</span>,arr.length<span class="number">-1</span>));</div><div class="line"><span class="built_in">console</span>.log(quickSort2(arr));</div></pre></td></tr></tbody></table></figure><h2 id="堆排序"><a href="#堆排序" class="headerlink" title="堆排序"></a>堆排序</h2><p>堆排序(Heapsort):利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。</p><p>算法描述:</p><ol><li>将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;</li><li>将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];</li><li>由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成</li></ol><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">heapSort</span>(<span class="params">array</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(array).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span>) {</div><div class="line"> <span class="comment">//建堆</span></div><div class="line"> <span class="keyword">var</span> heapSize = array.length, temp;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="built_in">Math</span>.floor(heapSize / <span class="number">2</span>) - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {</div><div class="line"> heapify(array, i, heapSize);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//堆排序</span></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = heapSize - <span class="number">1</span>; j >= <span class="number">1</span>; j--) {</div><div class="line"> temp = array[<span class="number">0</span>];</div><div class="line"> array[<span class="number">0</span>] = array[j];</div><div class="line"> array[j] = temp;</div><div class="line"> heapify(array, <span class="number">0</span>, --heapSize);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">'array is not an Array!'</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">heapify</span>(<span class="params">arr, x, len</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(arr).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span> && <span class="keyword">typeof</span> x === <span class="string">'number'</span>) {</div><div class="line"> <span class="keyword">var</span> l = <span class="number">2</span> * x + <span class="number">1</span>, r = <span class="number">2</span> * x + <span class="number">2</span>, largest = x, temp;</div><div class="line"> <span class="keyword">if</span> (l < len && arr[l] > arr[largest]) {</div><div class="line"> largest = l;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (r < len && arr[r] > arr[largest]) {</div><div class="line"> largest = r;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (largest != x) {</div><div class="line"> temp = arr[x];</div><div class="line"> arr[x] = arr[largest];</div><div class="line"> arr[largest] = temp;</div><div class="line"> heapify(arr, largest, len);</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">'arr is not an Array or x is not a number!'</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">91</span>,<span class="number">60</span>,<span class="number">96</span>,<span class="number">13</span>,<span class="number">35</span>,<span class="number">65</span>,<span class="number">46</span>,<span class="number">65</span>,<span class="number">10</span>,<span class="number">30</span>,<span class="number">20</span>,<span class="number">31</span>,<span class="number">77</span>,<span class="number">81</span>,<span class="number">22</span>];</div><div class="line"><span class="built_in">console</span>.log(heapSort(arr));</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="搜索算法"><a href="#搜索算法" class="headerlink" title="搜索算法"></a>搜索算法</h1><h2 id="顺序或线性搜索"><a href="#顺序或线性搜索" class="headerlink" title="顺序或线性搜索"></a>顺序或线性搜索</h2><p>最简单的搜索</p><p>工作原理:从左往右遍历寻找,返回索引</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">sequentialSearch</span>(<span class="params">array, item</span>)</span>{</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">if</span> (item === array[i]) {</div><div class="line"> <span class="keyword">return</span> i;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">91</span>,<span class="number">60</span>,<span class="number">96</span>,<span class="number">13</span>,<span class="number">35</span>,<span class="number">65</span>,<span class="number">46</span>,<span class="number">65</span>,<span class="number">10</span>,<span class="number">30</span>,<span class="number">20</span>,<span class="number">31</span>,<span class="number">77</span>,<span class="number">81</span>,<span class="number">22</span>];</div><div class="line"><span class="built_in">console</span>.log(sequentialSearch(arr, <span class="number">91</span>));</div></pre></td></tr></tbody></table></figure><h2 id="二分搜索"><a href="#二分搜索" class="headerlink" title="二分搜索"></a>二分搜索</h2><p>二分查找的前提为:数组、有序。逻辑为:优先和数组的中间元素比较,如果等于中间元素,则直接返回。如果不等于则取半继续查找。</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//递归</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">binarySearch</span>(<span class="params">arr, item, left, right</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (left > right)</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> <span class="keyword">var</span> start = left || <span class="number">0</span>;</div><div class="line"> <span class="keyword">var</span> end = right || arr.length - <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">var</span> mid = <span class="built_in">parseInt</span>(start + (end - start) / <span class="number">2</span>);</div><div class="line"> <span class="keyword">if</span>(item == arr[mid]){</div><div class="line"> <span class="keyword">return</span> mid;</div><div class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(item > arr[mid]){</div><div class="line"> <span class="keyword">return</span> binarySearch(arr, item, mid + <span class="number">1</span>, end);</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> <span class="keyword">return</span> binarySearch(arr, item, start, mid - <span class="number">1</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//非递归</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">binarySearch2</span>(<span class="params">arr, item</span>) </span>{</div><div class="line"> <span class="keyword">var</span> left = <span class="number">0</span>;</div><div class="line"> <span class="keyword">var</span> right = arr.length - <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (left <= right){</div><div class="line"> <span class="keyword">var</span> mid = <span class="built_in">parseInt</span>(left + (right - left) / <span class="number">2</span>);</div><div class="line"> <span class="keyword">if</span>(item == arr[mid]){</div><div class="line"> <span class="keyword">return</span> mid;</div><div class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(item > arr[mid]){</div><div class="line"> left = mid + <span class="number">1</span>;</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> right = mid - <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> arr=[<span class="number">13</span>,<span class="number">35</span>,<span class="number">46</span>,<span class="number">65</span>,<span class="number">77</span>,<span class="number">81</span>];</div><div class="line"><span class="built_in">console</span>.log(binarySearch(arr, <span class="number">35</span>));</div><div class="line"><span class="built_in">console</span>.log(binarySearch2(arr, <span class="number">35</span>));</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p><a href="https://juejin.im/post/57dcd394a22b9d00610c5ec8" target="_blank" rel="external">https://juejin.im/post/57dcd394a22b9d00610c5ec8</a></p><p><a href="https://www.jianshu.com/p/eef65b21ace0" target="_blank" rel="external">https://www.jianshu.com/p/eef65b21ace0</a></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用JavaScript实现基础排序算法和搜索算法</p>
</blockquote>
<h1 id="排序算法"><a href="#排序算法" class="headerlink" title="排序算法"></a>排序算法</h1><p><img src="/images/js数据结构与算法2/1595068515953.png" alt="1595068515953"></p>
<h2 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="冒泡排序"></a>冒泡排序</h2><p>工作原理:冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。</p>
<p>算法描述:</p>
<ol>
<li>比较相邻的元素,如果第一个比第二个大,就交换它们两个</li>
<li>对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数</li>
<li>针对所有的元素重复以上的步骤,除了最后一个</li>
<li>重复步骤1~3,直到排序完成。</li>
</ol>
</summary>
<category term="前端" scheme="https://www.awebone.com/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>数据结构与算法JavaScript版(三)</title>
<link href="https://www.awebone.com/posts/c0d60af6/"/>
<id>https://www.awebone.com/posts/c0d60af6/</id>
<published>2020-07-18T07:00:00.000Z</published>
<updated>2020-07-18T13:03:14.242Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用JavaScript实现一些常用的算法思想</p></blockquote><h1 id="算法思想"><a href="#算法思想" class="headerlink" title="算法思想"></a>算法思想</h1><h2 id="递归"><a href="#递归" class="headerlink" title="递归"></a>递归</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//斐波那契数列:递归</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">fibonacci</span>(<span class="params">num</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (num===<span class="number">1</span>||num===<span class="number">2</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> fibonacci(num<span class="number">-1</span>)+fibonacci(num<span class="number">-2</span>);</div><div class="line">}</div></pre></td></tr></tbody></table></figure><a id="more"></a><h2 id="非递归"><a href="#非递归" class="headerlink" title="非递归"></a>非递归</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//斐波那契数列:非递归</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">fib</span>(<span class="params">num</span>) </span>{</div><div class="line"> <span class="keyword">var</span> n1=<span class="number">1</span>,n2=<span class="number">1</span>,n=<span class="number">1</span>;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">3</span>; i <= num; i++) {</div><div class="line"> n=n1+n2;</div><div class="line"> n1=n2;</div><div class="line"> n2=n;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> n;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//动态规划:将大问题转化成小问题</span></div><div class="line"><span class="comment">//最少硬币找零问题:找到n所需的最小硬币数</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">dpMinCoinChange</span>(<span class="params">coins</span>) </span>{</div><div class="line"> <span class="keyword">var</span> coins=coins;</div><div class="line"> <span class="keyword">var</span> cache={};</div><div class="line"></div><div class="line"> <span class="keyword">this</span>.makeChange=<span class="function"><span class="keyword">function</span> (<span class="params">amount</span>) </span>{</div><div class="line"> <span class="keyword">var</span> me=<span class="keyword">this</span>;</div><div class="line"> <span class="keyword">if</span> (!amount) {<span class="comment">//判断为正</span></div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (cache[amount]) {<span class="comment">//判断是否有缓存</span></div><div class="line"> <span class="keyword">return</span> cache[amount];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">var</span> min=[],newMin,newAmount;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < coins.length; i++) {<span class="comment">//对每个面额计算</span></div><div class="line"> <span class="keyword">var</span> coin=coins[i];</div><div class="line"> newAmount=amount-coin;</div><div class="line"> <span class="keyword">if</span> (newAmount>=<span class="number">0</span>) {</div><div class="line"> newMin=me.makeChange(newAmount);</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (newAmount>=<span class="number">0</span> && (newMin.length<min.length<span class="number">-1</span> || !min.length) </div><div class="line"> && (newMin.length || !newAmount)) {</div><div class="line"> <span class="comment">//判断newAmount是否有效,最小硬币数是否最优,newMin和newAmount是否合理</span></div><div class="line"> min=[coin].concat(newMin);</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'new Min '</span>+min+ <span class="string">' for '</span>+amount);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> (cache[amount]=min);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="贪心策略"><a href="#贪心策略" class="headerlink" title="贪心策略"></a>贪心策略</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//贪心算法:近似求解,通过局部最优达到全局最优</span></div><div class="line"><span class="comment">//最少硬币找零问题:找到n所需的最小硬币数</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">txMinCoinChange</span>(<span class="params">coins</span>)</span>{</div><div class="line"> <span class="keyword">var</span> coins=coins;</div><div class="line"></div><div class="line"> <span class="keyword">this</span>.makeChange=<span class="function"><span class="keyword">function</span>(<span class="params">amount</span>)</span>{</div><div class="line"> <span class="keyword">var</span> change=[],total=<span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = coins.length; i >= <span class="number">0</span>; i--) {<span class="comment">//对每个面额从大面额开始,从大到小依次</span></div><div class="line"> <span class="keyword">var</span> coin=coins[i];</div><div class="line"> <span class="keyword">while</span> (total+coin<=amount) {</div><div class="line"> change.push(coin);</div><div class="line"> total+=coin;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> change;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用JavaScript实现一些常用的算法思想</p>
</blockquote>
<h1 id="算法思想"><a href="#算法思想" class="headerlink" title="算法思想"></a>算法思想</h1><h2 id="递归"><a href="#递归" class="headerlink" title="递归"></a>递归</h2><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//斐波那契数列:递归</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">fibonacci</span>(<span class="params">num</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (num===<span class="number">1</span>||num===<span class="number">2</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> fibonacci(num<span class="number">-1</span>)+fibonacci(num<span class="number">-2</span>);</div><div class="line">}</div></pre></td></tr></tbody></table></figure>
</summary>
<category term="前端" scheme="https://www.awebone.com/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>使用Docker搭建Ray集群</title>
<link href="https://www.awebone.com/posts/101d1957/"/>
<id>https://www.awebone.com/posts/101d1957/</id>
<published>2020-07-13T07:00:00.000Z</published>
<updated>2020-07-18T08:20:31.821Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用Docker中Ubuntu16.04镜像,搭建MiniConda环境,在conda之上搭建Ray集群环境</p></blockquote><h1 id="Docker镜像构建"><a href="#Docker镜像构建" class="headerlink" title="Docker镜像构建"></a>Docker镜像构建</h1><p><strong>编写Dockerfile文件,构建镜像,换源为阿里云:</strong></p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">FROM</span> ubuntu:<span class="number">16.04</span></div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> mv /etc/apt/sources.list.d /etc/apt/sources.list.d.bak</span></div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> mv /etc/apt/sources.list /etc/apt/sources.list.bak && \</span></div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe"</span> >>/etc/apt/sources.list && \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse"</span> >>/etc/apt/sources.list</div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> apt update</span></div></pre></td></tr></tbody></table></figure><p><strong>将Dockerfile文件放在用户目录下,运行下面命令构建镜像:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">docker build -t awebone/ubuntu16.04 .</div><div class="line"></div><div class="line">docker image ls <span class="_">-a</span> <span class="comment"># 查看镜像</span></div></pre></td></tr></tbody></table></figure><a id="more"></a><p><br></p><h1 id="基本准备工作"><a href="#基本准备工作" class="headerlink" title="基本准备工作"></a>基本准备工作</h1><p><strong>进入容器:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker run --name ray -itd awebone/ubuntu16.04 /bin/bash</div><div class="line">docker <span class="built_in">exec</span> -it ray /bin/bash</div></pre></td></tr></tbody></table></figure><p><strong>安装基本软件包:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">apt install python-software-properties -y</div><div class="line">apt install software-properties-common -y</div></pre></td></tr></tbody></table></figure><p><strong>安装经常使用的包:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">apt install -y vim wget git</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="MiniConda安装"><a href="#MiniConda安装" class="headerlink" title="MiniConda安装"></a>MiniConda安装</h1><p><strong>Conda安装:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py37_4.8.2-Linux-x86_64.sh</div><div class="line"></div><div class="line">bash Miniconda3-py37_4.8.2-Linux-x86_64.sh</div><div class="line"></div><div class="line"><span class="built_in">source</span> ~/.bashrc</div><div class="line"></div><div class="line">conda -V</div></pre></td></tr></tbody></table></figure><p><strong>conda镜像设置</strong></p><p>通过修改用户目录下的 <code>.condarc</code> 文件。先执行 <code>conda config --set show_channel_urls yes</code> 生成该文件之后再修改</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">channels:</div><div class="line"> - defaults</div><div class="line">show_channel_urls: <span class="literal">true</span></div><div class="line">channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda</div><div class="line">default_channels:</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2</div><div class="line">custom_channels:</div><div class="line"> conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div></pre></td></tr></tbody></table></figure><p>运行 <code>conda clean -i</code> 清除索引缓存,保证用的是镜像站提供的索引。</p><p><strong>环境创建</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">conda create -n ray python=3.6</div><div class="line">conda activate ray <span class="comment">#开启ray环境</span></div><div class="line">conda deactivate <span class="comment">#关闭环境</span></div><div class="line">conda env list <span class="comment">#显示所有的虚拟环境</span></div><div class="line">conda info --envs <span class="comment">#显示所有的虚拟环境</span></div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Ray安装"><a href="#Ray安装" class="headerlink" title="Ray安装"></a>Ray安装</h1><p><strong>pip镜像设置</strong></p><p>激活conda环境,运行:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">conda activate ray <span class="comment">#开启ray环境</span></div><div class="line">pip config <span class="built_in">set</span> global.index-url https://pypi.tuna.tsinghua.edu.cn/simple</div></pre></td></tr></tbody></table></figure><p><strong>ray安装</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">pip install ray <span class="comment"># ray安装</span></div><div class="line">pip install ray[tune] <span class="comment"># ray组件安装</span></div><div class="line">pip install ray[rllib] <span class="comment"># ray组件安装</span></div><div class="line">pip install tensorflow <span class="comment"># tf cpu安装</span></div><div class="line">pip install requests <span class="comment"># requests安装</span></div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="容器保存"><a href="#容器保存" class="headerlink" title="容器保存"></a>容器保存</h1><p><strong>将修改好的容器保存为镜像</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">docker commit (容器ID)[37639cc72d75] ubuntu-conda-ray</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Ray集群运行并使用"><a href="#Ray集群运行并使用" class="headerlink" title="Ray集群运行并使用"></a>Ray集群运行并使用</h1><p><strong>容器启动</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker run --shm-size 1000m --name ray1 -itd ubuntu-conda-ray /bin/bash</div><div class="line">docker run --shm-size 1000m --name ray2 -itd ubuntu-conda-ray /bin/bash</div></pre></td></tr></tbody></table></figure><p><strong>分两个终端进入容器</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker <span class="built_in">exec</span> -it ray1 /bin/bash</div><div class="line">docker <span class="built_in">exec</span> -it ray2 /bin/bash</div></pre></td></tr></tbody></table></figure><p><strong>两个容器分别激活Conda环境</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">conda activate ray <span class="comment">#开启ray环境</span></div></pre></td></tr></tbody></table></figure><p><strong>Ray启动</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">Ray1上:ray start --head --port=6379 <span class="comment"># 启动head节点</span></div><div class="line">Ray1上:ray start --address 172.16.0.2:6379 <span class="comment"># 向集群添加节点</span></div><div class="line">Ray2上:ray start --address 172.16.0.3:6379 <span class="comment"># 向集群添加节点</span></div></pre></td></tr></tbody></table></figure><p><strong>Ray集群测试</strong></p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># -*- coding: utf-8 -*-</span></div><div class="line"><span class="keyword">import</span> time</div><div class="line"><span class="keyword">import</span> ray</div><div class="line">ray.init(address=<span class="string">"auto"</span>)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></div><div class="line"> time.sleep(<span class="number">1</span>)</div><div class="line"></div><div class="line"><span class="meta">@ray.remote</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></div><div class="line"> time.sleep(<span class="number">1</span>)</div><div class="line"></div><div class="line"><span class="comment">#以下需要十秒。</span></div><div class="line">time1=time.time()</div><div class="line">[ f1() <span class="keyword">for</span> _ <span class="keyword">in</span> range(<span class="number">50</span>)]</div><div class="line">print(time.time()-time1)</div><div class="line"></div><div class="line"><span class="comment">#以下需要一秒(假设系统至少有10个CPU)。</span></div><div class="line">time2=time.time()</div><div class="line">ray.get([ f2.remote() <span class="keyword">for</span> _ <span class="keyword">in</span> range(<span class="number">50</span>)])</div><div class="line">print(time.time()-time2)</div></pre></td></tr></tbody></table></figure><p><strong>Ray RLLib使用</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">rllib train \</div><div class="line">--run=PG \</div><div class="line">--env=CartPole-v0 \</div><div class="line">--config=<span class="string">'{"output": "/tmp/cartpole-out", "output_max_file_size": 5000000}'</span> \</div><div class="line">--stop=<span class="string">'{"timesteps_total": 100000}'</span></div><div class="line"></div><div class="line">ls <span class="_">-l</span> /tmp/cartpole-out</div><div class="line"></div><div class="line">rllib train \</div><div class="line">--run=DQN \</div><div class="line">--env=CartPole-v0 \</div><div class="line">--config=<span class="string">'{</span></div><div class="line"> "input": "/tmp/cartpole-out",</div><div class="line"> "input_evaluation": [],</div><div class="line"> "explore": false}'</div></pre></td></tr></tbody></table></figure><p><strong>强化学习PPO算法实践</strong></p><p>编写<code>ppo.py</code>算法文件</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> gym</div><div class="line"><span class="keyword">from</span> gym.spaces <span class="keyword">import</span> Discrete, Box</div><div class="line"><span class="keyword">from</span> ray <span class="keyword">import</span> tune</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">SimpleCorridor</span><span class="params">(gym.Env)</span>:</span></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, config)</span>:</span></div><div class="line"> self.end_pos = config[<span class="string">"corridor_length"</span>]</div><div class="line"> self.cur_pos = <span class="number">0</span></div><div class="line"> self.action_space = Discrete(<span class="number">2</span>)</div><div class="line"> self.observation_space = Box(<span class="number">0.0</span>, self.end_pos, shape=(<span class="number">1</span>, ))</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">reset</span><span class="params">(self)</span>:</span></div><div class="line"> self.cur_pos = <span class="number">0</span></div><div class="line"> <span class="keyword">return</span> [self.cur_pos]</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">def</span> <span class="title">step</span><span class="params">(self, action)</span>:</span></div><div class="line"> <span class="keyword">if</span> action == <span class="number">0</span> <span class="keyword">and</span> self.cur_pos > <span class="number">0</span>:</div><div class="line"> self.cur_pos -= <span class="number">1</span></div><div class="line"> <span class="keyword">elif</span> action == <span class="number">1</span>:</div><div class="line"> self.cur_pos += <span class="number">1</span></div><div class="line"> done = self.cur_pos >= self.end_pos</div><div class="line"> <span class="keyword">return</span> [self.cur_pos], <span class="number">1</span> <span class="keyword">if</span> done <span class="keyword">else</span> <span class="number">0</span>, done, {}</div><div class="line"></div><div class="line">tune.run(</div><div class="line"> <span class="string">"PPO"</span>,</div><div class="line"> config={</div><div class="line"> <span class="string">"env"</span>: SimpleCorridor,</div><div class="line"> <span class="string">"num_workers"</span>: <span class="number">4</span>,</div><div class="line"> <span class="string">"env_config"</span>: {<span class="string">"corridor_length"</span>: <span class="number">5</span>}})</div></pre></td></tr></tbody></table></figure><p>运行<code>ppo.py</code>,查看训练状态:</p><p><img src="/images/使用Docker搭建Ray集群/ppo状态.png" alt="ppo状态"></p><p><img src="/images/使用Docker搭建Ray集群/ppo-status.png" alt="ppo-status"></p><p>查看CPU状态:</p><p><img src="/images/使用Docker搭建Ray集群/cpu-ray1-htop.png" alt="cpu-ray1-htop"></p><p><br></p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://docs.docker.com/engine/reference/run/" target="_blank" rel="external">https://docs.docker.com/engine/reference/run/</a></p><p><a href="https://www.jianshu.com/p/2a5cd519e583" target="_blank" rel="external">https://www.jianshu.com/p/2a5cd519e583</a></p><p><a href="https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/" target="_blank" rel="external">https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/</a></p><p><a href="https://blog.csdn.net/u011552182/article/details/80054899" target="_blank" rel="external">https://blog.csdn.net/u011552182/article/details/80054899</a></p><p><a href="https://github.com/ray-project/rl-experiments" target="_blank" rel="external">https://github.com/ray-project/rl-experiments</a></p><p><a href="https://www.twblogs.net/a/5db5755fbd9eee310da07c50?lang=zh-cn" target="_blank" rel="external">https://www.twblogs.net/a/5db5755fbd9eee310da07c50?lang=zh-cn</a></p><p><a href="https://blog.csdn.net/luanpeng825485697/article/details/88242020" target="_blank" rel="external">https://blog.csdn.net/luanpeng825485697/article/details/88242020</a></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用Docker中Ubuntu16.04镜像,搭建MiniConda环境,在conda之上搭建Ray集群环境</p>
</blockquote>
<h1 id="Docker镜像构建"><a href="#Docker镜像构建" class="headerlink" title="Docker镜像构建"></a>Docker镜像构建</h1><p><strong>编写Dockerfile文件,构建镜像,换源为阿里云:</strong></p>
<figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">FROM</span> ubuntu:<span class="number">16.04</span></div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> mv /etc/apt/sources.list.d /etc/apt/sources.list.d.bak</span></div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> mv /etc/apt/sources.list /etc/apt/sources.list.bak &amp;&amp; \</span></div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe"</span> &gt;&gt;/etc/apt/sources.list &amp;&amp; \</div><div class="line"> <span class="built_in">echo</span> <span class="string">"deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse"</span> &gt;&gt;/etc/apt/sources.list</div><div class="line"></div><div class="line"><span class="keyword">RUN</span><span class="bash"> apt update</span></div></pre></td></tr></tbody></table></figure>
<p><strong>将Dockerfile文件放在用户目录下,运行下面命令构建镜像:</strong></p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">docker build -t awebone/ubuntu16.04 .</div><div class="line"></div><div class="line">docker image ls <span class="_">-a</span> <span class="comment"># 查看镜像</span></div></pre></td></tr></tbody></table></figure>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="Ray" scheme="https://www.awebone.com/tags/Ray/"/>
</entry>
<entry>
<title>Centos7上Docker安装</title>
<link href="https://www.awebone.com/posts/6eadcfba/"/>
<id>https://www.awebone.com/posts/6eadcfba/</id>
<published>2020-07-11T07:00:00.000Z</published>
<updated>2020-07-18T08:22:43.106Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文在Centos7.8上安装Docker,并且加载国内镜像</p></blockquote><h1 id="虚拟机安装"><a href="#虚拟机安装" class="headerlink" title="虚拟机安装"></a>虚拟机安装</h1><p><strong>下载镜像:</strong><a href="https://mirrors.tuna.tsinghua.edu.cn/centos/7.8.2003/isos/x86_64/" target="_blank" rel="external">https://mirrors.tuna.tsinghua.edu.cn/centos/7.8.2003/isos/x86_64/</a></p><p><strong>虚拟机VMware安装Centos7</strong>:步骤略</p><p><strong>固定ip地址:</strong>图形化设置</p><p><strong>设置DNS:</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">sudo vim /etc/resolv.conf</div><div class="line"></div><div class="line"><span class="comment"># Generatedby NetworkManager</span></div><div class="line">nameserver 8.8.8.8</div><div class="line">nameserver 8.8.4.4</div><div class="line">nameserver 114.114.114.114</div></pre></td></tr></tbody></table></figure><p><strong>Centos镜像设置:</strong></p><p>建议先备份 CentOS-Base.repo</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak</div></pre></td></tr></tbody></table></figure><p>然后编辑 /etc/yum.repos.d/CentOS-Base.repo 文件,在 <code>mirrorlist=</code> 开头行前面加 <code>#</code> 注释掉;并将 <code>baseurl=</code> 开头行取消注释(如果被注释的话),把该行内的域名(例如<code>mirror.centos.org</code>)替换为 <code>mirrors.tuna.tsinghua.edu.cn</code>。</p><p>最后,更新软件包缓存</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum makecache</div></pre></td></tr></tbody></table></figure><a id="more"></a><p><br></p><h1 id="Docker安装"><a href="#Docker安装" class="headerlink" title="Docker安装"></a>Docker安装</h1><p>Docker 目前支持 CentOS 7 及以后的版本,内核要求至少为 3.10。</p><p>Docker 官网有安装步骤,本文只是记录一下,您也可以参考 <a href="https://docs.docker.com/install/linux/docker-ce/centos/" target="_blank" rel="external">Get Docker CE for CentOS</a></p><h2 id="环境查看"><a href="#环境查看" class="headerlink" title="环境查看"></a>环境查看</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">cat /etc/redhat-release </div><div class="line">uname <span class="_">-a</span></div></pre></td></tr></tbody></table></figure><h2 id="卸载旧版本"><a href="#卸载旧版本" class="headerlink" title="卸载旧版本"></a>卸载旧版本</h2><p>旧版本的 Docker 被叫做 <code>docker</code> 或 <code>docker-engine</code>,如果您安装了旧版本的 Docker ,您需要卸载掉它。</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine</div></pre></td></tr></tbody></table></figure><p>旧版本的内容在 <code>/var/lib/docker</code> 下,目录中的镜像(images), 容器(containers), 存储卷(volumes), 和 网络配置(networks)都可以保留。</p><p>Docker CE 包,目前的包名为 <code>docker-ce</code>。</p><h2 id="安装软件源"><a href="#安装软件源" class="headerlink" title="安装软件源"></a>安装软件源</h2><p>为了方便添加软件源,支持 devicemapper 存储类型,安装如下软件包</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo yum update</div><div class="line">sudo yum install -y yum-utils device-mapper-persistent-data lvm2</div></pre></td></tr></tbody></table></figure><p>添加 Docker 稳定版本的 yum 软件源</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo</div></pre></td></tr></tbody></table></figure><h2 id="安装-Docker"><a href="#安装-Docker" class="headerlink" title="安装 Docker"></a>安装 Docker</h2><p>把软件仓库地址替换为 TUNA:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo</div><div class="line">sudo sed -i <span class="string">'s+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+'</span> /etc/yum.repos.d/docker-ce.repo</div></pre></td></tr></tbody></table></figure><p>更新一下 yum 软件源的缓存,并安装 Docker。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo yum update</div><div class="line">sudo yum install docker-ce</div></pre></td></tr></tbody></table></figure><p>如果弹出 GPG key 的接收提示,请确认是否为 <code>060a 61c5 1b55 8a7f 742b 77aa c52f eb6b 621e 9f35</code>,如果是,可以接受并继续安装。</p><p>至此,Docker 已经安装完成了,Docker 服务是没有启动的,操作系统里的 docker 组被创建,但是没有用户在这个组里。</p><h2 id="将当前用户加入-docker-组"><a href="#将当前用户加入-docker-组" class="headerlink" title="将当前用户加入 docker 组"></a>将当前用户加入 docker 组</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo usermod <span class="_">-a</span>G docker <span class="variable">$USER</span></div></pre></td></tr></tbody></table></figure><p>退出当前终端并重新登录</p><h2 id="启动-Docker"><a href="#启动-Docker" class="headerlink" title="启动 Docker"></a>启动 Docker</h2><p>如果想添加到开机启动</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo systemctl <span class="built_in">enable</span> docker</div></pre></td></tr></tbody></table></figure><p>启动 docker 服务</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo systemctl start docker</div></pre></td></tr></tbody></table></figure><h2 id="验证安装"><a href="#验证安装" class="headerlink" title="验证安装"></a>验证安装</h2><p>验证 Docker CE 安装是否正确,可以运行 <code>hello-world</code> 镜像</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker version</div><div class="line">docker run hello-world</div></pre></td></tr></tbody></table></figure><h2 id="更新-Docker-CE"><a href="#更新-Docker-CE" class="headerlink" title="更新 Docker CE"></a>更新 Docker CE</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum update docker-ce</div></pre></td></tr></tbody></table></figure><h2 id="卸载-Docker-CE"><a href="#卸载-Docker-CE" class="headerlink" title="卸载 Docker CE"></a>卸载 Docker CE</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum remove docker-ce</div></pre></td></tr></tbody></table></figure><h2 id="删除本地文件"><a href="#删除本地文件" class="headerlink" title="删除本地文件"></a>删除本地文件</h2><p>注意,docker 的本地文件,包括镜像(images), 容器(containers), 存储卷(volumes)等,都需要手工删除。默认目录存储在 <code>/var/lib/docker</code>。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo rm -rf /var/lib/docker</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="镜像加速"><a href="#镜像加速" class="headerlink" title="镜像加速"></a>镜像加速</h1><p>在 <code>/etc/docker/daemon.json</code> 中写入如下内容(如果文件不存在请新建该文件)</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> <span class="string">"registry-mirrors"</span>: [</div><div class="line"> <span class="string">"https://docker.mirrors.ustc.edu.cn"</span>,</div><div class="line"> <span class="string">"http://f1361db2.m.daocloud.io"</span>,</div><div class="line"> <span class="string">"https://mirror.ccs.tencentyun.com"</span>,</div><div class="line"> <span class="string">"https://reg-mirror.qiniu.com"</span>,</div><div class="line"> <span class="string">"https://registry.docker-cn.com"</span></div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p>重新启动服务</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo systemctl daemon-reload</div><div class="line">sudo systemctl restart docker</div><div class="line">docker info</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Docker简单使用"><a href="#Docker简单使用" class="headerlink" title="Docker简单使用"></a>Docker简单使用</h1><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">docker pull python:3.6 <span class="comment"># 拉取python镜像</span></div><div class="line">docker image ls <span class="comment"># 查看所有镜像</span></div><div class="line">docker container ls <span class="_">-a</span> <span class="comment"># 查看所有容器</span></div><div class="line">docker rm $(docker container ls -aq) <span class="comment"># 删除所有容器</span></div><div class="line">docker ps --all <span class="comment"># 查看运行的容器</span></div><div class="line">docker run <span class="_">-d</span> --name ray01 python /bin/sh -c <span class="string">"while true; do sleep 3600; done"</span> <span class="comment"># 后台运行一个容器</span></div><div class="line">docker <span class="built_in">exec</span> -it ray01 /bin/bash <span class="comment"># 进入ray01,交互式运行</span></div><div class="line">docker cp <span class="built_in">test</span>1.py ray01:/ray/ <span class="comment"># 拷贝本地文件到容器中</span></div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://qizhanming.com/blog/2019/01/25/how-to-install-docker-ce-on-centos-7" target="_blank" rel="external">https://qizhanming.com/blog/2019/01/25/how-to-install-docker-ce-on-centos-7</a></p><p><a href="https://juejin.im/post/5cd2cf01f265da0374189441" target="_blank" rel="external">https://juejin.im/post/5cd2cf01f265da0374189441</a></p><p><a href="https://juejin.im/post/5dc241ce6fb9a04aa333c1bd#heading-7" target="_blank" rel="external">https://juejin.im/post/5dc241ce6fb9a04aa333c1bd#heading-7</a></p><p><a href="https://mirrors.tuna.tsinghua.edu.cn/help/pypi/" target="_blank" rel="external">https://mirrors.tuna.tsinghua.edu.cn/help/pypi/</a></p><p><a href="https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/" target="_blank" rel="external">https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/</a></p><p><a href="https://hub.docker.com/_/python" target="_blank" rel="external">https://hub.docker.com/_/python</a></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文在Centos7.8上安装Docker,并且加载国内镜像</p>
</blockquote>
<h1 id="虚拟机安装"><a href="#虚拟机安装" class="headerlink" title="虚拟机安装"></a>虚拟机安装</h1><p><strong>下载镜像:</strong><a href="https://mirrors.tuna.tsinghua.edu.cn/centos/7.8.2003/isos/x86_64/">https://mirrors.tuna.tsinghua.edu.cn/centos/7.8.2003/isos/x86_64/</a></p>
<p><strong>虚拟机VMware安装Centos7</strong>:步骤略</p>
<p><strong>固定ip地址:</strong>图形化设置</p>
<p><strong>设置DNS:</strong></p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">sudo vim /etc/resolv.conf</div><div class="line"></div><div class="line"><span class="comment"># Generatedby NetworkManager</span></div><div class="line">nameserver 8.8.8.8</div><div class="line">nameserver 8.8.4.4</div><div class="line">nameserver 114.114.114.114</div></pre></td></tr></tbody></table></figure>
<p><strong>Centos镜像设置:</strong></p>
<p>建议先备份 CentOS-Base.repo</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak</div></pre></td></tr></tbody></table></figure>
<p>然后编辑 /etc/yum.repos.d/CentOS-Base.repo 文件,在 <code>mirrorlist=</code> 开头行前面加 <code>#</code> 注释掉;并将 <code>baseurl=</code> 开头行取消注释(如果被注释的话),把该行内的域名(例如<code>mirror.centos.org</code>)替换为 <code>mirrors.tuna.tsinghua.edu.cn</code>。</p>
<p>最后,更新软件包缓存</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo yum makecache</div></pre></td></tr></tbody></table></figure>
</summary>
<category term="Linux" scheme="https://www.awebone.com/categories/Linux/"/>
<category term="Docker" scheme="https://www.awebone.com/tags/Docker/"/>
<category term="Linux" scheme="https://www.awebone.com/tags/Linux/"/>
</entry>
<entry>
<title>Conda搭建Ray集群</title>
<link href="https://www.awebone.com/posts/1fad2db9/"/>
<id>https://www.awebone.com/posts/1fad2db9/</id>
<published>2020-07-10T07:00:00.000Z</published>
<updated>2020-07-18T08:20:54.888Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用MiniConda搭建Ray集群环境</p></blockquote><h1 id="conda环境创建"><a href="#conda环境创建" class="headerlink" title="conda环境创建"></a>conda环境创建</h1><h2 id="conda镜像设置"><a href="#conda镜像设置" class="headerlink" title="conda镜像设置"></a>conda镜像设置</h2><p>通过修改用户目录下的 <code>.condarc</code> 文件。Windows 用户无法直接创建名为 <code>.condarc</code> 的文件,可先执行 <code>conda config --set show_channel_urls yes</code> 生成该文件之后再修改</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">channels:</div><div class="line"> - defaults</div><div class="line">show_channel_urls: <span class="literal">true</span></div><div class="line">channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda</div><div class="line">default_channels:</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2</div><div class="line">custom_channels:</div><div class="line"> conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div></pre></td></tr></tbody></table></figure><p>即可添加 Anaconda Python 免费仓库。</p><p>运行 <code>conda clean -i</code> 清除索引缓存,保证用的是镜像站提供的索引。</p><h2 id="环境创建"><a href="#环境创建" class="headerlink" title="环境创建"></a>环境创建</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">conda create -n ray python=3.6</div><div class="line">conda activate ray <span class="comment">#开启ray环境</span></div><div class="line">conda deactivate <span class="comment">#关闭环境</span></div><div class="line">conda env list <span class="comment">#显示所有的虚拟环境</span></div><div class="line">conda info --envs <span class="comment">#显示所有的虚拟环境</span></div></pre></td></tr></tbody></table></figure><a id="more"></a><p><br></p><h1 id="Ray安装"><a href="#Ray安装" class="headerlink" title="Ray安装"></a>Ray安装</h1><h2 id="pip镜像设置"><a href="#pip镜像设置" class="headerlink" title="pip镜像设置"></a>pip镜像设置</h2><h3 id="临时使用"><a href="#临时使用" class="headerlink" title="临时使用"></a>临时使用</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package</div></pre></td></tr></tbody></table></figure><p>注意,<code>simple</code> 不能少, 是 <code>https</code> 而不是 <code>http</code></p><h3 id="设为默认"><a href="#设为默认" class="headerlink" title="设为默认"></a>设为默认</h3><p>升级 pip 到最新的版本 (>=10.0.0) 后进行配置:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">pip install pip -U</div><div class="line">pip config <span class="built_in">set</span> global.index-url https://pypi.tuna.tsinghua.edu.cn/simple</div></pre></td></tr></tbody></table></figure><p>如果您到 pip 默认源的网络连接较差,临时使用本镜像站来升级 pip:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U</div></pre></td></tr></tbody></table></figure><h2 id="ray安装"><a href="#ray安装" class="headerlink" title="ray安装"></a>ray安装</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">pip install ray <span class="comment"># ray安装</span></div><div class="line">pip install ray[tune] ray[rllib] <span class="comment"># ray组件安装</span></div><div class="line">pip install tensorflow <span class="comment"># tf cpu安装</span></div><div class="line">conda install pytorch torchvision cudatoolkit=10.2 -c pytorch <span class="comment"># pytorch gpu安装</span></div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="多kernel安装"><a href="#多kernel安装" class="headerlink" title="多kernel安装"></a>多kernel安装</h1><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">pip install ipykernel</div><div class="line">python -m ipykernel install --name ray</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="jupyter-lab启动"><a href="#jupyter-lab启动" class="headerlink" title="jupyter lab启动"></a>jupyter lab启动</h1><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">jupyter lab</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Ray启动"><a href="#Ray启动" class="headerlink" title="Ray启动"></a>Ray启动</h1><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">ray start --head --port=6379 <span class="comment"># 启动head节点</span></div><div class="line">ray start --address 192.168.xxx.xxx:6379 <span class="comment"># 向集群添加节点</span></div><div class="line">python xxx.py <span class="comment"># 运行</span></div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用MiniConda搭建Ray集群环境</p>
</blockquote>
<h1 id="conda环境创建"><a href="#conda环境创建" class="headerlink" title="conda环境创建"></a>conda环境创建</h1><h2 id="conda镜像设置"><a href="#conda镜像设置" class="headerlink" title="conda镜像设置"></a>conda镜像设置</h2><p>通过修改用户目录下的 <code>.condarc</code> 文件。Windows 用户无法直接创建名为 <code>.condarc</code> 的文件,可先执行 <code>conda config --set show_channel_urls yes</code> 生成该文件之后再修改</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">channels:</div><div class="line"> - defaults</div><div class="line">show_channel_urls: <span class="literal">true</span></div><div class="line">channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda</div><div class="line">default_channels:</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro</div><div class="line"> - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2</div><div class="line">custom_channels:</div><div class="line"> conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div><div class="line"> simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud</div></pre></td></tr></tbody></table></figure>
<p>即可添加 Anaconda Python 免费仓库。</p>
<p>运行 <code>conda clean -i</code> 清除索引缓存,保证用的是镜像站提供的索引。</p>
<h2 id="环境创建"><a href="#环境创建" class="headerlink" title="环境创建"></a>环境创建</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">conda create -n ray python=3.6</div><div class="line">conda activate ray <span class="comment">#开启ray环境</span></div><div class="line">conda deactivate <span class="comment">#关闭环境</span></div><div class="line">conda env list <span class="comment">#显示所有的虚拟环境</span></div><div class="line">conda info --envs <span class="comment">#显示所有的虚拟环境</span></div></pre></td></tr></tbody></table></figure>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="Ray" scheme="https://www.awebone.com/tags/Ray/"/>
</entry>
<entry>
<title>高可用HBase搭建全流程</title>
<link href="https://www.awebone.com/posts/440e5582/"/>
<id>https://www.awebone.com/posts/440e5582/</id>
<published>2020-06-06T07:00:00.000Z</published>
<updated>2020-07-18T08:26:40.961Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="系统描述"><a href="#系统描述" class="headerlink" title="系统描述"></a>系统描述</h1><h2 id="系统介绍"><a href="#系统介绍" class="headerlink" title="系统介绍"></a>系统介绍</h2><p>系统基于ZooKeeper搭建Hadoop HA集群,在高可用分布式HDFS文件系统的基础上,搭建高可用分布式HBase数据库集群。</p><p>ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是 Google Chubby一个开源的实现。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如分布式同步,配置管理,集群管理,命名管理,队列管理。使用文件系统目录树作为数据模型。</p><p>Hadoop分布式集群采用主从架构,在Hadoop HA集群中,ZooKeeper用来解决SPOF单点故障问题。如果active namenod宕机,就从剩下的standby namenodes中选举出来一个新的active namenode,并且做到瞬时切换,使得在需求增长的前提下,分布式集群仍然可以向外提供服务。同样的,分布式HBase数据库也采用主从架构,在master server宕机的情况下,瞬时切换到backup master,使得HBase高可用。分布式HBase数据库的底层存储采用HDFS文件系统。</p><a id="more"></a><h2 id="环境要求和版本选择"><a href="#环境要求和版本选择" class="headerlink" title="环境要求和版本选择"></a>环境要求和版本选择</h2><p>(1)四台Linux服务器,分别为Hadoop01、Hadoop02、Hadoop03、Hadoop04,采用Centos 6.8版本;</p><p>(2)Java采用JDK 1.8版本;</p><p>(3)ZooKeeper 采用 3.4.10版本;</p><p>(4)Hadoop 采用2.7.6版本;</p><p>(5)HBase采用 1.2.6版本;</p><h2 id="集群规划和架构设计"><a href="#集群规划和架构设计" class="headerlink" title="集群规划和架构设计"></a>集群规划和架构设计</h2><p>Hadoop和HBase均采用主从架构模式,其系统内部均使用自己提供的负载均衡器。系统的集群规划如下表所示。</p><table><thead><tr><th></th><th>Hadoop01</th><th>Hadoop02</th><th>Hadoop03</th><th>Hadoop04</th></tr></thead><tbody><tr><td>NameNode</td><td>√</td><td>√</td><td></td><td></td></tr><tr><td>DataNode</td><td>√</td><td>√</td><td>√</td><td>√</td></tr><tr><td>ResourceManager</td><td></td><td></td><td>√</td><td>√</td></tr><tr><td>NodeManager</td><td>√</td><td>√</td><td>√</td><td>√</td></tr><tr><td>JobHistoryServer</td><td>√</td><td></td><td></td><td></td></tr><tr><td>ZooKeeper</td><td>√</td><td>√</td><td>√</td><td></td></tr><tr><td>JournalNode</td><td>√</td><td>√</td><td>√</td><td></td></tr><tr><td>Zkfc</td><td>√</td><td>√</td><td></td><td></td></tr><tr><td>HMaster</td><td>√</td><td></td><td></td><td>√</td></tr><tr><td>HRegionServer</td><td>√</td><td>√</td><td>√</td><td>√</td></tr></tbody></table><p> <br></p><h1 id="系统搭建"><a href="#系统搭建" class="headerlink" title="系统搭建"></a>系统搭建</h1><h2 id="ZooKeeper集群安装"><a href="#ZooKeeper集群安装" class="headerlink" title="ZooKeeper集群安装"></a>ZooKeeper集群安装</h2><h3 id="配置安排"><a href="#配置安排" class="headerlink" title="配置安排"></a>配置安排</h3><p>安装ZooKeeper集群时需要注意集群的节点个数必须是奇数,因为奇数个数是为了方便进行选举leader。这里将Hadoop01、Hadoop02、Hadoop03和Hadoop04均作为ZooKeeper集群的节点,但是将Hadoop04节点中的角色固定设置为observer,observer其实跟follower类似,只不过是为了给ZooKeeper进行扩充之使用,不会改变原来集群的主从所属关系,仅仅只是接受请求,然后进行处理,没有投票的权利,也没有被选举成为leader的权利。</p><h3 id="配置步骤"><a href="#配置步骤" class="headerlink" title="配置步骤"></a>配置步骤</h3><ol><li><p>获取安装包 <code>zookeeper-3.4.10.tar.gz</code></p></li><li><p>解压</p><p><code>tar -zxvf zookeeper-3.4.10.tar.gz -C ~/apps/</code> </p></li><li><p>修改配置文件<code>vim zoo.cfg</code></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">// znode数据存储系统中的所有节点的数据存储目录</div><div class="line">dataDir=/home/hadoop/data/zkdata/</div><div class="line">server.1=hadoop01:2888:3888</div><div class="line">server.2=hadoop02:2888:3888</div><div class="line">server.3=hadoop03:2888:3888</div><div class="line">server.4=hadoop04:2888:3888:observer</div></pre></td></tr></tbody></table></figure></li><li><p>在每个节点的/home/hadoop/data/zkdata/目录下创建一个myid的文件,该文件中直接存储一个id值即可</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">hadoop01:<span class="built_in">echo</span> 1 > myid</div><div class="line">hadoop02:<span class="built_in">echo</span> 2 > myid</div><div class="line">hadoop03:<span class="built_in">echo</span> 3 > myid</div></pre></td></tr></tbody></table></figure></li><li><p>配置环境变量<code>vim .bashrc</code></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">export</span> ZOOKEEPER_HOME=/home/hadoop/apps/zookeeper-3.4.10</div><div class="line"><span class="built_in">export</span> PATH=<span class="variable">$PATH</span>:<span class="variable">$ZOOKEEPER_HOME</span>/bin</div></pre></td></tr></tbody></table></figure></li><li><p>启动</p><p>在每个节点上都执行:<code>zkServer.sh start</code></p></li><li><p>客户端连接与shell操作</p><p>客户端连接:<code>zkCli.sh -server hostname:2181</code></p></li></ol><p><br></p><h2 id="Hadoop-HA集群安装"><a href="#Hadoop-HA集群安装" class="headerlink" title="Hadoop HA集群安装"></a>Hadoop HA集群安装</h2><h3 id="HA设计和配置安排"><a href="#HA设计和配置安排" class="headerlink" title="HA设计和配置安排"></a>HA设计和配置安排</h3><p>使用共享存储和ZooKeeper实现Hadoop HA。这里将Hadoop01作为NameNode的active节点,将Hadoop02作为NameNode的standby节点,Hadoop02是Hadoop01的热备,NameNode的元数据都存储在qjournal日志系统这个共享存储中,Hadoop01、Hadoop02、Hadoop03、Hadoop04都作为DataNode的节点,定时向NameNode发送报告和心跳。ZooKeeper中的zkfc进程监控NameNode的情况,当NameNode active节点失去心跳,即宕机时,自动切换,将standby节点激活,实现Hadoop集群的高可用。</p><p><img src="/images/HBase-HA/clip_image002-1591461382734.jpg" alt="img"></p><h3 id="配置步骤-1"><a href="#配置步骤-1" class="headerlink" title="配置步骤"></a>配置步骤</h3><ol><li><p>获取安装包<code>hadoop-2.7.6.tar.gz</code></p></li><li><p>解压</p><p><code>tar -zxvf hadoop-2.7.6.tar.gz -C ~/apps/</code></p></li><li><p>修改配置文件</p><p>hadoop-env.sh文件:</p><p><code>export JAVA_HOME=/home/hadoop/apps/jdk1.8.0_73</code></p><p>core-site.xml文件:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><configuration></div><div class="line"> <!-- 指定hdfs的nameservice为myha01 --></div><div class="line"> <property></div><div class="line"> <name>fs.defaultFS</name></div><div class="line"> <value>hdfs://myha/</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定hadoop临时目录 --></div><div class="line"> <property></div><div class="line"> <name>hadoop.tmp.dir</name></div><div class="line"> <value>/home/hadoop/data/hadoopdata/</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定zookeeper地址 --></div><div class="line"> <property></div><div class="line"> <name>ha.zookeeper.quorum</name> <value>hadoop01:2181,hadoop02:2181,hadoop03:2181,hadoop04:2181</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- hadoop链接zookeeper的超时时长设置 --></div><div class="line"> <property></div><div class="line"> <name>ha.zookeeper.session-timeout.ms</name></div><div class="line"> <value>1000</value></div><div class="line"> <description>ms</description></div><div class="line"> </property></div><div class="line"></configuration></div></pre></td></tr></tbody></table></figure><p>hdfs-site.xml文件:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div></pre></td><td class="code"><pre><div class="line"><configuration></div><div class="line"> <!-- 指定副本数 --></div><div class="line"> <property></div><div class="line"> <name>dfs.replication</name></div><div class="line"> <value>2</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 配置namenode和datanode的工作目录-数据存储目录 --></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.name.dir</name></div><div class="line"> <value>/home/hadoop/data/hadoopdata/dfs/name</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>dfs.datanode.data.dir</name></div><div class="line"> <value>/home/hadoop/data/hadoopdata/dfs/data</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 启用webhdfs --></div><div class="line"> <property></div><div class="line"> <name>dfs.webhdfs.enabled</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>dfs.nameservices</name></div><div class="line"> <value>myha</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- myha01下面有两个NameNode,分别是nn1,nn2 --></div><div class="line"> <property></div><div class="line"> <name>dfs.ha.namenodes.myha</name></div><div class="line"> <value>nn1,nn2</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- nn1的RPC通信地址 --></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.rpc-address.myha.nn1</name></div><div class="line"> <value>hadoop01:9000</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- nn1的http通信地址 --></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.http-address.myha.nn1</name></div><div class="line"> <value>hadoop01:50070</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- nn2的RPC通信地址 --></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.rpc-address.myha.nn2</name></div><div class="line"> <value>hadoop02:9000</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- nn2的http通信地址 --></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.http-address.myha.nn2</name></div><div class="line"> <value>hadoop02:50070</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03:8485/myha</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定JournalNode在本地磁盘存放数据的位置 --></div><div class="line"> <property></div><div class="line"> <name>dfs.journalnode.edits.dir</name></div><div class="line"> <value>/home/hadoop/data/journaldata</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 开启NameNode失败自动切换 --></div><div class="line"> <property></div><div class="line"> <name>dfs.ha.automatic-failover.enabled</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 配置失败自动切换实现方式 --></div><div class="line"> <property></div><div class="line"> <name>dfs.client.failover.proxy.provider.myha</name></div><div class="line"> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行 --></div><div class="line"> <property></div><div class="line"> <name>dfs.ha.fencing.methods</name></div><div class="line"> <value></div><div class="line"> sshfence</div><div class="line"> shell(/bin/<span class="literal">true</span>)</div><div class="line"> </value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 使用sshfence隔离机制时需要ssh免登陆 --></div><div class="line"> <property></div><div class="line"> <name>dfs.ha.fencing.ssh.private-key-files</name></div><div class="line"> <value>/home/hadoop/.ssh/id_rsa</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 配置sshfence隔离机制超时时间 --></div><div class="line"> <property></div><div class="line"> <name>dfs.ha.fencing.ssh.connect-timeout</name></div><div class="line"> <value>30000</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>ha.failover-controller.cli-check.rpc-timeout.ms</name></div><div class="line"> <value>60000</value></div><div class="line"> </property></div><div class="line"> </configuration></div></pre></td></tr></tbody></table></figure></li></ol><p> mapred-site.xml文件:</p> <figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><configuration></div><div class="line"> <!-- 指定mr框架为yarn方式 --></div><div class="line"> <property></div><div class="line"> <name>mapreduce.framework.name</name></div><div class="line"> <value>yarn</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定mapreduce jobhistory地址 --></div><div class="line"> <property></div><div class="line"> <name>mapreduce.jobhistory.address</name></div><div class="line"> <value>hadoop01:10020</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 任务历史服务器的web地址 --></div><div class="line"> <property></div><div class="line"> <name>mapreduce.jobhistory.webapp.address</name></div><div class="line"> <value>hadoop01:19888</value></div><div class="line"> </property></div><div class="line"></configuration></div></pre></td></tr></tbody></table></figure><p> yarn-sitem.xml文件:</p> <figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line"><configuration></div><div class="line"> <!-- 开启RM高可用 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.ha.enabled</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定RM的cluster id --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.cluster-id</name></div><div class="line"> <value>yrc</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定RM的名字 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.ha.rm-ids</name></div><div class="line"> <value>rm1,rm2</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 分别指定RM的地址 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.hostname.rm1</name></div><div class="line"> <value>hadoop03</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.hostname.rm2</name></div><div class="line"> <value>hadoop04</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 指定zk集群地址 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.zk-address</name></div><div class="line"> <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>yarn.nodemanager.aux-services</name></div><div class="line"> <value>mapreduce_shuffle</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>yarn.log-aggregation-enable</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <property></div><div class="line"> <name>yarn.log-aggregation.retain-seconds</name></div><div class="line"> <value>86400</value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 启用自动恢复 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.recovery.enabled</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"> </property></div><div class="line"></div><div class="line"> <!-- 制定resourcemanager的状态信息存储在zookeeper集群上 --></div><div class="line"> <property></div><div class="line"> <name>yarn.resourcemanager.store.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value></div><div class="line"> </property></div><div class="line"></configuration></div></pre></td></tr></tbody></table></figure><p> slaves文件:</p> <figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">hadoop01</div><div class="line">hadoop02</div><div class="line">hadoop03</div><div class="line">hadoop04</div></pre></td></tr></tbody></table></figure><ol><li><p>分发,在一个节点上配置,分发到其他节点,配置信息全部一致</p><p><code>scp -r hadoop-2.7.6 hadoop02:~/apps/</code></p><p><code>scp -r hadoop-2.7.6 hadoop03:~/apps/</code></p><p><code>scp -r hadoop-2.7.6 hadoop04:~/apps/</code></p></li><li><p>配置环境变量.bashrc</p><p><code>export HADOOP_HOME=/home/hadoop/apps/hadoop-2.7.6</code></p><p><code>export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin</code></p></li><li><p>第一次启动</p><p>Hadoop HA集群启动前,需要先启动ZooKeeper集群。需要找到qjournal系统的所有节点执行:<code>hadoop-daemon.sh start journalnode</code>,找到其中的一个HDFS主节点执行初始化:<code>hadoop namenode -format</code>。把当前初始化成功的那个namenode节点的工作目录中的数据文件全部拷贝到剩下的其他namenode节点中的对应目录:<code>scp -r hadoopdata/ hadoop02:~/data/</code>,选择其中的一个namenode节点然后执行命令去进行zkfc的初始化:<code>hdfs zkfc –formatZK</code></p></li><li><p>正式启动 </p><p>启动hdfs:<code>start-dfs.sh</code></p><p>启动yarn集群:<code>start-yarn.sh</code></p><p>启动mr历史服务器:<code>mr-jobhistory-daemon.sh start historyserver</code></p></li></ol><p><br></p><h2 id="HBase-HA集群安装"><a href="#HBase-HA集群安装" class="headerlink" title="HBase HA集群安装"></a>HBase HA集群安装</h2><h3 id="配置安排-1"><a href="#配置安排-1" class="headerlink" title="配置安排"></a>配置安排</h3><p>HBase分布式数据库底层数据存储采用刚刚搭建的HDFS分布式文件系统,使用ZooKeeper来作为HMaster和Backup HMaster的协调,在HMaster失去心跳宕机时,Backup HMaster自动切换成active状态,实现高可用分布式数据库。这里将Hadoop01和Hadoop04作为HMaster节点,将Hadoop01、Hadoop02、Hadoop03、Hadoop04作为HRegionServer节点。</p><h3 id="配置步骤-2"><a href="#配置步骤-2" class="headerlink" title="配置步骤"></a>配置步骤</h3><ol><li><p>安装包<code>hbase-1.2.6.tar.gz</code></p></li><li><p>解压</p><p><code>tar -zxvf hbase-1.2.6.tar.gz -C ~/apps/</code></p></li><li><p>修改配置文件</p><p>hbase-env.sh文件:</p><p><code>export JAVA_HOME=/home/hadoop/jdk1.8.0_73</code></p><p><code>export HBASE_MANAGES_ZK=false</code></p><p>hbase-site.xml文件:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><property></div><div class="line"> <!-- 指定 hbase 在 HDFS 上存储的路径 --></div><div class="line"> <name>hbase.rootdir</name></div><div class="line"> <value>hdfs://myha/myhbase</value></div><div class="line"></property></div><div class="line"> </div><div class="line"><property</div><div class="line"> <!-- 指定 hbase 是分布式的 --></div><div class="line"> <name>hbase.cluster.distributed</name></div><div class="line"> <value><span class="literal">true</span></value></div><div class="line"></property></div><div class="line"> </div><div class="line"><property></div><div class="line"> <!-- 指定 zk 的地址,多个用“,”分割 --></div><div class="line"> <name>hbase.zookeeper.quorum</name></div><div class="line"> <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value></div><div class="line"></property></div></pre></td></tr></tbody></table></figure></li></ol><p> regionservers文件:</p> <figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">hadoop01</div><div class="line">hadoop02</div><div class="line">hadoop03</div><div class="line">hadoop04</div></pre></td></tr></tbody></table></figure><p> backup-masters文件:</p><p> <code>hadoop01</code></p><ol><li><p>将hadoop的hdfs-site.xml、core-site.xml放在hbase的conf下</p><p><code>cp /home/hadoop/hadoop-2.7.6/etc/hadoop/core-site.xml .</code></p><p><code>cp /home/hadoop/hadoop-2.7.6/etc/hadoop/hdfs-site.xml .</code></p></li><li><p>将hbase的安装包发送到其他节点</p><p><code>scp -r hbase-1.2.6 hadoop01:$PWD</code></p><p><code>scp -r hbase-1.2.6 hadoop02:$PWD</code></p><p><code>scp -r hbase-1.2.6 hadoop03:$PWD</code></p><p><code>scp -r hbase-1.2.6 hadoop04:$PWD</code></p></li><li><p>启动</p><p><code>start-hbase.sh</code></p></li></ol><p><br></p><h1 id="系统测试与结果展示"><a href="#系统测试与结果展示" class="headerlink" title="系统测试与结果展示"></a>系统测试与结果展示</h1><h2 id="系统测试"><a href="#系统测试" class="headerlink" title="系统测试"></a>系统测试</h2><p>在四台机器上运行<code>jps</code>命令,查看相关进程是否启动。</p><p><img src="/images/HBase-HA/clip_image004-1591461382734.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image006-1591461382734.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image008-1591461382734.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image010-1591461382734.jpg" alt="img"></p><h2 id="ZooKeeper状态查看"><a href="#ZooKeeper状态查看" class="headerlink" title="ZooKeeper状态查看"></a>ZooKeeper状态查看</h2><p>在四台机器上使用<code>zkServer.sh status</code>命令查看ZooKeeper的状态。</p><p><img src="/images/HBase-HA/clip_image012-1591461382734.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image014-1591461382734.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image016-1591461382735.jpg" alt="img"></p><p><img src="/images/HBase-HA/clip_image018-1591461382735.jpg" alt="img"></p><h2 id="Hadoop-HA展示"><a href="#Hadoop-HA展示" class="headerlink" title="Hadoop HA展示"></a>Hadoop HA展示</h2><p>HDFS启动过程:</p><p><img src="/images/HBase-HA/clip_image020-1591461382735.jpg" alt="img"></p><p>YARN启动过程:</p><p><img src="/images/HBase-HA/clip_image022-1591461382735.jpg" alt="img"></p><p>机架感知状态查看:</p><p><img src="/images/HBase-HA/clip_image024-1591461382735.jpg" alt="img"></p><p>Web页面查看:</p><p><img src="/images/HBase-HA/clip_image026-1591461382735.jpg" alt="img"></p><h2 id="HBase-HA展示"><a href="#HBase-HA展示" class="headerlink" title="HBase HA展示"></a>HBase HA展示</h2><p>HBase启动过程:</p><p><img src="/images/HBase-HA/clip_image028-1591461382735.jpg" alt="img"></p><p>Web页面查看:</p><p><img src="/images/HBase-HA/clip_image030-1591461382735.jpg" alt="img"></p><p>HBase底层存储情况:</p><p><img src="/images/HBase-HA/clip_image032-1591461382735.jpg" alt="img"></p><p> <br></p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>系统根据需求,进行架构设计,确定一主多从的架构,接着根据系统环境和版本兼容性的选择,确定最终系统中安装包的版本,然后在仅有的四台服务器上进行集群规划,尽量使得各个节点负载均衡。</p><p>通过搭建ZooKeeper分布式集群,以感知服务器上下线,接着基于ZooKeeper搭建Hadoop HA集群,保证HDFS文件系统高可用,再在高可用分布式HDFS文件系统的基础上搭建高可用分布式HBase数据库,完整实现这个过程,学习到分布式系统中关于数据一致性的知识,在系统中,均可保证最终一致性。掌握了ZooKeeper、Hadoop、HBase高可用集群的搭建部署,学习了在分布式文件系统HDFS之上,数据库的应用场景。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="系统描述"><a href="#系统描述" class="headerlink" title="系统描述"></a>系统描述</h1><h2 id="系统介绍"><a href="#系统介绍" class="headerlink" title="系统介绍"></a>系统介绍</h2><p>系统基于ZooKeeper搭建Hadoop HA集群,在高可用分布式HDFS文件系统的基础上,搭建高可用分布式HBase数据库集群。</p>
<p>ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是 Google Chubby一个开源的实现。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如分布式同步,配置管理,集群管理,命名管理,队列管理。使用文件系统目录树作为数据模型。</p>
<p>Hadoop分布式集群采用主从架构,在Hadoop HA集群中,ZooKeeper用来解决SPOF单点故障问题。如果active namenod宕机,就从剩下的standby namenodes中选举出来一个新的active namenode,并且做到瞬时切换,使得在需求增长的前提下,分布式集群仍然可以向外提供服务。同样的,分布式HBase数据库也采用主从架构,在master server宕机的情况下,瞬时切换到backup master,使得HBase高可用。分布式HBase数据库的底层存储采用HDFS文件系统。</p>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="面试" scheme="https://www.awebone.com/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="Hadoop" scheme="https://www.awebone.com/tags/Hadoop/"/>
</entry>
<entry>
<title>Transformer模型详解</title>
<link href="https://www.awebone.com/posts/c96b08bc/"/>
<id>https://www.awebone.com/posts/c96b08bc/</id>
<published>2020-06-06T07:00:00.000Z</published>
<updated>2020-07-18T08:35:52.574Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="机器翻译发展变化趋势"><a href="#机器翻译发展变化趋势" class="headerlink" title="机器翻译发展变化趋势"></a>机器翻译发展变化趋势</h1><p>机器翻译(MT)是借机器之力,自动地将一种自然语言文本(源语言)翻译成另一种自然语言文本(目标语言)。使用机器做翻译的思想最早由 Warren Weaver 于 1949 年提出,在很长一段时间里(20 世纪 50 年代到 80 年代),机器翻译都是通过研究源语言与目标语言的语言学信息来做的,也就是基于词典和语法生成翻译,这被称为基于规则的机器翻译(RBMT)。随着统计学的发展,研究者开始将统计模型应用于机器翻译,这种方法是基于对双语文本语料库的分析来生成翻译结果。这种方法被称为统计机器翻译(SMT),它的表现比 RBMT 更好,并且在 1980 年代到 2000 年代之间主宰了这一领域。1997 年,Ramon Neco 和 Mikel Forcada 提出了使用编码器-解码器结构做机器翻译的想法。几年之后的 2003 年,蒙特利尔大学 Yoshua Bengio 领导的一个研究团队开发了一个基于神经网络的语言模型,改善了传统 SMT 模型的数据稀疏性问题。他们的研究工作为未来神经网络在机器翻译上的应用奠定了基础。</p><a id="more"></a><p>2013 年,Nal Kalchbrenner 和 Phil Blunsom 提出了一种用于机器翻译的新型端到端编码器-解码器结构。该模型可以使用卷积神经网络(CNN)将给定的一段源文本编码成一个连续的向量,然后再使用循环神经网络(RNN)作为解码器将该状态向量转换成目标语言。他们的研究成果可以说是神经机器翻译(NMT)的诞生,神经机器翻译是一种使用深度学习神经网络获取自然语言之间的映射关系的方法。NMT 的非线性映射不同于线性的 SMT 模型,而且是使用了连接编码器和解码器的状态向量来描述语义的等价关系。此外,RNN 应该还能得到无限长句子背后的信息,从而解决所谓的长距离重新排序(long distance reordering)问题。但是,梯度爆炸或者消失问题让 RNN 实际上难以处理长距依存(long distance dependency),因此,NMT 模型一开始的表现并不好。</p><p>一年后的 2014 年,Sutskever et al. 和 Cho et al. 开发了一种名叫序列到序列(seq2seq)学习的方法,可以将 RNN 既用于编码器也用于解码器,并且还为 NMT 引入了长短时记忆(LSTM,是一种 RNN)。在门机制(gate mechanism)的帮助下,允许在 LSTM 中删除和更新明确的记忆,梯度爆炸/消失问题得到了控制,从而让模型可以远远更好地获取句子中的长距依存。</p><p>LSTM 的引入解决了长距离重新排序问题,同时将 NMT 的主要难题变成了固定长度向量(fixed-length vector)问题,不管源句子的长度几何,这个神经网络都需要将其压缩成一个固定长度的向量,这会在解码过程中带来更大的复杂性和不确定性,尤其是当源句子很长时。</p><p>自 2014 年 Yoshua Bengio 的团队为 NMT 引入了注意力(attention)机制之后,固定长度向量问题也开始得到解决。注意力机制最早是由 DeepMind 为图像分类提出的,这让神经网络在执行预测任务时可以更多关注输入中的相关部分,更少关注不相关的部分。当解码器生成一个用于构成目标句子的词时,源句子中仅有少部分是相关的。因此,可以应用一个基于内容的注意力机制来根据源句子动态地生成一个加权的语境向量(context vector),然后网络会根据这个语境向量而不是某个固定长度的向量来预测词。自那以后,NMT 的表现得到了显著提升,注意力编码器-解码器网络已经成为了 NMT 领域当前最佳的模型。</p><p>Transformer模型是在注意力机制上的进一步改进,不仅在Encoder-Decoder之间有注意力机制,其Encoder和Decoder自身也有自注意力机制(self-attention),即能注意输入序列的不同位置以计算该序列的表示的能力。</p><p><br></p><h1 id="Transform模型原理"><a href="#Transform模型原理" class="headerlink" title="Transform模型原理"></a>Transform模型原理</h1><p>Transformer 模型的核心思想是自注意力机制(self-attention),能注意输入序列的不同位置以计算该序列的表示的能力。Transformer 是多层自注意力层组成的堆栈。</p><p>Transformer 模型与标准的具有注意力机制的序列到序列模型遵循相同的一般模式。输入语句经过 N 个编码器层,为序列中的每个词/标记生成一个输出,解码器关注编码器的输出以及它自身的输入(自注意力)来预测下一个词。</p><p>其模型架构图如下:</p><p><img src="/images/transformer/clip_image002.png" alt="img"></p><p>Transformer 使用的注意力函数有三个输入:Q(请求(query))、K(主键(key))、V(数值(value))。点积注意力被缩小了深度的平方根倍,这样做是因为对于较大的深度值,点积的大小会增大,从而推动 softmax 函数往仅有很小的梯度的方向靠拢,导致了一种很硬的softmax。</p><p>例如,假设 Q 和 K 的均值为0,方差为1。它们的矩阵乘积将有均值为0,方差为 dk。因此,dk 的平方根被用于缩放(而非其他数值),因为,Q 和 K 的矩阵乘积的均值本应该为 0,方差本应该为1,这样会获得一个更平缓的 softmax。</p><p>遮挡(mask)与 -1e9(接近于负无穷)相乘,这样做是因为遮挡与缩放的 Q 和 K 的矩阵乘积相加,并在 softmax 之前立即应用,目标是将这些单元归零,因为 softmax 的较大负数输入在输出中接近于零。当 softmax 在 K 上进行归一化后,它的值决定了分配到 Q 的重要程度。输出表示注意力权重和 V(数值)向量的乘积。这确保了要关注的词保持原样,而无关的词将被清除掉。</p><p>其公式和架构图如下:</p><p><img src="/images/transformer/clip_image004.jpg" alt="img"></p><p><img src="/images/transformer/clip_image006.jpg" alt="img"></p><p>多头注意力由四部分组成:线性层并分拆成多头、按比缩放的点积注意力、多头及联、最后一层线性层。</p><p>每个多头注意力块有三个输入:Q(请求)、K(主键)、V(数值)。这些输入经过线性层,并分拆成多头。Q、K、和V被拆分到了多个头,而非单个的注意力头,因为多头允许模型共同注意来自不同表示空间的不同位置的信息。在分拆后,每个头部的维度减少,因此总的计算成本与有着全部维度的单个注意力头相同。将上面定义的缩放点积注意力函数应用于每个头(进行了广播以提高效率),然后将每个头的注意力输出连接起来,并放入最后的 Dense 层,最终输出注意力权重和输出。其公式和架构图如下:</p><p><img src="/images/transformer/clip_image008.jpg" alt="img"></p><p><img src="/images/transformer/clip_image010.jpg" alt="img"></p><p>因为该模型并不包括任何的循环或卷积,所以模型添加了位置编码,为模型提供一些关于单词在句子中相对位置的信息。</p><p>位置编码向量被加到嵌入向量中,嵌入表示一个 d 维空间的标记,在 d 维空间中有着相似含义的标记会离彼此更近。但是,嵌入并没有对在一句话中的词的相对位置进行编码。因此,当加上位置编码后,词将基于它们含义的相似度以及它们在句子中的位置,在 d 维空间中离彼此更近。</p><p>这里采用正弦余弦的位置编码方式,其公式如下:</p><p><img src="/images/transformer/clip_image012.jpg" alt="img"></p><p>在进行预测时,采用强制教学(teacher force),即上一步的输出当做下一步的输入,逐步预测出整个序列。</p><p><br></p><h1 id="Transform模型优缺点"><a href="#Transform模型优缺点" class="headerlink" title="Transform模型优缺点"></a>Transform模型优缺点</h1><p>一个 Transformer 模型用自注意力层而非 RNNs 或 CNNs 来处理变长的输入。这种通用架构有一系列的优势:</p><p>(1)它不对数据间的时间/空间关系做任何假设,这是处理一组对象的理想选择。</p><p>(2)层输出可以并行计算,而非像 RNN 这样的序列计算。</p><p>(3)远距离项可以影响彼此的输出,而无需经过许多 RNN 步骤或卷积层(4)它能学习长距离的依赖。在许多序列任务中,这是一项挑战。</p><p>该架构的目前的缺点是:</p><p>(1)对于时间序列,一个单位时间的输出是从整个历史记录计算的,而非仅从输入和当前的隐含状态计算得到,这可能效率较低。</p><p>(2)如果输入确实有时间/空间的关系,像文本,则必须加入一些位置编码,否则模型将有效地看到一堆单词。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="机器翻译发展变化趋势"><a href="#机器翻译发展变化趋势" class="headerlink" title="机器翻译发展变化趋势"></a>机器翻译发展变化趋势</h1><p>机器翻译(MT)是借机器之力,自动地将一种自然语言文本(源语言)翻译成另一种自然语言文本(目标语言)。使用机器做翻译的思想最早由 Warren Weaver 于 1949 年提出,在很长一段时间里(20 世纪 50 年代到 80 年代),机器翻译都是通过研究源语言与目标语言的语言学信息来做的,也就是基于词典和语法生成翻译,这被称为基于规则的机器翻译(RBMT)。随着统计学的发展,研究者开始将统计模型应用于机器翻译,这种方法是基于对双语文本语料库的分析来生成翻译结果。这种方法被称为统计机器翻译(SMT),它的表现比 RBMT 更好,并且在 1980 年代到 2000 年代之间主宰了这一领域。1997 年,Ramon Neco 和 Mikel Forcada 提出了使用编码器-解码器结构做机器翻译的想法。几年之后的 2003 年,蒙特利尔大学 Yoshua Bengio 领导的一个研究团队开发了一个基于神经网络的语言模型,改善了传统 SMT 模型的数据稀疏性问题。他们的研究工作为未来神经网络在机器翻译上的应用奠定了基础。</p>
</summary>
<category term="算法" scheme="https://www.awebone.com/categories/%E7%AE%97%E6%B3%95/"/>
<category term="面试" scheme="https://www.awebone.com/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="NLP" scheme="https://www.awebone.com/tags/NLP/"/>
</entry>
<entry>
<title>Hadoop面经总结</title>
<link href="https://www.awebone.com/posts/1d6a9c79/"/>
<id>https://www.awebone.com/posts/1d6a9c79/</id>
<published>2020-03-31T07:00:00.000Z</published>
<updated>2020-07-18T08:24:09.113Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文主要收集大数据Hadoop相关知识点总结。</p></blockquote><h1 id="HDFS总结"><a href="#HDFS总结" class="headerlink" title="HDFS总结"></a>HDFS总结</h1><h2 id="介绍一下HDFS的NameNode和DataNode"><a href="#介绍一下HDFS的NameNode和DataNode" class="headerlink" title="介绍一下HDFS的NameNode和DataNode"></a>介绍一下HDFS的NameNode和DataNode</h2><p>主节点NameNode:掌管文件系统目录树,处理客户端读写请求,负责管理整个文件系统的元数据,负责维持文件的副本数量</p><p>SecondaryNameNode:主要是给NameNode分担压力,把NN的fsimage和edit log做定期融合,融合后传给NN,以确保备份到的元数据是最新的,是冷备。</p><p>从节点DataNode:存储整个集群所有数据块,处理真正的数据读写,通过心跳信息定期地向NameNode汇报自身保存的文件块信息</p><a id="more"></a><h2 id="NameNode如何保证高可用"><a href="#NameNode如何保证高可用" class="headerlink" title="NameNode如何保证高可用"></a>NameNode如何保证高可用</h2><p>搭建Hadoop HA集群,通过多个NameNode实现集群中NameNode的热备,解决单点故障问题,保证高可用。在任何时候,要确保NameNode只有一个处于Active状态,其他处于Standby状态。</p><p>在高可用配置下,edit log不在存放在SecondaryNameNode,而是存放在QJM(quorum journal manager)共享存储系统中,Standby NameNode监听这个共享存储系统,发现新数据写入,则读取数据并且加载到自己内存中,确保自己的内存状态和Active NameNode保持一致。</p><h2 id="HDFS为什么不适合存储小文件"><a href="#HDFS为什么不适合存储小文件" class="headerlink" title="HDFS为什么不适合存储小文件"></a>HDFS为什么不适合存储小文件</h2><ol><li>数据的元信息存储在NameNode内存中,但是NameNode的内存和存储block数目是有限的。一个block元信息消耗大约150byte内存,存储一亿个block,会需要20GB内存。</li><li>相比于存取同等大小的一个大文件,存取大量小文件会消耗大量的寻道时间</li></ol><h2 id="Hadoop心跳机制"><a href="#Hadoop心跳机制" class="headerlink" title="Hadoop心跳机制"></a>Hadoop心跳机制</h2><ol><li>Hadoop是主从架构,Master有NameNode和ResourceManager,Slave有DataNode和NodeManager。</li><li>Master启动时会启动一个IPC Server(进程间通信服务),等待Slave的连接。</li><li>Slave启动时,主动连接Master的IPC Server,每隔3s连接一次。Slave通过心跳汇报自己的信息,Master通过心跳给Slave下达命令。</li><li>HDFS默认的超时时间为10min+30s,当超过这个时间还没有心跳,则认为节点宕机。其中10min为2次心跳重试间隔时间(5min),30秒为10次心跳间隔时间(3s)。</li></ol><h2 id="Hadoop正常启动时进入安全模式的原因"><a href="#Hadoop正常启动时进入安全模式的原因" class="headerlink" title="Hadoop正常启动时进入安全模式的原因"></a>Hadoop正常启动时进入安全模式的原因</h2><ol><li>NameNode的内存元数据中,包含文件路径、副本数、blockid、每一个block所在的DataNode的信息。但是在NameNode启动时,元数据从fsimage中加载,没有每一个block所在的DataNode的信息。</li><li>NameNode认为block丢失,block丢失率超过0.1%即进入安全模式。</li><li>DataNode启动后,通过心跳机制汇报自身持有的blockid信息,NameNode接受心跳,会将内存元数据中的每一个block所在的DataNode的信息补全,找到所有block位置后,退出安全模式。</li></ol><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文主要收集大数据Hadoop相关知识点总结。</p>
</blockquote>
<h1 id="HDFS总结"><a href="#HDFS总结" class="headerlink" title="HDFS总结"></a>HDFS总结</h1><h2 id="介绍一下HDFS的NameNode和DataNode"><a href="#介绍一下HDFS的NameNode和DataNode" class="headerlink" title="介绍一下HDFS的NameNode和DataNode"></a>介绍一下HDFS的NameNode和DataNode</h2><p>主节点NameNode:掌管文件系统目录树,处理客户端读写请求,负责管理整个文件系统的元数据,负责维持文件的副本数量</p>
<p>SecondaryNameNode:主要是给NameNode分担压力,把NN的fsimage和edit log做定期融合,融合后传给NN,以确保备份到的元数据是最新的,是冷备。</p>
<p>从节点DataNode:存储整个集群所有数据块,处理真正的数据读写,通过心跳信息定期地向NameNode汇报自身保存的文件块信息</p>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="面试" scheme="https://www.awebone.com/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="Hadoop" scheme="https://www.awebone.com/tags/Hadoop/"/>
</entry>
<entry>
<title>多种计算引擎实现WordCount</title>
<link href="https://www.awebone.com/posts/dd22b276/"/>
<id>https://www.awebone.com/posts/dd22b276/</id>
<published>2020-03-26T07:00:00.000Z</published>
<updated>2020-07-18T08:37:20.775Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用多种计算引擎实现词频统计</p></blockquote><h1 id="MapReduce实现"><a href="#MapReduce实现" class="headerlink" title="MapReduce实现"></a>MapReduce实现</h1><p>编写MapReduce程序分成三部分:<code>Mapper</code>、<code>Reducer</code>、<code>Driver</code></p><p><strong>业务逻辑</strong></p><ol><li><code>MapTask</code>阶段处理每个数据分块的单词统计分析,每遇到一个单词,将其转换为一个<code>k-v</code>对,如<code><hello, 1></code>的形式,发送给<code>ReduceTask</code>进行汇总</li><li><code>ReduceTask</code>阶段接受<code>MapTask</code>的结果,做汇总计数</li></ol><p><strong>Mapper接受的四个泛型</strong></p><ul><li><code>KEYIN</code>:输入的键的类型,在这里指的是每一行起始的偏移量</li><li><code>VALUEIN</code>:输入的值的类型,在这里指的是一行的内容</li><li><code>KEYOUT</code>:输出的键的类型,这里指的是单词,允许重复的</li><li><code>VALUEOUT</code>:输出的值的类型</li></ul><a id="more"></a><p><strong>Reducer接受的四个泛型</strong></p><ul><li><code>KEYIN</code>:map输出的key,指的就是单词</li><li><p><code>VALUEIN</code>:map输出的value,指的就是1</p></li><li><p><code>KEYOUT</code>:输出的key的类型,这里指的就是单词,这里的key不可以重复</p></li><li><code>VALUEOUT</code>:输出的value的类型,这里指的就是总的词频</li></ul><p><strong>Hadoop中自定义的序列化和反序列化的接口</strong></p><p>Java中的序列化和反序列化接口Serializable,将类结构一并进行序列化和反序列化,过于臃肿</p><ul><li><code>long——LongWritable</code></li><li><code>int——IntWritable</code></li><li><code>double——DoubleWritable</code></li><li><code>float——FloatWritable</code></li><li><code>null——NullWritable</code></li><li><code>string——Text</code></li></ul><p><strong>Map实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">WordCountMapper</span> <span class="keyword">extends</span> <span class="title">Mapper</span><<span class="title">LongWritable</span>, <span class="title">Text</span>, <span class="title">Text</span>, <span class="title">IntWritable</span>></span>{</div><div class="line"><span class="comment">/**</span></div><div class="line"> * 这个方法的调用频率:每行调用一次,文本中有几行就调用几次</div><div class="line"> * key:当前行的起始偏移量</div><div class="line"> * value:当前行的内容,和key是一一对应的</div><div class="line"> */</div><div class="line"> <span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">map</span><span class="params">(LongWritable key,</span></span></div><div class="line">Text value, </div><div class="line">Context context)</div><div class="line"><span class="keyword">throws</span> IOException, InterruptedException {</div><div class="line"><span class="comment">//拿到每一行的内容 进行分割 </span></div><div class="line"><span class="comment">//将text---String</span></div><div class="line">String line = value.toString();</div><div class="line"><span class="comment">//拆分单词</span></div><div class="line">String[] words = line.split(<span class="string">"\t"</span>);</div><div class="line"><span class="comment">//循环遍历每一个单词 进行打标机 1 发送给reduce进行统一统计</span></div><div class="line"><span class="keyword">for</span>(String w:words){</div><div class="line"><span class="comment">//参数1:key 参数2:value</span></div><div class="line"><span class="comment">//String--text</span></div><div class="line">Text k=<span class="keyword">new</span> Text(w);</div><div class="line">IntWritable v=<span class="keyword">new</span> IntWritable(<span class="number">1</span>);</div><div class="line">context.write(k, v);</div><div class="line">}</div><div class="line">}</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>Reduce实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">WordCountReducer</span> <span class="keyword">extends</span> <span class="title">Reducer</span><<span class="title">Text</span>, <span class="title">IntWritable</span>, <span class="title">Text</span>, <span class="title">IntWritable</span>></span>{</div><div class="line"><span class="comment">/**</span></div><div class="line"> * 这个方法的调用频率:每组调用一次</div><div class="line"> * 分组规则:key相同的为一组</div><div class="line"> * key:reduce输入的,这里指的是单词,每一组中的一个key</div><div class="line"> * values:每一组中的所有value,<1,1,1></div><div class="line"> */</div><div class="line"><span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">reduce</span><span class="params">(Text key, </span></span></div><div class="line">Iterable<IntWritable> values,</div><div class="line">Context context) <span class="keyword">throws</span> IOException, InterruptedException {</div><div class="line"><span class="comment">//进行词频统计</span></div><div class="line"><span class="keyword">int</span> sum=<span class="number">0</span>;</div><div class="line"><span class="comment">//循环变遍历values 求和</span></div><div class="line"><span class="keyword">for</span>(IntWritable v:values){</div><div class="line"><span class="comment">//v.get() 这个是将intwritable转换为int</span></div><div class="line">sum+=v.get();</div><div class="line">}</div><div class="line">context.write(key, <span class="keyword">new</span> IntWritable(sum));</div><div class="line">}</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>Driver实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Driver</span> </span>{</div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span></div><div class="line"> <span class="keyword">throws</span> IOException, ClassNotFoundException, InterruptedException {</div><div class="line">System.setProperty(<span class="string">"HADOOP_USER_NAME"</span>, <span class="string">"hadoop"</span>);</div><div class="line"><span class="comment">//加载配置文件</span></div><div class="line">Configuration conf=<span class="keyword">new</span> Configuration();</div><div class="line"><span class="comment">//启动一个job:一个map reduce程序,这里叫做一个job</span></div><div class="line">Job job=Job.getInstance(conf);</div><div class="line"></div><div class="line"><span class="comment">//ָ指定job运行的主类</span></div><div class="line">job.setJarByClass(Driver.class);</div><div class="line"></div><div class="line"><span class="comment">//指定这个job的mapper类和reduce类</span></div><div class="line">job.setMapperClass(WordCountMapper.class);</div><div class="line">job.setReducerClass(WordCountReducer.class);</div><div class="line"></div><div class="line"><span class="comment">//指定map的输出的key和value的类型</span></div><div class="line"><span class="comment">//这里为什么还要指定:泛型的只在编译的时候有作用,运行会自动擦除,所以在这里需要指定一下</span></div><div class="line">job.setMapOutputKeyClass(Text.class);</div><div class="line">job.setMapOutputValueClass(IntWritable.class);</div><div class="line"></div><div class="line"><span class="comment">//指定reduce输出的key和value类型</span></div><div class="line">job.setOutputKeyClass(Text.class);</div><div class="line">job.setOutputValueClass(IntWritable.class);</div><div class="line"></div><div class="line"><span class="comment">//指定combiner组件</span></div><div class="line"><span class="comment">//job.setCombinerClass(WordCountReducer.class);</span></div><div class="line"><span class="comment">//添加自定义分区</span></div><div class="line"><span class="comment">//job.setPartitionerClass(MyPartitioner.class);</span></div><div class="line"><span class="comment">// 这个参数如果不指定,默认reducetask=1</span></div><div class="line">job.setNumReduceTasks(<span class="number">4</span>);</div><div class="line"></div><div class="line"> <span class="comment">//传参方式</span></div><div class="line"><span class="comment">//FileInputFormat.addInputPath(job, new Path(args[0]));</span></div><div class="line"><span class="comment">//添加输出路径:输出路径一定不能存在,怕如果存在会进行覆盖</span></div><div class="line"><span class="comment">//FileOutputFormat.setOutputPath(job, new Path(args[1]));</span></div><div class="line"> </div><div class="line"> <span class="comment">//固定写死</span></div><div class="line">FileInputFormat.addInputPath(job, <span class="keyword">new</span> Path(<span class="string">"hdfs://hadoop01:9000/in"</span>));</div><div class="line">FileOutputFormat.setOutputPath(job, <span class="keyword">new</span> Path(<span class="string">"hdfs://hadoop01:9000/out"</span>));</div><div class="line"><span class="comment">//提交job</span></div><div class="line">job.waitForCompletion(<span class="keyword">true</span>);</div><div class="line">}</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Scala实现"><a href="#Scala实现" class="headerlink" title="Scala实现"></a>Scala实现</h1><p>定义数据:<code>array = Array("a b", "c c", "b c")</code></p><h2 id="第一种方式实现"><a href="#第一种方式实现" class="headerlink" title="第一种方式实现"></a>第一种方式实现</h2><figure class="highlight scala"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">val</span> countWord = array.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.groupBy(_._1)</div><div class="line">.map( x => (x._1, x._2.length))</div><div class="line">.toList</div><div class="line">.sortBy(_._2)</div><div class="line">.reverse</div></pre></td></tr></tbody></table></figure><p><strong>中间结果详解</strong></p><ul><li><code>array.map(_.split(" "))</code>输出:<code>Array(Array("a","b"), Array("c","c"), Array("b","c"))</code></li><li>使用<code>flatMap(_.split(" "))</code>输出:<code>Array("a","b", "c","c", "b","c")</code></li><li>再使用<code>map((_,1))</code>输出:<code>Array((a,1), (b,1), (c,1), (c,1), (b,1), (c,1))</code></li><li>再使用<code>groupBy(_._1)</code>输出:<code>(a,1),(b,1),(b,1),(c,1),(c,1),(c,1)</code>,即<code>Map(b -> Array((b,1), (b,1)), a -> Array((a,1)), c -> Array((c,1), (c,1), (c,1)))</code></li><li>在进行计数:<code>array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length))</code></li><li>从大到小排序:<code>array.flatMap(_.split(" ")).map((_,1)).groupBy(_._1).map( x => (x._1, x._2.length)).toList.sortBy(_._2).reverse</code></li></ul><h2 id="其他方式实现"><a href="#其他方式实现" class="headerlink" title="其他方式实现"></a>其他方式实现</h2><figure class="highlight scala"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">val</span> countWord1 = array.map(_.split(<span class="string">" "</span>))</div><div class="line">.flatten</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.groupBy(_._1)</div><div class="line">.map(t => (t._1,t._2.size))</div><div class="line">.toList</div><div class="line">.sortBy(_._2)</div><div class="line">.reverse</div><div class="line"></div><div class="line"><span class="keyword">val</span> countWord2 = array.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.groupBy(_._1)</div><div class="line">.mapValues(_.size)</div><div class="line">.toList</div><div class="line">.sortBy(_._2)</div><div class="line">.reverse</div><div class="line"></div><div class="line"><span class="keyword">val</span> countWord3 = array.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.groupBy(_._1)</div><div class="line">.mapValues(_.foldLeft(<span class="number">0</span>)(_+_._2))</div><div class="line">.toList</div><div class="line">.sortBy(_._2)</div><div class="line">.reverse</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="Spark-Shell实现"><a href="#Spark-Shell实现" class="headerlink" title="Spark-Shell实现"></a>Spark-Shell实现</h1><h2 id="第一种方式实现-1"><a href="#第一种方式实现-1" class="headerlink" title="第一种方式实现"></a>第一种方式实现</h2><figure class="highlight scala"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">sc.textFile(<span class="string">"hdfs://myha/spark/wc/input/words.txt"</span>)</div><div class="line">.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_, <span class="number">1</span>))</div><div class="line">.reduceByKey(_+_)</div><div class="line">.collect</div></pre></td></tr></tbody></table></figure><p><strong>详解</strong></p><ul><li><code>sc</code>是<code>SparkContext</code>对象,该对象是提交<code>spark</code>程序的入口</li><li><code>textFile("hdfs://myha/spark/wc/input/words.txt")</code>是从<code>HDFS</code>中读取数据</li><li><code>flatMap(_.split(" "))</code>先<code>map</code>再压平</li><li><code>map((_,1))</code>将单词和1构成元组</li><li><code>reduceByKey(_+_)</code>按照<code>key</code>进行<code>reduce</code>,并将<code>value</code>累加</li><li><code>saveAsTextFile("hdfs://myha/spark/wc/output")</code>将结果写入到<code>HDFS</code>中</li><li>其中:<code>reduceByKey = groupByKey + reduce = groupBy + reduce = groupBy + map</code></li></ul><h2 id="其他方式实现-1"><a href="#其他方式实现-1" class="headerlink" title="其他方式实现"></a>其他方式实现</h2><figure class="highlight scala"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">sc.textFile(<span class="string">"hdfs://myha/spark/wc/input/words.txt"</span>)</div><div class="line">.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.reduceByKey(_+_)</div><div class="line">.collect</div><div class="line">.foreach(println)</div><div class="line"></div><div class="line">sc.textFile(<span class="string">"hdfs://myha/spark/wc/input/words.txt"</span>)</div><div class="line">.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.countByValue</div><div class="line">.foreach(println)</div><div class="line"></div><div class="line">sc.textFile(<span class="string">"hdfs://myha/spark/wc/input/words.txt"</span>)</div><div class="line">.flatMap(_.split(<span class="string">" "</span>))</div><div class="line">.map((_,<span class="number">1</span>))</div><div class="line">.countByKey()</div><div class="line">.foreach(println)</div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用多种计算引擎实现词频统计</p>
</blockquote>
<h1 id="MapReduce实现"><a href="#MapReduce实现" class="headerlink" title="MapReduce实现"></a>MapReduce实现</h1><p>编写MapReduce程序分成三部分:<code>Mapper</code>、<code>Reducer</code>、<code>Driver</code></p>
<p><strong>业务逻辑</strong></p>
<ol>
<li><code>MapTask</code>阶段处理每个数据分块的单词统计分析,每遇到一个单词,将其转换为一个<code>k-v</code>对,如<code>&lt;hello, 1&gt;</code>的形式,发送给<code>ReduceTask</code>进行汇总</li>
<li><code>ReduceTask</code>阶段接受<code>MapTask</code>的结果,做汇总计数</li>
</ol>
<p><strong>Mapper接受的四个泛型</strong></p>
<ul>
<li><code>KEYIN</code>:输入的键的类型,在这里指的是每一行起始的偏移量</li>
<li><code>VALUEIN</code>:输入的值的类型,在这里指的是一行的内容</li>
<li><code>KEYOUT</code>:输出的键的类型,这里指的是单词,允许重复的</li>
<li><code>VALUEOUT</code>:输出的值的类型</li>
</ul>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="算法" scheme="https://www.awebone.com/tags/%E7%AE%97%E6%B3%95/"/>
<category term="面试" scheme="https://www.awebone.com/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>Java单例模式</title>
<link href="https://www.awebone.com/posts/86ceb8f1/"/>
<id>https://www.awebone.com/posts/86ceb8f1/</id>
<published>2020-03-20T07:00:00.000Z</published>
<updated>2020-07-18T08:27:19.647Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="懒汉式"><a href="#懒汉式" class="headerlink" title="懒汉式"></a>懒汉式</h1><p>在初次调用静态方法getSingleton,才会初始化signleton实例。</p><p><strong>双重检查模式实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singletom</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> Singletom singletom;</div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singletom</span><span class="params">()</span></span>{}</div><div class="line"> </div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singletom <span class="title">getSingleton</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">if</span> (singletom == <span class="keyword">null</span>){</div><div class="line"> <span class="keyword">synchronized</span> (Singletom.class){</div><div class="line"> <span class="keyword">if</span> (singletom == <span class="keyword">null</span>){</div><div class="line"> singletom = <span class="keyword">new</span> Singletom();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> singletom;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><ul><li><p>实现了延迟初始化,只有在初次调用静态方法getSingleton,才会初始化signleton实例。</p></li><li><p>性能优化,同步会造成性能下降,在同步前通过判读singleton是否初始化,减少不必要的同步开销。</p></li><li><p>线程安全,同步创建Singleton对象,同时注意到静态变量singleton使用volatile修饰,避免JVM进行优化重排序。</p></li></ul><a id="more"></a><p><strong>静态内部类实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singletom</span> </span>{</div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singletom</span><span class="params">()</span></span>{}</div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singletom <span class="title">getSingleton</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">return</span> Inner.instance;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Singletom instance = <span class="keyword">new</span> Singletom();</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><ul><li>代码简洁,和双重检查模式对比,静态内部类单例实现清晰明了。</li></ul><ul><li><p>延迟初始化,调用getSingleton才初始化Singleton对象。</p></li><li><p>线程安全,JVM在执行类的初始化阶段,会获得一个可以同步多个线程对同一个类的初始化的锁。</p></li></ul><p><br></p><h1 id="饿汉式"><a href="#饿汉式" class="headerlink" title="饿汉式"></a>饿汉式</h1><p>直接初始化signleton实例,直接获取实例,没有延迟初始化。</p><p><strong>多线程安全实现</strong></p><figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singletom</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Singletom instance = <span class="keyword">new</span> Singletom();</div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singletom</span><span class="params">()</span></span>{}</div><div class="line"> </div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singletom <span class="title">getSingleton</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">return</span> instance;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="懒汉式"><a href="#懒汉式" class="headerlink" title="懒汉式"></a>懒汉式</h1><p>在初次调用静态方法getSingleton,才会初始化signleton实例。</p>
<p><strong>双重检查模式实现</strong></p>
<figure class="highlight java"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singletom</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> Singletom singletom;</div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="title">Singletom</span><span class="params">()</span></span>{}</div><div class="line"> </div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singletom <span class="title">getSingleton</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">if</span> (singletom == <span class="keyword">null</span>){</div><div class="line"> <span class="keyword">synchronized</span> (Singletom.class){</div><div class="line"> <span class="keyword">if</span> (singletom == <span class="keyword">null</span>){</div><div class="line"> singletom = <span class="keyword">new</span> Singletom();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> singletom;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure>
<ul>
<li><p>实现了延迟初始化,只有在初次调用静态方法getSingleton,才会初始化signleton实例。</p>
</li>
<li><p>性能优化,同步会造成性能下降,在同步前通过判读singleton是否初始化,减少不必要的同步开销。</p>
</li>
<li><p>线程安全,同步创建Singleton对象,同时注意到静态变量singleton使用volatile修饰,避免JVM进行优化重排序。</p>
</li>
</ul>
</summary>
<category term="Java" scheme="https://www.awebone.com/categories/Java/"/>
<category term="面试" scheme="https://www.awebone.com/tags/%E9%9D%A2%E8%AF%95/"/>
<category term="Java" scheme="https://www.awebone.com/tags/Java/"/>
</entry>
<entry>
<title>ElasticSearch安装避坑</title>
<link href="https://www.awebone.com/posts/62e0a87a/"/>
<id>https://www.awebone.com/posts/62e0a87a/</id>
<published>2020-03-17T07:00:00.000Z</published>
<updated>2020-07-18T08:23:21.523Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>本文使用Centos7安装ElasticSearch6.5.2,记录避坑指南。</p></blockquote><h1 id="升级内核"><a href="#升级内核" class="headerlink" title="升级内核"></a>升级内核</h1><p>通过命令查看内核:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">uname -a</div><div class="line"># 3.10.0-327.el7.x86_64</div></pre></td></tr></tbody></table></figure><p>Centos7自带的内核为3.10,但是ElasticSearch6.5.2要求系统内核必须在3.5以上,故升级内核,root用户下执行:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"># 导入key</div><div class="line">rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org </div><div class="line"># 安装elrepo的yum源</div><div class="line">rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm</div><div class="line"># 安装内核</div><div class="line">yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml</div><div class="line"># 查看默认启动顺序</div><div class="line">awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg</div><div class="line"># 默认启动的顺序是从0开始,新内核是从头插入,选择0</div><div class="line">grub2-set-default 0</div></pre></td></tr></tbody></table></figure><p>安装完毕后重启<code>reboot</code>生效</p><p>查看内核为5.5.9:<code>Linux awebone.com 5.5.9-1.el7.elrepo.x86_64 #1 SMP Wed Mar 11 19:01:01 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux</code></p><p>如果遇到<code>curl 不兼容或不支持的协议版本</code>的问题,通过以下方法解决:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yum update -y nss curl libcurl</div></pre></td></tr></tbody></table></figure><a id="more"></a><p><br></p><h1 id="关闭防火墙和SELinux"><a href="#关闭防火墙和SELinux" class="headerlink" title="关闭防火墙和SELinux"></a>关闭防火墙和SELinux</h1><p>因为在本地虚拟机安装,关闭防火墙和SELinux,方便测试:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"># 查看防火墙状态</div><div class="line">systemctl status firewalld</div><div class="line"># 关闭防火墙</div><div class="line">systemctl stop firewalld</div><div class="line"># 设置开机不启动</div><div class="line">sudo systemctl disable firewalld.service</div><div class="line"></div><div class="line"># 关闭SELinux</div><div class="line">setenforce 1</div><div class="line"># 查看SELinux状态</div><div class="line">getenforce</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="安装JDK1-8和ElasticSearch"><a href="#安装JDK1-8和ElasticSearch" class="headerlink" title="安装JDK1.8和ElasticSearch"></a>安装JDK1.8和ElasticSearch</h1><p>通过官网下载安装包<code>elasticsearch-6.5.2.tar.gz</code>和<code>jdk-8u73-linux-x64.tar.gz</code></p><h2 id="安装JDK"><a href="#安装JDK" class="headerlink" title="安装JDK"></a>安装JDK</h2><p>ES要求jdk需要为1.8版本以上,故删除自带的1.7:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">rpm -qa |grep java</div><div class="line">sudo yum -y remove java*</div></pre></td></tr></tbody></table></figure><p>解压jdk到apps目录下:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">tar -zxvf jdk-8u73-linux-x64.tar.gz -C ~/apps/</div></pre></td></tr></tbody></table></figure><p>配置环境变量:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">sudo vim /etc/profile</div><div class="line"></div><div class="line"># 在最后添加以下内容,目录改为自己的:</div><div class="line">JAVA_HOME=/home/xxx/apps/jdk1.8.0_73</div><div class="line">JRE_HOME=$JAVA_HOME/jre</div><div class="line">PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin</div><div class="line">CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib</div><div class="line">export JAVA_HOME JRE_HOME PATH CLASSPATH</div></pre></td></tr></tbody></table></figure><p>最后加载环境变量:<code>source /etc/profile</code></p><p>查看JDK版本:<code>java -version</code></p><p><img src="/images/es/es1.png" alt="es1"></p><h2 id="安装ElasticSearch"><a href="#安装ElasticSearch" class="headerlink" title="安装ElasticSearch"></a>安装ElasticSearch</h2><p>注意:ES从2.X版本起,就不能再root用户下安装,故在普通用户下安装</p><p>解压到apps目录下:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">tar -zxvf elasticsearch-6.5.2.tar.gz -C ~/apps/</div></pre></td></tr></tbody></table></figure><p>配置环境变量:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">vim ~/.bashrc </div><div class="line"></div><div class="line"># 在最后添加以下内容:</div><div class="line">ELASTICSEARCH_HOME=/home/linuxprobe/apps/elasticsearch-6.5.2</div><div class="line">export PATH=$PATH:$ELASTICSEARCH_HOME/bin</div></pre></td></tr></tbody></table></figure><p>加载环境变量:<code>source ~/.bashrc</code></p><p>进行ElasticSearch的配置,修改<code>$ELASTICSEARCH_HOME/conf/elasticsearch.yml</code>文件:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">vim $ELASTICSEARCH_HOME/conf/elasticsearch.yml</div><div class="line"></div><div class="line"># 填入以下内容,目录改为自己的</div><div class="line">cluster.name: es</div><div class="line">node.name: hadoop</div><div class="line">path.data: /home/xxx/data/elastic(手动创建目录)</div><div class="line">path.logs: /home/xxx/logs/elastic(手动创建目录)</div><div class="line">network.host: 0.0.0.0</div><div class="line">http.port: 9200</div></pre></td></tr></tbody></table></figure><p>启动:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"># es后台启动,不加-d为前台启动</div><div class="line">elasticsearch -d</div></pre></td></tr></tbody></table></figure><p>测试:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"># 查看java进程状态</div><div class="line">jps</div><div class="line"></div><div class="line"># 查看服务状态</div><div class="line">curl -XGET http://localhost:9200</div></pre></td></tr></tbody></table></figure><p><img src="/images/es/es2.png" alt="es2"></p><p>通过网页查看:</p><p><img src="/images/es/es3.png" alt="es3"></p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>本文使用Centos7安装ElasticSearch6.5.2,记录避坑指南。</p>
</blockquote>
<h1 id="升级内核"><a href="#升级内核" class="headerlink" title="升级内核"></a>升级内核</h1><p>通过命令查看内核:</p>
<figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">uname -a</div><div class="line"># 3.10.0-327.el7.x86_64</div></pre></td></tr></tbody></table></figure>
<p>Centos7自带的内核为3.10,但是ElasticSearch6.5.2要求系统内核必须在3.5以上,故升级内核,root用户下执行:</p>
<figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"># 导入key</div><div class="line">rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org </div><div class="line"># 安装elrepo的yum源</div><div class="line">rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm</div><div class="line"># 安装内核</div><div class="line">yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml</div><div class="line"># 查看默认启动顺序</div><div class="line">awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg</div><div class="line"># 默认启动的顺序是从0开始,新内核是从头插入,选择0</div><div class="line">grub2-set-default 0</div></pre></td></tr></tbody></table></figure>
<p>安装完毕后重启<code>reboot</code>生效</p>
<p>查看内核为5.5.9:<code>Linux awebone.com 5.5.9-1.el7.elrepo.x86_64 #1 SMP Wed Mar 11 19:01:01 EDT 2020 x86_64 x86_64 x86_64 GNU/Linux</code></p>
<p>如果遇到<code>curl 不兼容或不支持的协议版本</code>的问题,通过以下方法解决:</p>
<figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yum update -y nss curl libcurl</div></pre></td></tr></tbody></table></figure>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="ELK" scheme="https://www.awebone.com/tags/ELK/"/>
</entry>
<entry>
<title>MySQL基本使用</title>
<link href="https://www.awebone.com/posts/75c6e52f/"/>
<id>https://www.awebone.com/posts/75c6e52f/</id>
<published>2019-03-17T07:00:00.000Z</published>
<updated>2020-04-01T01:58:59.099Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="MySQL基本使用"><a href="#MySQL基本使用" class="headerlink" title="MySQL基本使用"></a>MySQL基本使用</h1><h2 id="修改MySQL提示符"><a href="#修改MySQL提示符" class="headerlink" title="修改MySQL提示符"></a>修改MySQL提示符</h2><p><strong>修改提示符的两种方式:</strong></p><ol><li>连接客户端时通过参数指定:<code>shell>mysql -uroot -proot --prompt</code> 提示符</li><li>连接上客户端后,通过<code>prompt</code>修改:<code>mysql>prompt</code> 提示符</li></ol><p><strong>修改参数:</strong></p><p><code>\D</code> 完整日期<br><code>\d</code> 数据库<br>还可以搭配一起<code>+</code>符号<br><code>\h</code> 服务器<br><code>\u</code> 用户</p><a id="more"></a><h2 id="MySQL常用命令"><a href="#MySQL常用命令" class="headerlink" title="MySQL常用命令"></a>MySQL常用命令</h2><p><strong>系统查看:</strong></p><p><code>VERSION();</code> 当前数据库版本<br><code>NOW();</code>当前系统时间<br><code>USER();</code> 当前登录的用户</p><p><strong>MySQL语句的规范:</strong></p><ol><li>关键字与函数名称全部大写</li><li>数据库名称、表名称、字段名称全部小写</li><li>SQL语句必须以分号结尾</li></ol><h2 id="数据库相关语句"><a href="#数据库相关语句" class="headerlink" title="数据库相关语句"></a>数据库相关语句</h2><blockquote><p>成功安装后默认会带4个数据库;{}代表必选项;”|”代表从这里面做选择;中括号[]代表有或没有都可以,可选项。</p></blockquote><ul><li><p>查看所有数据库</p><p><code>SHOW DATABASES;</code></p></li><li><p>查看所有警告</p><p><code>SHOW WARNINGS;</code></p></li><li><p>查看数据库创建时的信息</p><p><code>SHOW CREATE DATABASE db_name(数据库名);</code></p></li><li><p>新建数据库</p><p><code>CREATE {DATABASE|SCHERMA}[IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET = charset_name</code></p><p>如:新建数据库并设置格式</p><p><code>CREATE DATABASE IF NOT EXISTS db_name [DEFAULT] (default可省略)CHARACTER SET utf-8(格式,默认utf-8,可以改为任意的);</code></p></li><li><p>修改数据库</p><p><code>ALTER {DATABASE|SCHEMA}[db_name][DEFAULT] CHARACTER SET charset_name;</code></p><p>如果需要修改编码格式,可写:</p><p><code>ALTER DATABASE db_name CHARACTER SET = uft8;</code></p></li><li><p>删除数据库</p><p><code>DROP {DATABASE|SCHEMA}[IF EXISTS] db_name;</code></p></li></ul><h2 id="表相关语句"><a href="#表相关语句" class="headerlink" title="表相关语句"></a>表相关语句</h2><ul><li><p>打开某个数据库</p><p><code>USE db_name;</code></p></li><li><p>查看用户当前所打开的数据库</p><p><code>SELECT DATABASE();</code></p></li><li><p>创建数据表(如果数据表已存在,加上<code>if not exists</code>,系统将不提示错误,否则会提示错误)</p><p><code>CREATE TABLE[IF NOT EXISTS] table_name(colume_name data_type);</code></p><p>列名称:经过分析得到</p><p>数据类型:整型,浮点型等</p><p>注意:逗号是两个字段之间的分隔符,最后一个字段不需要加逗号。</p><p>例子:</p><figure class="highlight sql"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/*打开要创建表的数据库*/</span></div><div class="line"><span class="keyword">USE</span> 数据库名;</div><div class="line"></div><div class="line"><span class="comment">/*在打开的数据库中创建表*/</span></div><div class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> tb1(</div><div class="line"> username <span class="built_in">VARCHAR</span>(<span class="number">20</span>), </div><div class="line"> age TINYINT <span class="keyword">UNSIGNED</span>,</div><div class="line"> salary <span class="built_in">FLOAT</span>(<span class="number">8</span>,<span class="number">2</span>) <span class="keyword">UNSIGNED</span></div><div class="line">);</div></pre></td></tr></tbody></table></figure></li><li><p>显示当前数据库的表</p><p><code>SHOW TABLES;</code></p></li><li><p>显示mysql库中的表</p><p><code>SHOW TABLES FROM mysql;</code></p><p>注:但是并没有改变当前数据库,只是显示了一次其他数据库的列表</p></li><li><p>查看数据表结构</p><p><code>SHOW COLUMNS FROM table_name;</code></p></li><li><p>插入数据</p><p><code>INSERT [INTO] tb_name(表名) [col_name,....](表里的哪几列要赋值,可省略) VALUES(val,...)(值是多少)</code></p><p>如果省略列的名称,必须给所有字段赋值,否则会报错。</p></li><li><p>查询全表</p><p><code>SELECT * FROM tb1;</code></p></li></ul><h2 id="创建表时需要注意的字段控制"><a href="#创建表时需要注意的字段控制" class="headerlink" title="创建表时需要注意的字段控制"></a>创建表时需要注意的字段控制</h2><p><strong>字段是否为空</strong></p><p><code>NULL</code>:字段值可为空</p><p><code>NOT NULL</code>:字段值不为空</p><p>同一个字段不可能既为NULL,又为NOT NULL</p><p>在创建数据表的时候,如果字段值可为空,可以写NULL,也可省略,不写的话默认为空,如果为空可赋值也可不赋值</p><figure class="highlight sql"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> tb2(</div><div class="line"> username <span class="built_in">VARCHAR</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</div><div class="line"> age TINYINT <span class="keyword">UNSIGNED</span> <span class="literal">NULL</span></div><div class="line">);</div></pre></td></tr></tbody></table></figure><p><strong>字段是否自增</strong></p><p>字段为数值型时可为整数或浮点数,为浮点数时小数位必须要为0,如:<code>FLOAT (7,0)</code></p><p><code>AUTO_INCREMENT</code>:自动编号,必须与主键组合使用,否则会报错,默认情况下,起始值为1,每次的增量为1,保证记录唯一性</p><p><code>AUTO_INCREMENT</code>必须和<code>PRIMARY KEY</code> 一起使用,每次自增1,可不进行赋值</p><p>而<code>PRIMARY KEY</code> 可以不和<code>AUTO_INCREMENT</code>一起使用,可以被赋值但是不允许有相同值的出现</p><figure class="highlight sql"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> tb3(</div><div class="line"> <span class="keyword">id</span> <span class="built_in">SMALLINT</span> <span class="keyword">UNSIGNED</span> AUTO_INCREMENT PRIMARY <span class="keyword">KEY</span>,</div><div class="line"> username <span class="built_in">VARCHAR</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span></div><div class="line">);</div></pre></td></tr></tbody></table></figure><p><strong>字段是否唯一</strong></p><p><code>unique key</code>:唯一约束</p><p>唯一约束可以保证记录的唯一性</p><p>唯一约束的字段可以为空值(null),即使存储多个值,最终保留的空值也只有一个,故可以保证唯一性。</p><p>每张数据表可以存在多个唯一约束,可以存在多个空值null,primary key就只有1个。</p><p>唯一约束添加语句:<code>username varchar(20) not null unique key</code></p><p>达到的效果就是如果插入语句有相同的字段,那么会约束它,只能保证数据唯一性。</p><p><strong><code>primary key</code>与<code>unique key</code>的区别</strong></p><p><code>primary key</code>与<code>unique key</code>都是唯一性约束,但二者有很大的区别:</p><ol><li>作为<code>primary key</code>的1个或多个列必须为<code>NOT NULL</code>,而<code>unique key</code>约束的列可以为<code>null</code>,这是<code>primary key</code>与<code>unique key</code>最大的区别。</li><li>一个表只能有一个<code>primary key</code>(单列或多列,多列主键叫联合主键),但可以有多个<code>unique key</code>。</li></ol><p><strong>默认值设置</strong></p><p>default 设置:当插入记录时,如果没有明确为字段赋值,则自动赋予默认值</p><p><code>sex enum('1','2','3') default '3'</code></p><p>这个语句要达成的效果就是性别提供三个选项:1男,2女,3保密,那么如果数据插入没有添加性别,那么默认为3选项</p><h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><p><strong>字符型</strong></p><p><img src="/images/mysql/mysql_char.jpg" alt="mysql_char"></p><p><strong>整型</strong></p><p><img src="/images/mysql/mysql_int.jpg" alt="mysql_int"></p><p><strong>浮点型</strong></p><p><img src="/images/mysql/mysql_float.jpg" alt="mysql_float"></p><p><strong>日期时间型</strong></p><p><img src="/images/mysql/mysql_data.jpg" alt="mysql_data"></p><p>数据表操作:插入几录 查找记录<br>记录操作:创建数据表 约束的使用</p><p>create table table_name 创建数据表<br>show columns from table_name查看数据表结构<br>select*from table_name数据查找,验证数据是否成功写入。</p><p>auto_increment必须要和主键一起使用 但是主键可以不和auto_increment一起使用 不一起使用时主键可以自主赋值<br>PRIMARY KEY 主键约束 一张表只能有一个主键约束<br>Unique key 唯一约束 一个表可以有多个Unique约束<br>default 默认约束</p><p>具有外键列的表称为子表;子表所参照的表称为父表<br>1.父表和子表必须使用相同的存储引擎,而且禁止使用临时表<br>2.数据表的存储引擎只能为InnoDB<br>3.外键列和参照列必须具有相似的数据类型,其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同<br>4.外键列和参照列必须创建索引,如果参照列不存在索引的话,mysql将自动创建索引;如果外键列没有索引,mysql将不会自动创建索引(此处根据语音修改,与PPT内容不一致——经查,mysql5.5以上的版本不会自动创建外键索引,但根据实际情况,创建外建索引很有必要。)</p><p>表级约束:约束只针对某一字段<br>列级约束:约束针对两个及两个以上字段<br>FOREIGN KEY(外键约束):保持数据的一致性,完整性。实现数据表的一对一,一对多的关系。<br>1,父表(子表所参照的表)和子表(具有外键列的表)必须使用相同的存储引擎,而且禁止使用临时表。<br>2,数据表的存储引擎只能为InnoDB(可在my.ini查看修改。5.7版本my.ini地址:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini)。<br>3,外键列(曾经加过foreign关键词的那一列)和参照列(外键列所参照的那列)必须具有相似的数据类型(字符,整型,日期时间等)。其中数字的长度或是否有符号位(如整型有无符号(unsigned)和有符号(signed)两种类型;)必须相同;而字符的长度则可以不同。比如说父表里面有一个参数id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,子表里面就要写作pid SMALLINT UNSIGNED(符号位和数据类型要相似)<br>4,外键列和参照列必须创建索引。如果外键列不存在索引的话,MySQL将自动创建索引。<br>FOREIGN KEY (pid)REFERENCES 父表名(id)<br>也就是users表中有两个索引(id pid)<br>外键列:pid (可自定义)<br>参照列:id (可自定义)<br>SHOW INDEXES FROM table_name查看索引<br>SHOW INDEXES FROM table_name\G;以网格方式来查看索引</p><p>外键约束的参照操作:<br>在实际的项目开发中,为避免受引擎限制,通常使用逻辑外键约束,而不使用此物理的外键约束(按照外键的定义来设计数据表,但不使用FOREIGN KEY)。<br>1.CASCADE从父表删除或更新时自动删除或更新子表中的匹配行<br>2.SET NULL从父表删除或更新行时,设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定NOT NULL<br>3.RESTRICT拒绝对父表的删除或更新操作<br>4.NO ACTION标准的SQL关键字,在mysql中与RESTRICT作用相同</p><p>对于一个列所创建的约束,称之为列级约束。<br>而对于两个或两个以上的列所创建的约束,我们称之为表级约束。<br>列级约束在使用时,既可以在列定义的时候声明,也可以在列定义以后声明,而表级的约束只能在列定义以后来声明。<br>在实际开发中,用列级约束比较多,表级约束很少用,<br>在所有的约束中,并不是说每种约束都存在着表级或列级约束,其中,NOT NULL 非空约束,DEFAULT约束这两种约束就不存在表级约束,它们只有列级约束,而对于其他的三种,像主键,唯一,外键,它们都可以存在表级和列级约束。</p><p>删除列:ALTER TABLE tb1_name DROP[COLUMN] col_name;<br>添加多列:ALTER TABLE tb1_name ADD[COLUMN] (col_name column_definition,…);<br>添加单列:ALTER TABLE tb1_name ADD[COLUMN] col_name column_definition [FIRST|AFTER col_name];<br>删除记录:DELETE FROM province WHERE id=3;<br>验证表中是否有相应的记录:SELECT * FROM province;<br>显示索引:SHOW INDEXES FROM province;SHOW INDEXES FROM province\G;(以网格呈现)<br>打开数据表test:USE test;<br>查看创建命令:SHOW CREATE TABLE province;<br>查看数据表结构:SHOW COLUMNS FROM tb3;<br>插入记录:INSERT [INTO] tb1_name [(col_name,…)] VALUES (val,…);<br>查看数据表列表:SHOW TABLES [FROM db_name] [LIKE ‘pattern’|WHERE expr];<br>添加的单列将他至于那一列后面语句:after 后面跟要添加其下的列名<br>alter table users1 add 要添加的列名 varchar(32) not null after 列名;<br>将添加的单列位于所有列之前:first<br>alter table users1 add 要添加的列名和属性 first;<br>多个操作可以同时操作,用逗号分开</p><p>增加一行<br>ALTER TABLE tb_name ADD age SMALLINT UNSIGNED NOT NULL;<br>添加主键约束(只能添加一个)<br>ALTER TABLE tbl_name ADD [CONSTRAINT [symbol自定义的约束的名称]] PRIMARY KEY [index_type] (index_col_name,…)<br>ALTER TABLE tb_1 ADD PRIMARY KEY(id);<br>添加唯一约束(可以添加多个)<br>ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [index_type] (index_col_name,…)<br>ALTER TABLE tb_1 ADD UNIQUE (username);<br>添加外键约束<br>ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_type] (index_col_name,…)<br>reference_definition<br>例:ALTER TABLE t3 ADD FOREIGN KEY (age)REFERENCES t2(age);<br>添加/删除默认约束<br>ALTER TABLE tbl_name ALTER [COLUMN] col_name SET DAFAULT literal(比如age里面可设置为10,20 |DROP DEFAULT<br>例:ALTER TABLE user2 ALTER age SET DEFAULT 15;<br>ALTER TABLE user2 ALTER age DROP DEFAULT;</p><p>查索引是SHOW INDEX<br>查约束是SHOW INDEXES<br>约束和索引, 前者是用来检查数据的正确性,后者用来实现数据查询的优化,目的不同。<br>唯一性约束与唯一索引有所不同:<br>(1).创建唯一约束会在Oracle中创建一个Constraint,同时也会创建一个该约束对应的唯一索引。<br>(2).创建唯一索引只会创建一个唯一索引,不会创建Constraint。<br>也就是说其实唯一约束是通过创建唯一索引来实现的。<br>在删除时这两者也有一定的区别:<br>删除唯一约束时可以只删除约束而不删除对应的索引,所以对应的列还是必须唯一的,<br>而删除了唯一索引的话就可以插入不唯一的值。<br>删除唯一约束:ALTER TABLE table_name DROP INDEX 数据名;<br>PRIMARY KEY 和 KEY 的区别:<br>主键一定是唯一性索引,唯一性索引并不一定就是主键<br>一个表中可以有多个唯一性索引,但只能有一个主键<br>主键列不允许空值,而唯一性索引列允许空值<br>删除主键约束:alter table user2 drop primary key;<br>不用选择字段 因为一张表有也只有一个主键。<br>删除外键约束:alter table 数据表名 drop foreign key user_ibfk_1;<br>在删除之前要先找到外键名 需用show create table 数据表名;来查看</p><p>1.修改列定义<br>用关键字ALTER TABLE..MODIFY<br>ALTER TABLE tbl_name MODIFY [COLUMN] col_name column_definition [FIRST |AFTER col_name];<br>ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; //将id字段的位置提到第一列<br>SHOW COLUMNS FROM users2;<br>ALTER TABLE users2 MODIFY id TINYINT UNSIGNED NOT NULL; //修改数据类型,需注意数据丢失的问题</p><p>2.修改列名称,用CHANGE方法可以同时修改列名称和列定义.<br>用关键字ALTER..CHANGE<br>ALTER TABLE tbl_name CHANGE [COLUMN] col_name new_col_name column_definition [FIRST|AFTER col_name];<br>ALTER TABLE users2 CHANGE pid p_id TINYINT UNSIGNED; //修改列名称</p><p>3.更换数据表名<br>用关键字ALTER..RENAME<br>修改一个表的表名(方法1)<br>ALTER TABLE users2 RENAME person;<br>修改一个表的表名(方法2)<br>用关键字RENAME..TO<br>RENAME TABLE users5 TO users2;<br>一次修改多个表的表名,操作间用逗号隔开.<br>RENAME TABLE users5 TO users2,users3 TO users4;<br>应该少使用数据表的列名及表名的更名。</p><ol><li>创建表:<br>create table user(<pre><code>id smallint primary key not null auto_increment,name varchar(20),age smallint</code></pre>);</li><li>show create table user; 查看创建表信息<br>show tables; 显示当前数据库所有的表<br>show columns from user; 显示列属性 或 discribe user;<br>show indexes from user \G; 显示所有的索引,“\G” 表示按列显示</li><li>drop table user1; 删除表</li><li>表添加一列: alter table user add age tinyint<br>表删除一列: alter table user drop age;</li><li>添加主键约束:alter table user2 add primary key (id);<br>删除主键约束:alter table user2 drop primary key;<br>添加唯一约束: alter table user2 add unique key uni_key (name);<br>删除唯一约束: drop index uni_key on user2;<br>添加外键约束:alter table user2 add foreign key (age) references user(id);<br>添加默认约束:alter table user2 alter age set default 20;<br>删除默认约束:alter table user2 alter age drop default;<br>修改列属性:alter table user2 modify name varchar(30);<br>修改列名:alter table user2 change age age1 tinyint not null;<br>修改表名:alter tabler user2 rename user3 或者 rename table user3 to user2;<br>注:尽量不要修改列名和表名</li></ol><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="MySQL基本使用"><a href="#MySQL基本使用" class="headerlink" title="MySQL基本使用"></a>MySQL基本使用</h1><h2 id="修改MySQL提示符"><a href="#修改MySQL提示符" class="headerlink" title="修改MySQL提示符"></a>修改MySQL提示符</h2><p><strong>修改提示符的两种方式:</strong></p>
<ol>
<li>连接客户端时通过参数指定:<code>shell&gt;mysql -uroot -proot --prompt</code> 提示符</li>
<li>连接上客户端后,通过<code>prompt</code>修改:<code>mysql&gt;prompt</code> 提示符</li>
</ol>
<p><strong>修改参数:</strong></p>
<p><code>\D</code> 完整日期<br><code>\d</code> 数据库<br>还可以搭配一起<code>+</code>符号<br><code>\h</code> 服务器<br><code>\u</code> 用户</p>
</summary>
<category term="数据库" scheme="https://www.awebone.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
<category term="MySQL" scheme="https://www.awebone.com/tags/MySQL/"/>
</entry>
<entry>
<title>使用JavaScript实现焦点轮播图</title>
<link href="https://www.awebone.com/posts/7a7093e6/"/>
<id>https://www.awebone.com/posts/7a7093e6/</id>
<published>2017-12-28T16:00:00.000Z</published>
<updated>2020-07-18T08:18:02.132Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h1><p>各大网站都使用焦点轮播图来展示自己的图片,如淘宝、京东等。</p><ol><li>焦点轮播图所用技能点:DOM操作、定时器、事件运用、JS动画、函数递归、无限滚动;</li><li>无限滚动实现:包含图片的父级标签要有一个属性<code>overflow:hidden</code> 来隐藏超出自身尺寸的内容;有<code>style:left</code>通过控制left值来实现滚动; 图片列表中要在开始和结束位置添加两张相同的附属图,使图片实现无缝连接。</li></ol><a id="more"></a><p><br></p><h1 id="使用html和css实现静态页面布局"><a href="#使用html和css实现静态页面布局" class="headerlink" title="使用html和css实现静态页面布局"></a>使用html和css实现静态页面布局</h1><ol><li>父容器要承载图片、圆点下标、左右切换箭头,要让超出部分隐藏<code>overflow:hidden</code>、定位为<code>position:relative</code>;</li><li>图片的div要添加定位:<code>position:absolute</code>让它基于父容器relative,<code>z-index:1</code>使图片堆叠在第一层上;</li><li>圆点下标和左右切换箭头设置<code>z-index:2</code>,<code>position:absolute</code>,让其覆盖在图片上;</li><li>左右切换箭头在初始状态下设置为隐藏<code>display:none</code>,鼠标移上图片时使其显示<code>display:block</code>,鼠标移到箭头上时改变透明度RGBA,使箭头颜色加深;</li></ol><p><strong>HTML代码</strong></p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="meta"><!DOCTYPE html></span></div><div class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></div><div class="line"><span class="tag"><<span class="name">head</span>></span></div><div class="line"><span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></div><div class="line"><span class="tag"><<span class="name">title</span>></span>焦点轮播图<span class="tag"></<span class="name">title</span>></span></div><div class="line"><span class="tag"><<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">type</span>=<span class="string">"text/css"</span> <span class="attr">href</span>=<span class="string">"css/焦点轮播图.css"</span>></span></div><div class="line"><span class="tag"></<span class="name">head</span>></span></div><div class="line"><span class="tag"><<span class="name">body</span>></span></div><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"container"</span>></span></div><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"list"</span> <span class="attr">style</span>=<span class="string">"left: -600px"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/5.jpg"</span> <span class="attr">alt</span>=<span class="string">"5"</span>></span> <span class="comment"><!-- 附属图实现无缝的滚动 --></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/1.jpg"</span> <span class="attr">alt</span>=<span class="string">"1"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/2.jpg"</span> <span class="attr">alt</span>=<span class="string">"2"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/3.jpg"</span> <span class="attr">alt</span>=<span class="string">"3"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/4.jpg"</span> <span class="attr">alt</span>=<span class="string">"4"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/5.jpg"</span> <span class="attr">alt</span>=<span class="string">"5"</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"images/1.jpg"</span> <span class="attr">alt</span>=<span class="string">"5"</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"buttons"</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span> <span class="attr">index</span>=<span class="string">"1"</span> <span class="attr">class</span>=<span class="string">"on"</span>></span><span class="tag"></<span class="name">span</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span> <span class="attr">index</span>=<span class="string">"2"</span>></span><span class="tag"></<span class="name">span</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span> <span class="attr">index</span>=<span class="string">"3"</span>></span><span class="tag"></<span class="name">span</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span> <span class="attr">index</span>=<span class="string">"4"</span>></span><span class="tag"></<span class="name">span</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span> <span class="attr">index</span>=<span class="string">"5"</span>></span><span class="tag"></<span class="name">span</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"javascript:;"</span> <span class="attr">id</span>=<span class="string">"prev"</span> <span class="attr">class</span>=<span class="string">"arrow"</span>></span>&lt;<span class="tag"></<span class="name">a</span>></span></div><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"javascript:;"</span> <span class="attr">id</span>=<span class="string">"next"</span> <span class="attr">class</span>=<span class="string">"arrow"</span>></span>&gt;<span class="tag"></<span class="name">a</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"js/焦点轮播图.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></div><div class="line"><span class="tag"></<span class="name">body</span>></span></div><div class="line"><span class="tag"></<span class="name">html</span>></span></div></pre></td></tr></tbody></table></figure><p><strong>CSS代码</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div></pre></td><td class="code"><pre><div class="line">*{</div><div class="line"><span class="attribute">margin</span>: <span class="number">0</span>;</div><div class="line"><span class="attribute">padding</span>: <span class="number">0</span>;</div><div class="line"><span class="attribute">text-decoration </span>:none;</div><div class="line">}</div><div class="line"><span class="selector-tag">body</span>{</div><div class="line"><span class="attribute">padding</span>: <span class="number">20px</span>;</div><div class="line">}</div><div class="line"><span class="selector-id">#container</span>{</div><div class="line"><span class="attribute">width</span>: <span class="number">600px</span>;</div><div class="line"><span class="attribute">height</span>: <span class="number">400px</span>;</div><div class="line"><span class="attribute">position</span>: relative;</div><div class="line"><span class="attribute">border</span>: <span class="number">3px</span> solid <span class="number">#333</span>;</div><div class="line"><span class="attribute">overflow</span>: hidden;</div><div class="line">}</div><div class="line"><span class="selector-id">#list</span>{</div><div class="line"><span class="attribute">height</span>: <span class="number">400px</span>;</div><div class="line"><span class="attribute">width</span>: <span class="number">4200px</span>;</div><div class="line"><span class="attribute">position</span>: absolute;</div><div class="line"><span class="attribute">z-index</span>: <span class="number">1</span>; <span class="comment">/*设置元素的堆叠顺序*/</span></div><div class="line">}</div><div class="line"><span class="selector-id">#list</span> <span class="selector-tag">img</span>{</div><div class="line"><span class="attribute">float</span>: left;</div><div class="line">}</div><div class="line"><span class="selector-id">#buttons</span>{</div><div class="line"><span class="attribute">height</span>: <span class="number">10px</span>;</div><div class="line"><span class="attribute">width</span>: <span class="number">100px</span>;</div><div class="line"><span class="attribute">z-index</span>: <span class="number">2</span>;</div><div class="line"><span class="attribute">bottom</span>: <span class="number">20px</span>;</div><div class="line"><span class="attribute">left</span>: <span class="number">250px</span>;</div><div class="line"><span class="attribute">position</span>: absolute;</div><div class="line">}</div><div class="line"><span class="selector-id">#buttons</span> <span class="selector-tag">span</span> {</div><div class="line"><span class="attribute">cursor</span>: pointer; <span class="comment">/*规定要显示的光标的类型(手指)*/</span></div><div class="line"><span class="attribute">float</span>: left;</div><div class="line"><span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#fff</span>;</div><div class="line"><span class="attribute">width</span>: <span class="number">10px</span>;</div><div class="line"><span class="attribute">height</span>: <span class="number">10px</span>;</div><div class="line"><span class="attribute">border-radius</span>: <span class="number">50%</span>;</div><div class="line"><span class="attribute">background</span>: <span class="number">#333</span>;</div><div class="line"><span class="attribute">margin-right</span>: <span class="number">5px</span>;</div><div class="line">}</div><div class="line"><span class="selector-id">#buttons</span> <span class="selector-class">.on</span> { </div><div class="line"><span class="attribute">background</span>: orangered;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.arrow</span> {</div><div class="line"><span class="attribute">cursor</span>: pointer;</div><div class="line"><span class="attribute">display</span>: none; <span class="comment">/*箭头隐藏*/</span></div><div class="line"><span class="attribute">line-height</span>: <span class="number">39px</span>;</div><div class="line"><span class="attribute">text-align</span>: center;</div><div class="line"><span class="attribute">font-size</span>: <span class="number">36px</span>;</div><div class="line"><span class="attribute">font-weight</span>: bold;</div><div class="line"><span class="attribute">width</span>: <span class="number">40px</span>; <span class="attribute">height</span>: <span class="number">40px</span>; </div><div class="line"><span class="attribute">position</span>: absolute;</div><div class="line"><span class="attribute">z-index</span>: <span class="number">2</span>;</div><div class="line"><span class="attribute">top</span>: <span class="number">180px</span>;</div><div class="line"><span class="attribute">background-color</span>: <span class="built_in">RGBA</span>(0,0,0,.3); <span class="comment">/*透明度设置*/</span></div><div class="line"><span class="attribute">color</span>: <span class="number">#fff</span>;</div><div class="line">}</div><div class="line"><span class="selector-class">.arrow</span><span class="selector-pseudo">:hover</span> {</div><div class="line"><span class="attribute">background-color</span>: <span class="built_in">RGBA</span>(0,0,0,.7);</div><div class="line">}</div><div class="line"><span class="selector-id">#container</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.arrow</span> {</div><div class="line"><span class="attribute">display</span>: block; <span class="comment">/*箭头显示*/</span></div><div class="line">}</div><div class="line"><span class="selector-id">#prev</span> {</div><div class="line"><span class="attribute">left</span>: <span class="number">20px</span>;</div><div class="line">}</div><div class="line"><span class="selector-id">#next</span> {</div><div class="line"><span class="attribute">right</span>: <span class="number">20px</span>;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="JS动画实现"><a href="#JS动画实现" class="headerlink" title="JS动画实现"></a>JS动画实现</h1><p><strong>箭头切换 -> 无限滚动 -> 按钮切换 -> 延迟切换 -> 自动播放</strong></p><ol><li><p><strong>箭头切换</strong></p><ul><li>整个页面加载<code>window.onload</code>,获取元素</li><li>通过ID名获取页面中的元素(父容器、承载图片容器、圆点列表、箭头),赋值给一个变量</li><li>添加一个时间绑定,点击箭头时实现图片的切换</li><li>当点击右箭头时,改变left的值,向左移动,要减去一张图的宽度</li><li>获取图片容器的值,<code>list.style.left</code> = 自身的值再减去一张图片的宽度<br><strong>注意要把等号后面字符串使用<code>parseInt</code>函数转换为数字才可以进行减法,减去的图片宽度要加px单位</strong></li><li>反方向同理,加上一张图片的宽度</li><li>左右箭头的写法很相似,只是加减不一样,可以封装成一个函数,通过参数的正负值实现加减</li></ul></li></ol><ol><li><p><strong>无限滚动</strong>:弥补左右键切换的空白</p><ul><li>当前面的附属图比第一张大,最后一张附属图比最后一张小的时候,出现这两种情况时让它复位到真正的第一张或第五张图</li><li>判断是否滚到了辅助图上,滚到了让它归位</li><li>把常用的<code>list.style.left</code>,存到一个变量中,方便使用</li><li>添加圆点的切换功能,创建一个变量来承载当前存储的第几张图片/显示第个圆点</li><li>写一个函数,用来显示亮起小圆点的功能<ul><li>圆点是数组,所以创建的变量要减去1才能对应上要显示的圆点,让它亮起来添加class名<br><code><span index="1" class="on"></code></li></ul></li><li>再绑定事件中左箭头index要加一,右箭头要减一,调用圆点函数让它点击时显示,每次点击箭头的时候都要改变index的值,使它对应到正确的图片上,调用showButton亮起对应的圆点</li><li>亮起自己的同时,让其他不亮,使用for循环,去掉所有的class,然后break退出循环,不再继续遍历元素节点</li><li>箭头点击时,当圆点index大于5时,让它归位为1,小于1时,归位为5,不到5时加1</li></ul></li></ol><ol><li><p><strong>圆点按钮切换</strong></p><ul><li><p>通过for循环遍历圆点,添加点击事件</p></li><li><p>点击按钮时,取到index值,就可以知道当前点击的是第几个按钮,要显示第几张图片</p></li><li><p>通过DOM2级方法<code>getAttribute()</code>获取到自定义(或自带)属性,为了计算再转换为数字<code>var myIndex = parseInt(this.getAttribute('index'));</code></p></li><li><p>通过新的值减去旧的值获取偏移量<code>var offset = -600 * (myIndex - index);</code></p></li><li><p>写一个判断,当这张图片是打开状态的,就什么都不做,用class=on来判断是否打开,return跳出,后面的代码不会再执行</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (animated) {</div><div class="line"><span class="keyword">return</span>;</div><div class="line">}</div><div class="line"><span class="keyword">if</span> (<span class="keyword">this</span>.className == <span class="string">'on'</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line">}</div></pre></td></tr></tbody></table></figure></li></ul></li></ol><ol><li><p><strong>动画函数</strong></p><ul><li>图片在一定时间内进行位移,要判断是否达到目标值,没有达到还要继续做位移</li><li>声明一个变量用offset总共的偏移量除以次数(位移总时间time除以位移间隔时间inteval),求出每次移动多少<code>var speed = offset / (time / inteval);</code></li><li>判断speed小于0并且left值是否大于目标值newLeft或speed大于0并且left值小于目标值,这两种情况让它做位移<code>speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left</code></li><li>在判断中放入定时器setTimeout<br>一个函数不停的在一定的条件之后调用自身这种做法叫做递归</li></ul></li></ol><ul><li>优化:声明一个变量,作为动画是否在运行的依据,开始状态为false表示没有运行<code>var animated = false; //优化</code></li></ul><ol><li><p><strong>自动播放</strong></p><ul><li>鼠标移开时自动播放,鼠标移上去时停止,通过定时器<code>setTimeout</code>和<code>clearTimeout</code>来实现的</li><li>设置定时器,让它隔几秒切换一次,相当于3秒钟调一次<code>next.onclick</code>(右箭头)事件</li><li>自动切换需要写两个函数来控制自动切换,声明一个变量来存放定时器不给任何值</li><li>鼠标移开时定时器执行,移上时清除定时器执行,要给整个容器加一个鼠标移入移开事件</li><li>鼠标不做任何事情时让它自动播放,调用函数</li></ul></li></ol><p><strong>代码如下</strong></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">window</span>.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> container = <span class="built_in">document</span>.getElementById(<span class="string">'container'</span>);</div><div class="line"> <span class="keyword">var</span> list = <span class="built_in">document</span>.getElementById(<span class="string">'list'</span>);</div><div class="line"> <span class="keyword">var</span> buttons = <span class="built_in">document</span>.getElementById(<span class="string">'buttons'</span>).getElementsByTagName(<span class="string">'span'</span>);</div><div class="line"> <span class="keyword">var</span> prev = <span class="built_in">document</span>.getElementById(<span class="string">'prev'</span>);</div><div class="line"> <span class="keyword">var</span> next = <span class="built_in">document</span>.getElementById(<span class="string">'next'</span>);</div><div class="line"> <span class="keyword">var</span> index = <span class="number">1</span>; <span class="comment">//索引</span></div><div class="line"> <span class="keyword">var</span> len = <span class="number">5</span>;</div><div class="line"> <span class="keyword">var</span> animated = <span class="literal">false</span>; <span class="comment">//优化</span></div><div class="line"> <span class="keyword">var</span> interval = <span class="number">3000</span>; <span class="comment">//时间间隔</span></div><div class="line"> <span class="keyword">var</span> timer;</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">showButton</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < buttons.length; i++) {</div><div class="line"> <span class="keyword">if</span> (buttons[i].className == <span class="string">'on'</span>) {</div><div class="line"> buttons[i].className = <span class="string">''</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> buttons[index - <span class="number">1</span>].className = <span class="string">'on'</span>;</div><div class="line"> } <span class="comment">//按钮切换</span></div><div class="line"></div><div class="line"> next.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">if</span> (animated) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (index == <span class="number">5</span>) {</div><div class="line"> index = <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> index += <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> animate(<span class="number">-600</span>);</div><div class="line"> showButton();</div><div class="line"> }<span class="comment">//右切换</span></div><div class="line"> prev.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">if</span> (animated) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (index == <span class="number">1</span>) {</div><div class="line"> index = <span class="number">5</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> index -= <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> animate(<span class="number">600</span>);</div><div class="line"> showButton();</div><div class="line"> }<span class="comment">//左切换</span></div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">play</span>(<span class="params"></span>) </span>{</div><div class="line"> timer = setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> next.onclick();</div><div class="line"> play();</div><div class="line"> }, interval);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">stop</span>(<span class="params"></span>) </span>{</div><div class="line"> clearTimeout(timer);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < buttons.length; i++) {</div><div class="line"> buttons[i].onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">if</span> (animated) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.className == <span class="string">'on'</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">var</span> myIndex = <span class="built_in">parseInt</span>(<span class="keyword">this</span>.getAttribute(<span class="string">'index'</span>));</div><div class="line"> <span class="keyword">var</span> offset = <span class="number">-600</span> * (myIndex - index);</div><div class="line"> animate(offset);</div><div class="line"> index = myIndex;</div><div class="line"> showButton();</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">animate</span>(<span class="params">offset</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (offset == <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> animated = <span class="literal">true</span>;</div><div class="line"> <span class="keyword">var</span> time = <span class="number">300</span>; <span class="comment">//时间</span></div><div class="line"> <span class="keyword">var</span> inteval = <span class="number">10</span>; <span class="comment">//时间间隔</span></div><div class="line"> <span class="keyword">var</span> speed = offset / (time / inteval); <span class="comment">//速度</span></div><div class="line"> <span class="keyword">var</span> left = <span class="built_in">parseInt</span>(list.style.left) + offset; <span class="comment">//改变值来实现滚动</span></div><div class="line"></div><div class="line"> <span class="keyword">var</span> go = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">if</span> ((speed > <span class="number">0</span> && <span class="built_in">parseInt</span>(list.style.left) < left) || (speed < <span class="number">0</span> && <span class="built_in">parseInt</span>(list.style.left) > left)) {</div><div class="line"> list.style.left = <span class="built_in">parseInt</span>(list.style.left) + speed + <span class="string">'px'</span>;</div><div class="line"> setTimeout(go, inteval);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> list.style.left = left + <span class="string">'px'</span>;</div><div class="line"> <span class="keyword">if</span> (left > <span class="number">-200</span>) {</div><div class="line"> list.style.left = <span class="number">-600</span> * len + <span class="string">'px'</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> (left < (<span class="number">-600</span> * len)) {</div><div class="line"> list.style.left = <span class="string">'-600px'</span>;</div><div class="line"> }</div><div class="line"> animated = <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> } <span class="comment">//自动滚动</span></div><div class="line"> go();</div><div class="line"> }</div><div class="line"></div><div class="line"> container.onmouseover = stop();</div><div class="line"> container.onmouseout = play();</div><div class="line"></div><div class="line"> play();</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>焦点轮播图的实现需要耐心分析原理,掌握焦点轮播图所需的技能点,从而通过代码实现。</p><p>先写出静态页面html+css,注意属性值的设置。再用js一步一步写出箭头切换、按钮切换的函数,学会设置和清除定时器、递归调用函数,实现自动滚动播放。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h1><p>各大网站都使用焦点轮播图来展示自己的图片,如淘宝、京东等。</p>
<ol>
<li>焦点轮播图所用技能点:DOM操作、定时器、事件运用、JS动画、函数递归、无限滚动;</li>
<li>无限滚动实现:包含图片的父级标签要有一个属性<code>overflow:hidden</code> 来隐藏超出自身尺寸的内容;有<code>style:left</code>通过控制left值来实现滚动; 图片列表中要在开始和结束位置添加两张相同的附属图,使图片实现无缝连接。</li>
</ol>
</summary>
<category term="前端" scheme="https://www.awebone.com/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>HTML5音频解析与可视化</title>
<link href="https://www.awebone.com/posts/fd5cbc55/"/>
<id>https://www.awebone.com/posts/fd5cbc55/</id>
<published>2017-10-24T16:00:00.000Z</published>
<updated>2020-03-21T06:54:19.249Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="HTML5音频解析与可视化"><a href="#HTML5音频解析与可视化" class="headerlink" title="HTML5音频解析与可视化"></a>HTML5音频解析与可视化</h1><h2 id="基本结构"><a href="#基本结构" class="headerlink" title="基本结构"></a>基本结构</h2><p>使用express 框架搭建后台基本结构</p><a id="more"></a><h2 id="加载音乐并用ajax请求资源"><a href="#加载音乐并用ajax请求资源" class="headerlink" title="加载音乐并用ajax请求资源"></a>加载音乐并用ajax请求资源</h2><p><strong>加载音乐文件:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> lis = $(<span class="string">"#list li"</span>);</div><div class="line"></div><div class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < list.length; i++) {</div><div class="line"> lis[i].onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = <span class="number">0</span>; j < lis.length; j++) {</div><div class="line"> lis[j].className = <span class="string">""</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">this</span>.className = <span class="string">"selected"</span>;</div><div class="line"> load(<span class="string">"/media/"</span> + <span class="keyword">this</span>.title);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>ajax加载资源</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</div><div class="line">xhr.abort();</div><div class="line">xhr.open(<span class="string">"GET"</span>, url);</div><div class="line">xhr.responseType = <span class="string">"arraybuffer"</span>;</div><div class="line">xhr.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{};</div><div class="line">xhr.send();</div></pre></td></tr></tbody></table></figure><h2 id="Web-Audio-Api-关系图"><a href="#Web-Audio-Api-关系图" class="headerlink" title="Web Audio Api 关系图"></a>Web Audio Api 关系图</h2><p><img src="/images/h5-audio/1.webAudio-API.jpg" alt="1.webAudio-API"></p><h2 id="使用AudioContext解码"><a href="#使用AudioContext解码" class="headerlink" title="使用AudioContext解码"></a>使用AudioContext解码</h2><p><img src="/images/h5-audio/2.AudioContext.jpg" alt="2.AudioContext"></p><p><strong>实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> ac = <span class="keyword">new</span>(<span class="built_in">window</span>.AudioContext || <span class="built_in">window</span>.webkitAudioContext)();</div><div class="line">ac.decodeAudioData(xhr.response, <span class="function"><span class="keyword">function</span>(<span class="params">buffer</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (n != count) <span class="keyword">return</span>;</div><div class="line"> <span class="keyword">var</span> bufferSource = ac.createBufferSource();</div><div class="line"> bufferSource.buffer = buffer;</div><div class="line"> bufferSource.connect(gainNode);</div><div class="line"> <span class="comment">//bufferSource.connect(ac.destination);</span></div><div class="line"> bufferSource[bufferSource.start ? <span class="string">"start"</span> : <span class="string">"noteOn"</span>](<span class="number">0</span>);</div><div class="line"> suurce = bufferSource;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="使用gainNode调节音量"><a href="#使用gainNode调节音量" class="headerlink" title="使用gainNode调节音量"></a>使用gainNode调节音量</h2><p><img src="/images/h5-audio/3.GainNode.jpg" alt="3.GainNode"></p><p><strong>实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> gainNode = ac[ac.createGain ? <span class="string">"createGain"</span> : <span class="string">"createGainNode"</span>]();</div><div class="line">gainNode.connect(ac.destination);</div></pre></td></tr></tbody></table></figure><h2 id="bufferSource连接gainNode"><a href="#bufferSource连接gainNode" class="headerlink" title="bufferSource连接gainNode"></a>bufferSource连接gainNode</h2><p><img src="/images/h5-audio/4.AudioBufferSourceNode.jpg" alt="4.AudioBufferSourceNode"></p><p><strong>实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">bufferSource.connect(gainNode);</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">changeVolume</span>(<span class="params">percent</span>) </span>{</div><div class="line"> gainNode.gain.value = percent * percent;</div><div class="line">}</div><div class="line"></div><div class="line">$(<span class="string">"#volume"</span>)[<span class="number">0</span>].onchange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> changeVolume(<span class="keyword">this</span>.value / <span class="keyword">this</span>.max);</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="音乐播放逻辑问题"><a href="#音乐播放逻辑问题" class="headerlink" title="音乐播放逻辑问题"></a>音乐播放逻辑问题</h2><p><strong>实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//音乐资源加载</span></div><div class="line"><span class="keyword">var</span> source = <span class="literal">null</span>;</div><div class="line"></div><div class="line"><span class="comment">//计数器</span></div><div class="line"><span class="keyword">var</span> count = <span class="number">0</span>;</div><div class="line"></div><div class="line"><span class="keyword">var</span> n = ++count;</div><div class="line"></div><div class="line">source && source[source.stop ? <span class="string">"stop"</span> : <span class="string">"noteOff"</span>](); <span class="comment">//默认为0</span></div><div class="line"></div><div class="line"><span class="keyword">if</span> (n != count) <span class="keyword">return</span>;</div></pre></td></tr></tbody></table></figure><h2 id="分析音频资源"><a href="#分析音频资源" class="headerlink" title="分析音频资源"></a>分析音频资源</h2><blockquote><p><a href="https://www.imooc.com/video/6028" target="_blank" rel="external">参考链接</a></p></blockquote><p><img src="/images/h5-audio/5.AnalyserNode.jpg" alt="5.AnalyserNode"></p><p><strong>实现:</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> analyser=ac.createAnalyser();</div><div class="line">analyser.fftSize=<span class="number">512</span>;</div><div class="line">analyser.connect(gainNode);</div><div class="line"></div><div class="line"><span class="comment">//bufferSource连接analyser</span></div><div class="line">bufferSource.connect(analyser);</div></pre></td></tr></tbody></table></figure><p><strong>时时分析</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">visualizer</span>(<span class="params"></span>)</span>{</div><div class="line"><span class="keyword">var</span> arr=<span class="keyword">new</span> <span class="built_in">Uint8Array</span>(analyser.frequencyBinCount);</div><div class="line"> requestAnimationFrame=<span class="built_in">window</span>.requestAnimationFrame||<span class="built_in">window</span>.webkitRequestAnimationFrame||<span class="built_in">window</span>.mozRequestAnimationFrame;</div><div class="line"> </div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">v</span>(<span class="params"></span>)</span>{</div><div class="line"> analyser.getByteFrequencyData(arr);</div><div class="line"> }</div><div class="line"> requestAnimationFrame(v);</div><div class="line">}</div><div class="line"></div><div class="line">visualizer();</div></pre></td></tr></tbody></table></figure><h2 id="音乐数据可视化"><a href="#音乐数据可视化" class="headerlink" title="音乐数据可视化"></a>音乐数据可视化</h2><p><strong>使用canvas画图进行可视化</strong></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//canvas画图(柱状)</span></div><div class="line"><span class="keyword">var</span> box = $(<span class="string">"#box"</span>)[<span class="number">0</span>];</div><div class="line"><span class="keyword">var</span> height, width;</div><div class="line"><span class="keyword">var</span> canvas = <span class="built_in">document</span>.createElement(<span class="string">"canvas"</span>);</div><div class="line"><span class="keyword">var</span> ctx = canvas.getContext(<span class="string">"2d"</span>);</div><div class="line">box.appendChild(canvas);</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">resize</span>(<span class="params"></span>) </span>{</div><div class="line"> height = box.clientHeight;</div><div class="line"> width = box.clientWidth;</div><div class="line"> canvas.height = height;</div><div class="line"> canvas.width = width;</div><div class="line"> <span class="keyword">var</span> line = ctx.createLinearGradient(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, height);</div><div class="line"> line.addColorStop(<span class="number">0</span>, <span class="string">"red"</span>);</div><div class="line"> line.addColorStop(<span class="number">0.5</span>, <span class="string">"yello"</span>);</div><div class="line"> line.addColorStop(<span class="number">1</span>, <span class="string">"green"</span>);</div><div class="line"> ctx.fillstyle = line;</div><div class="line">}</div><div class="line">resize();</div><div class="line"><span class="built_in">window</span>.onresize = resize;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">draw</span>(<span class="params">arr</span>) </span>{</div><div class="line">ctx.clearRect(<span class="number">0</span>,<span class="number">0</span>,width,height);</div><div class="line"> <span class="keyword">var</span> w = width / size;</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < size; i++) {</div><div class="line"> <span class="keyword">var</span> h = arr[i] / <span class="number">256</span> * height;</div><div class="line"> ctx.fillRect(w * i, height - h, w * <span class="number">0.6</span>, h);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="HTML5音频解析与可视化"><a href="#HTML5音频解析与可视化" class="headerlink" title="HTML5音频解析与可视化"></a>HTML5音频解析与可视化</h1><h2 id="基本结构"><a href="#基本结构" class="headerlink" title="基本结构"></a>基本结构</h2><p>使用express 框架搭建后台基本结构</p>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="HTML5" scheme="https://www.awebone.com/tags/HTML5/"/>
</entry>
<entry>
<title>Mac转Windows的拯救指南</title>
<link href="https://www.awebone.com/posts/143a0a72/"/>
<id>https://www.awebone.com/posts/143a0a72/</id>
<published>2017-10-12T16:00:00.000Z</published>
<updated>2020-03-14T08:20:17.900Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Mac转Windows的拯救指南"><a href="#Mac转Windows的拯救指南" class="headerlink" title="Mac转Windows的拯救指南"></a>Mac转Windows的拯救指南</h1><blockquote><p>假期使用Mac开发,目前转Windows开发学习,体会了Mac上高效率的快捷键之后,感觉用鼠标点来点去很麻烦,将一些小工具使用,来提高效率。这只是给新手介绍,大神请绕过。</p></blockquote><p>下面开始介绍一些工具来拯救Mac党</p><h3 id="1-Chocolatey"><a href="#1-Chocolatey" class="headerlink" title="1.Chocolatey"></a>1.Chocolatey</h3><p><a href="https://chocolatey.org/" target="_blank" rel="external">Chocolatey</a>是一个Windows上的包管理器,类似于linux上的yum和 apt-get。 你可以在其官方网站上查看具体的使用说明。一般的安装步骤应该是下面这样:</p><p><strong>CMD</strong></p><figure class="highlight cmd"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object <span class="built_in">net</span>.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && <span class="built_in">SET</span> <span class="built_in">PATH</span>=<span class="variable">%PATH%</span>;<span class="variable">%ALLUSERSPROFILE%</span>\chocolatey\bin</div></pre></td></tr></tbody></table></figure><p><strong>Powershell</strong></p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Set-ExecutionPolicy</span> Bypass; iex ((<span class="built_in">New-Object</span> System.Net.WebClient).DownloadString(<span class="string">'https://chocolatey.org/install.ps1'</span>))</div></pre></td></tr></tbody></table></figure><p>一般来说,使用Chocolatey来安装软件的时候,需要以管理员的身份来运行命令提示符窗口。chocolatey的网站可能在国内访问困难,导致上述安装命令无法正常完成。请使用科学上网。</p><a id="more"></a><h3 id="2-Cmder-or-Powershell-or-Git"><a href="#2-Cmder-or-Powershell-or-Git" class="headerlink" title="2.Cmder or Powershell or Git"></a>2.Cmder or Powershell or Git</h3><p><a href="http://cmder.net/" target="_blank" rel="external">Cmder</a>是一个替代原机自带cmd的命令行,可以配置,有快捷键,常用的Tab补全,集成Git等。</p><p><a href="https://docs.microsoft.com/en-us/powershell/" target="_blank" rel="external">Powershell</a>是微软公司开发的任务自动化和管理框架。功能强大,背后还有牛逼的老爹支持,命令与cmd有所不同,老司机可以玩玩。</p><p><a href="https://git-scm.com/" target="_blank" rel="external">Git</a>是一个自由开源的版本控制工具,它在Windows下有相应的命令行工具,命令与linux命令相同,学习了linux,可以很快上手,对于前端来说,这个我觉得是比较方便的,但是,有时候也会抽风。</p><h3 id="3-Listary-or-Wox"><a href="#3-Listary-or-Wox" class="headerlink" title="3.Listary or Wox"></a>3.Listary or Wox</h3><p><a href="http://www.listary.com/" target="_blank" rel="external">Listary</a>是一个文件浏览增强工具。和Mac下的Alfred工具差不多,个人使用free版本即可,自定义快捷键,笔记本可以脱离鼠标,直接使用键盘和触摸板。</p><p><a href="http://www.getwox.com/" target="_blank" rel="external">Wox</a>是一个有效的搜索工具。</p><ul><li>可以文件和应用搜索</li><li>有插件支持</li><li>主题修改</li><li>web快捷键快速查找,自定义搜索引擎</li></ul><h3 id="4-Total-Commander"><a href="#4-Total-Commander" class="headerlink" title="4.Total Commander"></a>4.Total Commander</h3><p><a href="https://www.ghisler.com/" target="_blank" rel="external">Total Commander</a>是一款应用于 Windows 平台的文件管理器 ,它包含两个并排的窗口,这种设计可以让用户方便地对不同位置的“文件或文件夹”进行操作,例如复制、移动、删除、比较等,相对 Windows 资源管理器而言方便很多,极大地提高了文件操作的效率,被广大软件爱好者亲切地简称为:TC 。</p><p>它拥有文件快速预览、快速搜索、多标签、文件比较、批量重命名、FTP 客户端等诸多实用的功能,并可通过大量的插件进行个性化配置。</p><p>官网介绍不是很详细,可查看维基百科的介绍,<a href="https://zh.wikipedia.org/wiki/Total_Commander" target="_blank" rel="external">TC</a>。</p><h3 id="5-FastStone-Screen-Capture-or-Snipaste"><a href="#5-FastStone-Screen-Capture-or-Snipaste" class="headerlink" title="5.FastStone Screen Capture or Snipaste"></a>5.FastStone Screen Capture or Snipaste</h3><p><a href="http://www.faststone.org/FSCaptureDetail.htm" target="_blank" rel="external">FastStone Screen Capture</a>是一个轻量的截屏工具,很老但是很强大。</p><p><a href="https://zh.snipaste.com/" target="_blank" rel="external">Snipaste</a>,免费,免安装,可定制。</p><h3 id="6-NotePad"><a href="#6-NotePad" class="headerlink" title="6.NotePad++"></a>6.NotePad++</h3><p><a href="https://notepad-plus-plus.org/download/" target="_blank" rel="external">NotePad++</a>,替代记事本的轻量级记事本,原本的记事本会有很多弊病,编码格式不是UTF-8。NotePad++解决了这些麻烦,还可以自定义设置,完全变成编辑器,有提示。</p><h3 id="7-Xshell"><a href="#7-Xshell" class="headerlink" title="7.Xshell"></a>7.Xshell</h3><p><a href="">Xshell</a>是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以在Windows界面下用来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="Mac转Windows的拯救指南"><a href="#Mac转Windows的拯救指南" class="headerlink" title="Mac转Windows的拯救指南"></a>Mac转Windows的拯救指南</h1><blockquote>
<p>假期使用Mac开发,目前转Windows开发学习,体会了Mac上高效率的快捷键之后,感觉用鼠标点来点去很麻烦,将一些小工具使用,来提高效率。这只是给新手介绍,大神请绕过。</p>
</blockquote>
<p>下面开始介绍一些工具来拯救Mac党</p>
<h3 id="1-Chocolatey"><a href="#1-Chocolatey" class="headerlink" title="1.Chocolatey"></a>1.Chocolatey</h3><p><a href="https://chocolatey.org/">Chocolatey</a>是一个Windows上的包管理器,类似于linux上的yum和 apt-get。 你可以在其官方网站上查看具体的使用说明。一般的安装步骤应该是下面这样:</p>
<p><strong>CMD</strong></p>
<figure class="highlight cmd"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object <span class="built_in">net</span>.webclient).DownloadString('https://chocolatey.org/install.ps1'))" &amp;&amp; <span class="built_in">SET</span> <span class="built_in">PATH</span>=<span class="variable">%PATH%</span>;<span class="variable">%ALLUSERSPROFILE%</span>\chocolatey\bin</div></pre></td></tr></tbody></table></figure>
<p><strong>Powershell</strong></p>
<figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Set-ExecutionPolicy</span> Bypass; iex ((<span class="built_in">New-Object</span> System.Net.WebClient).DownloadString(<span class="string">'https://chocolatey.org/install.ps1'</span>))</div></pre></td></tr></tbody></table></figure>
<p>一般来说,使用Chocolatey来安装软件的时候,需要以管理员的身份来运行命令提示符窗口。chocolatey的网站可能在国内访问困难,导致上述安装命令无法正常完成。请使用科学上网。</p>
</summary>
<category term="工具" scheme="https://www.awebone.com/categories/%E5%B7%A5%E5%85%B7/"/>
<category term="Mac" scheme="https://www.awebone.com/tags/Mac/"/>
<category term="Windons" scheme="https://www.awebone.com/tags/Windons/"/>
</entry>
<entry>
<title>MapReduce初探</title>
<link href="https://www.awebone.com/posts/e6939326/"/>
<id>https://www.awebone.com/posts/e6939326/</id>
<published>2017-09-13T16:00:00.000Z</published>
<updated>2020-03-14T08:20:17.902Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="MapReduce初探"><a href="#MapReduce初探" class="headerlink" title="MapReduce初探"></a>MapReduce初探</h1><p><strong>MapReduce是一个用于处理海量数据的分布式计算框架</strong></p><p>MapReduce解决的问题:</p><ul><li>数据分布式存储</li><li>作业调度</li><li>容错</li><li>机器间通信</li></ul><a id="more"></a><p>MapReduce存储:HDFS</p><ul><li>系统可靠性</li><li>可扩展性</li><li>并发处理</li></ul><p><img src="/images/mr-learn/HDFS.png" alt="Alt text"></p><p>MapReduce思想:分治</p><ul><li><p>分解</p></li><li><p>求解</p></li><li><p>合并</p></li><li><p>分:map</p><p>把复杂的问题分解为若干简单的任务</p></li><li><p>合:reduce</p></li></ul><h2 id="MapReduce执行流程"><a href="#MapReduce执行流程" class="headerlink" title="MapReduce执行流程"></a>MapReduce执行流程</h2><p><img src="/images/mr-learn/MR1.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR2.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR3.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR4.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR5.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR6.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR7.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR8.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR9.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR10.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR11.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR12.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR13.png" alt="Alt text"></p><p><img src="/images/mr-learn/MR14.png" alt="Alt text"></p><h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2><h3 id="WordCount"><a href="#WordCount" class="headerlink" title="WordCount"></a>WordCount</h3><p><img src="/images/mr-learn/WordCount.png" alt="Alt text"></p><h2 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h2><ul><li>数据统计<ul><li>A/B test的需要,实验和对照统计对比各个指标</li><li>统计广告每天的展示、点击和消费总量</li><li>统计视频在一段时间内展示和点击数量,CTR指标</li></ul></li></ul><ul><li>数据过滤<ul><li>从日志中找到某一个条件数据</li><li>除去非法数据,保留合法数据</li><li>数据格式整理</li></ul></li></ul><ul><li>同类汇聚<ul><li>多份日志中,相同时间点、用户行为日志混合</li><li>类表格文件存储中,相同主键拼接相关的属性</li><li>历史的主数据与新增、修改数据合并</li></ul></li></ul><ul><li>全局排序<ul><li>混合日志按时间排序</li><li>多个字段排序</li><li>数据按名称排序</li></ul></li></ul><ul><li>容错框架<ul><li>易出错的服务,大数值计算</li><li>计算规模经常变化调整的服务</li><li>单进程程序。迅速提升执行计算效率</li></ul></li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="MapReduce初探"><a href="#MapReduce初探" class="headerlink" title="MapReduce初探"></a>MapReduce初探</h1><p><strong>MapReduce是一个用于处理海量数据的分布式计算框架</strong></p>
<p>MapReduce解决的问题:</p>
<ul>
<li>数据分布式存储</li>
<li>作业调度</li>
<li>容错</li>
<li>机器间通信</li>
</ul>
</summary>
<category term="大数据" scheme="https://www.awebone.com/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
<category term="MapReduce" scheme="https://www.awebone.com/tags/MapReduce/"/>
</entry>
<entry>
<title>MongoDB基础学习</title>
<link href="https://www.awebone.com/posts/8c3b0bac/"/>
<id>https://www.awebone.com/posts/8c3b0bac/</id>
<published>2017-06-30T16:00:00.000Z</published>
<updated>2020-07-18T08:28:25.472Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p>MongoDB是一个跨平台,面向文档的数据库,提供高性能,高可用性和易于扩展,总结知识点分享给与我一样刚入门MongoDB的人。</p></blockquote><h1 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h1><ul><li>数据库:数据库是一个集合的物理容器。每个数据库获取其自己设定在文件系统上的文件。一个单一的MongoDB服务器通常有多个数据库</li><li>集合:集合是一组MongoDB的文件。它与一个RDBMS表是等效的。一个集合存在于数据库中。集合不强制执行模式。集合中的文档可以有不同的字段。</li><li><p>文档:文档是一组键值对。文档具有动态模式。动态模式是指,在同一个集合的文件不必具有相同一组集合的文档字段或结构,并且相同的字段可以保持不同类型的数据。</p></li><li><p>文档是MongoDB中数据的基本单元</p></li><li>在MongoDB中,一个MongoDB实例可以承载多个数据库,每个数据库拥有0或多个集合,一个集合拥有多个文档</li><li>在同一个MongoDB服务器上存放多个应用那个程序或用户的数据,需要使用不同的数据库</li><li>使用BSON格式</li></ul><a id="more"></a><p><br></p><h1 id="使用MongoDB在哪些场景"><a href="#使用MongoDB在哪些场景" class="headerlink" title="使用MongoDB在哪些场景"></a>使用MongoDB在哪些场景</h1><ul><li>大而复杂的数据</li><li>移动和社会基础设施数据</li><li>内容管理和交付</li><li>用户数据管理</li><li>数据中心</li></ul><p><br></p><h1 id="初始化的数据库"><a href="#初始化的数据库" class="headerlink" title="初始化的数据库"></a>初始化的数据库</h1><ul><li>admin:root数据库,有数据库所以权限</li><li>local:存储所以本地集合</li><li>config:存储分片信息</li></ul><p><br></p><h1 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h1><ul><li>null:空或不存在</li><li>布尔型:true或false</li><li>数值:默认64位浮点型数值</li><li>字符串:UTF-8</li><li>日期:自新世纪以来经过的毫秒,不存储时区</li><li>正则表达式:与js语法相同</li><li>数组:数据列表或数据集</li><li>内嵌文档:对象嵌套</li><li>对象<ul><li>对象id是一个12字节的ID,是一个由24个十六进制数字组成的字符串,作为文档唯一标识,一秒钟最多允许每个进程拥有2563个不同的ObjectId</li><li>ObjectId前四个字节是从标准纪元开始的时间戳,单位为秒</li><li>接下来3个字节是所在主机的唯一标识符,机器主机名的散列值</li><li>接下来2个字节来自产生ObjectId的进程的进程标识符PID</li><li>最后3个字节是一个自动增加的计数器</li></ul></li><li>二进制数据</li><li>代码</li></ul><p><br></p><h1 id="MongoDB-shell"><a href="#MongoDB-shell" class="headerlink" title="MongoDB shell"></a>MongoDB shell</h1><ul><li><p>启动时会连到test数据库,并将数据库连接赋值给全局变量db</p></li><li><p>连接到不同的数据库或服务器</p></li></ul><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">mongo --nodb</div><div class="line">connect=<span class="keyword">new</span> Mongo(<span class="string">"host:27017"</span>)</div><div class="line">db=connect.getDB(<span class="string">"myDB"</span>)</div></pre></td></tr></tbody></table></figure><ul><li><p>帮助</p><ul><li><code>help</code></li><li><code>db.foo.update</code>,方法不加括号可查看相应函数的源码</li></ul></li><li><p>创建<code>.mongorc.js</code></p><ul><li>频繁加载的脚本</li><li>移除比较危险的shell辅助函数</li><li>指定<code>--norc</code>,可以禁止加载<code>.mongorc.js</code></li></ul></li><li><p>定制shell提示:将prompt变量设为一个字符串或函数</p></li><li><p>编辑符合变量:设置EDITOR</p></li></ul><p><br></p><h1 id="四个基本操作:创建、读取、更新、删除(CRUD)"><a href="#四个基本操作:创建、读取、更新、删除(CRUD)" class="headerlink" title="四个基本操作:创建、读取、更新、删除(CRUD)"></a>四个基本操作:创建、读取、更新、删除(CRUD)</h1><h2 id="创建"><a href="#创建" class="headerlink" title="创建"></a>创建</h2><ul><li>单个插入:<code>insert</code></li><li>批量插入:<code>batchInsert</code></li></ul><h2 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h2><ul><li>删除文档:<code>remove</code>,可接受一个查询文档作为参数</li><li>删除集合:<code>drop</code>,不能指定条件</li></ul><h2 id="更新"><a href="#更新" class="headerlink" title="更新"></a>更新</h2><ul><li><code>update</code>:必须接受两个参数,第一个匹配待更新文档,第二个是修改器文档。接受第三个参数,若为true,则表示这是upsert。接受第四个参数,若为true,则表示更新所有匹配的文档。</li><li>原子性的更新修改器<ul><li><code>$set</code>:指定一个字段的值</li><li><code>$unset</code>:删除指定键</li><li><code>$inc</code>:增加已有键的值,不存在则创建,只能用于整型、长整型或双精度浮点型的值</li><li><code>$push</code>:向已有数组末尾加入一个元素<ul><li><code>$each</code>:通过一次<code>$push</code>操作添加多个值</li><li><code>$slice</code>:设置最大长度,必须为负整数,相当于建立队列,保留最后的元素</li><li><code>$sort</code>:清理元素</li></ul></li><li><code>$addToSet</code>:添加新数据,可以避免重复</li><li><code>$pop</code>:可以从数组任何一端删除元素</li></ul></li><li><code>$pull</code>:删除所有匹配的文档</li><li><code>upsert</code>:若未找到符合更新条件的文档,则以此为条件创建新文档;若找到相应文档,正常更新。可用于创建又可用于更新。</li></ul><h2 id="读取"><a href="#读取" class="headerlink" title="读取"></a>读取</h2><p><strong>find和findOne</strong></p><ul><li>第一个参数用于指定查询条件</li><li><p>第二个参数指定想要返回的键</p></li><li><p>查询条件</p><ul><li><code>$lt,$lte,$gt,$gte,$ne</code>对应小于、小于等于、大于、大于等于、不等于</li><li><code>$in</code>:用来查询一个键的多个值</li><li><p><code>$or</code>:在多个键中查询任意给定值</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">db.raffle.find({<span class="string">"$or"</span>:[{<span class="string">"tricket_no"</span>:{<span class="string">"in"</span>:[<span class="number">755</span>,<span class="number">542</span>,<span class="number">390</span>]}},{<span class="string">"winner"</span>:<span class="literal">true</span>}]})</div></pre></td></tr></tbody></table></figure></li><li><p><code>$not</code>:用来查询与特定模式不匹配的文档</p></li><li><code>$exists</code>:判定键值是否存在</li><li><code>$maxscan</code>:指定本次查询文档数量的上限</li><li><code>$min</code>:强制指定下边界</li><li><code>$max</code>:强制指定上边界</li></ul></li><li><p><code>$showDiskLoc</code>:用于显示结果在磁盘的位置</p></li><li><p>数组查询</p><ul><li><code>$all</code>:通过多个元素匹配数组</li><li><code>$size</code>:查询特定长度的数组</li><li><code>$slice</code>:返回某个键匹配的数组元素的一个子集</li><li><code>$elemMatch</code>:指定一组添加,只可用于数组</li></ul></li><li><p>查询函数</p><ul><li><code>limit</code>:限制返回数量</li><li><code>skip</code>:忽略一定数量的结果</li><li><code>sort</code>:接受一个对象作为参数,键为文档键名,值为排序方向(1为升序,-1为降序)</li></ul></li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<blockquote>
<p>MongoDB是一个跨平台,面向文档的数据库,提供高性能,高可用性和易于扩展,总结知识点分享给与我一样刚入门MongoDB的人。</p>
</blockquote>
<h1 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h1><ul>
<li>数据库:数据库是一个集合的物理容器。每个数据库获取其自己设定在文件系统上的文件。一个单一的MongoDB服务器通常有多个数据库</li>
<li>集合:集合是一组MongoDB的文件。它与一个RDBMS表是等效的。一个集合存在于数据库中。集合不强制执行模式。集合中的文档可以有不同的字段。</li>
<li><p>文档:文档是一组键值对。文档具有动态模式。动态模式是指,在同一个集合的文件不必具有相同一组集合的文档字段或结构,并且相同的字段可以保持不同类型的数据。</p>
</li>
<li><p>文档是MongoDB中数据的基本单元</p>
</li>
<li>在MongoDB中,一个MongoDB实例可以承载多个数据库,每个数据库拥有0或多个集合,一个集合拥有多个文档</li>
<li>在同一个MongoDB服务器上存放多个应用那个程序或用户的数据,需要使用不同的数据库</li>
<li>使用BSON格式</li>
</ul>
</summary>
<category term="数据库" scheme="https://www.awebone.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
<category term="MongoDB" scheme="https://www.awebone.com/tags/MongoDB/"/>
</entry>
<entry>
<title>FreeCodeCamp学习笔记(二)</title>
<link href="https://www.awebone.com/posts/e20ef482/"/>
<id>https://www.awebone.com/posts/e20ef482/</id>
<published>2017-05-13T16:00:00.000Z</published>
<updated>2020-03-31T13:16:04.854Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="FreeCodeCamp学习笔记(二)"><a href="#FreeCodeCamp学习笔记(二)" class="headerlink" title="FreeCodeCamp学习笔记(二)"></a>FreeCodeCamp学习笔记(二)</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="软件概念"><a href="#软件概念" class="headerlink" title="软件概念"></a>软件概念</h3><ul><li>软件是程序或在硬件上运行的程序,写入硬件的代码,两种软件类型是操作系统和应用软件。</li><li>有三个主要的操作系统:Windows,Mac和Linux。</li><li>应用范围包括所有其他软件,如Web浏览器,游戏,还有像Photoshop,查看邮件,编辑文档的软件等。</li></ul><h3 id="CDN"><a href="#CDN" class="headerlink" title="CDN"></a>CDN</h3><ul><li>内容传递网络(CDN)是一种分布式服务器(网络),基于用户的地理位置向用户分发网页和其他Web内容,网页和内容分发服务器的起源。</li><li>CDN的目标是建立更高质量的网络连接。</li><li>CDNs通过为用户和用户目标站点之间建立快速通道或提供更快的建立在其他服务器上的镜像站点来达成目标。</li><li>这个概念和这种类型的服务不是创新型的想法,但是它正使互联网更加普及。</li><li>网站付费使用CDN服务,而CDN反过来you向因特网提供商付费来使用他们的服务和数据。</li><li>谷歌托管库就是一种CDNs : <code>developers.google.com/speed/libraries/#jquery</code></li><li>谷歌托管那些(常用的)库,比起你自己(在自己的服务器上)部署这些库,你的用户就可以更快的访问到它。</li><li>有可能的话,用户浏览器甚至会存储已经访问过的网站的缓存。</li></ul><a id="more"></a><h3 id="模拟与数字转换和压缩"><a href="#模拟与数字转换和压缩" class="headerlink" title="模拟与数字转换和压缩"></a>模拟与数字转换和压缩</h3><ul><li>一个模拟声波可能看起来像任何东西,例子中它是一条波浪线。</li><li>计算机采集和测量很多很多不同的点。把他们转化为数字,这就是所谓的采样。之后,计算机可以使用这些数字,并再次把它们变成声音。</li><li>压缩的好处是,它是一个更小的文件:它更容易储存,它更容易发送给其他人,它只是占用更少的空间。</li><li>压缩声音的一种常用方法是以更低的频率采样。</li><li>另一种方式是,它从一个中点而不是0开始采样,所以所采集的数字更小。</li><li>在图像中,它是通过测量一组16个的像素来压缩,而不是独立的。</li><li>视频中减掉的部分是你想使用一个高质量的数字文件,但当你在压缩时,你需要决定压缩到何种程度以确保用户仍然有最好的体验。</li></ul><h3 id="联网"><a href="#联网" class="headerlink" title="联网"></a>联网</h3><ul><li>路由器是连接不同的小范围网络的东西。</li></ul><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">我想打个比方:我是一名教师,我在一所学校工作。</div><div class="line"></div><div class="line">假如说我有一个包,并且我需要把它送给我在民政事务处工作的人。</div><div class="line"></div><div class="line">我不知道她在哪里,我不知道她的办公室所在地,但我知道她的名字。</div><div class="line"></div><div class="line">我找我的秘书,像我的第一台路由器,我说"嘿,我需要找在民政事务处的某某,你能帮帮我吗?",她会说:"当然,我不知道她的办公室准确位置,但我知道,下一步,我可以找到她所在的区域。"</div><div class="line"></div><div class="line">于是,她继续并将其它发送至到民政事务处的秘书,下一个路由器。</div><div class="line"></div><div class="line">那秘书不知道我是谁或者我在哪里,但她看到包装上的名称,知道结束位置。</div><div class="line"></div><div class="line">我想要去表达的是每个路由器只需要知道自己的小网,就在它旁边的站点。</div><div class="line"></div><div class="line">它不必知道整个互联网,但只是它自己的连接。</div><div class="line"></div><div class="line">它可以获取信息并说,好吧,我不知道确切位置这回事,但我会在正确的方向传递下去吧。</div><div class="line"></div><div class="line">这就是它所需要做的事。</div></pre></td></tr></tbody></table></figure><ul><li>路由器可以是不同的尺寸,不同容量,但他们做的是知道自己的邻居,获得信息,并传递向正确的方向。</li><li>路由器甚至不必须有完整的包的信息。</li><li>如果一台电脑正试图将信息发送到另一个时,数据可能会在不同的路由器之间分开,但是这没问题。计算机仍然知道如何正确地把信息重新组合到一起。</li><li>所发送信息的小碎片被称为数据包。包实际上是一小段二进制代码。</li><li>这是一个数据包的样子的示例,一段电流的视觉表示,计算机可以把它转化为1和0的,这就是我们所知道的二进制,可以代表任何数字数据。</li><li>这些小数据包通过路由器发送,并且如果一个文件是用一个信息包(发送)太大,它可以被分成帧(较小的小数据包)。帧发送到目的地不必采用相同的路由。</li><li>他们可以决定哪个路由是开放的,取其速度最快,而且因为它们具有IP地址,所有的路由器知道从哪里发送。一旦他们到达终点目的地,计算机知道如何把所有的信息重新拼合到一起。</li></ul><h3 id="源代码,解释器和编译器"><a href="#源代码,解释器和编译器" class="headerlink" title="源代码,解释器和编译器"></a>源代码,解释器和编译器</h3><ul><li>源代码本身是程序员创建的文本文档:他们键入它,它的字母,数字和符号。</li><li>如果你把这个给别人,让他们看看在他们的电脑查看这个文档,这没法帮助他们查看电子邮件,它不是一个浏览器,它只是一个文本文档。</li><li>计算机必须有一种解释它的东西,并使一些有用的东西可以运行于它。</li><li>有两种主要的方法是这样做:无论是由一个解释器或编译器。</li><li>每个浏览器都有一个解释器,这就是JavaScript如何被处理的。</li><li>其他的语言,像C++,使用编译器。</li><li>与解释器不同的是,编译器将其所有的工作都放在了程序员的端上。</li><li>他们发送他们的包,他们的产品,它已经被编译,它已经可以在一台机器上运行。</li><li>然而,JavaScript,和其他的解释型语言,您只需编写JavaScript,用户端的浏览器有能力解释它所以你不需要编译它。</li></ul><h2 id="硬件基础知识"><a href="#硬件基础知识" class="headerlink" title="硬件基础知识"></a>硬件基础知识</h2><h3 id="硬件组成"><a href="#硬件组成" class="headerlink" title="硬件组成"></a>硬件组成</h3><p><strong>计算机由4个基本部分组成:输入、输出、CPU(中央处理器)、存储器。</strong></p><ul><li><p>输入是你放入计算机的东西。</p></li><li><p>输出是你在显示屏上所看见的或在扬声器里所听见的。</p></li><li><p>CPU代表中央处理单元,并且当我们提到计算机时都能想起它。CPU是实现功能,运行软件的部分,由CPU来操作数据。</p></li><li><p>存储器是我们存储数据和信息的地方。CPU对存储器具有独占访问权。你无法通过输入和输出来访问内存而不使用CPU。</p><ul><li><p>现在存储器可以分为短期存储器, 称作RAM, 或者是长期存储器.</p></li><li><p>长期存储器通常是硬盘, 但是也可以是使CD-ROM或者是闪存设备, 或是任何这一类的。</p></li></ul></li></ul><p><strong>除了这四个基本部分, 我们今天还有另外三样东西要谈论: 主板,扩展槽和电源。</strong></p><ul><li><p>主板是连接这些硬件的东西。当这些数据到处流动试图找出该去哪时, 主板帮助他们导流他们,使他们去向正确的地方</p></li><li><p>扩展卡是声卡,显卡,这类可以提升用户体验的东西。</p></li><li><p>电源, 就像他的名字一样, 给我们的计算机提供电力。它通常是一个部件并有一个风扇在上面来帮助它散热。</p><ul><li>一个芯片全是由成千上万的晶体管(一种只能是0或1的开关)组成的</li></ul></li><li>所有的这些晶体管塞进了一个芯片里,并且这就是芯片存储信息的方式。<ul><li>在一个芯片上集成的晶体管数量决定了芯片的大小和速度</li></ul></li><li>摩尔定律是观察到自从1965年芯片上的晶体管数量每两年增加一倍的一种规律。<ul><li>二进制码是一种非常常见的计算机语言,它只能是1或0,也是on(开)或关,1代表on(开),0代表off(关)。</li></ul></li></ul><h3 id="数据"><a href="#数据" class="headerlink" title="数据"></a>数据</h3><p><strong>数据大小</strong></p><ul><li><p>最小的单位我们称之为1比特(bit)。比特(bit)只能是0或1, 也就是回到我们一直在学习的二进制。</p></li><li><p>字节, 很常见, 8比特(bit)。很多东西都可以用二个字节来表示。</p></li><li><p>下一步是KB, 1024个字节, 或者8192个比特(bit).</p></li><li><p>之后是MB, 1024个字节的2次方。</p></li><li><p>之后就是GB了, 1024个字节的3次方; TB, 1024个字节的4次方, 和PB, 1024个字节的5次方。</p></li></ul><p><strong>数据的速率</strong></p><ul><li>数据速率不同于数据大小, 通常是计算每秒多少比特, 而大小是计算有多少比特。</li><li>一旦我们涉及到指数级,数据速率的表示就有了很大的不同</li><li><p>怎么讨论数据速率取决于我们在讨论的东西。</p><ul><li><p>在音频下载中,我们使用KB/s</p></li><li><p>网速,我们使用MB/s。如果你看到你的网速有多少多少比特每秒,记住它永远比按你提到数据大小时的字节小8倍。</p></li><li><p>网络中, 我们用GB/s (十亿比特每秒!)。</p></li></ul></li><li>这里主要选取方式是速度是按比特来计算而大小是按字节来计算。</li></ul><h3 id="超级计算机"><a href="#超级计算机" class="headerlink" title="超级计算机"></a>超级计算机</h3><ul><li>一种使用一种叫做并行处理的技术同理用很多CPU处理同一问题的计算机。</li></ul><h3 id="服务器"><a href="#服务器" class="headerlink" title="服务器"></a>服务器</h3><ul><li>服务器拥有并访问大量的数据或程序。</li></ul><h3 id="工作站"><a href="#工作站" class="headerlink" title="工作站"></a>工作站</h3><ul><li>一种和个人电脑非常相似的计算机, 但是更耗能且贵的多。</li></ul><h3 id="微控制器"><a href="#微控制器" class="headerlink" title="微控制器"></a>微控制器</h3><ul><li><p>一种可能你汽车里都有的计算机,它非常擅长处理小型的特定的任务但是不可以像个人计算机那样操作和使用。</p></li><li><p>主板的构成是处理器和内存之间的桥梁-如果它不这样做,它就不是一个主板。但是大多数主板要比这个功能多的多。主要是它们有扩展槽和接口。</p><ul><li>扩展槽使你可以任意插入提高计算机性能的东西,而不需要让中央处理器负担更多。</li></ul></li><li>举个例子,显卡和声卡可以提供更好的声音和更出色的显示效果从而显著提升用户体验,却不会拖慢电脑。<ul><li>网卡也可以插进扩展槽。</li></ul></li><li>PC和扩展卡在笔记本上很常见,并且扩展卡因为他们尺寸很小被合并到了主板上。<ul><li>在电脑上,你会知道有一个地方链接USB,电源接口,SD卡,以太网,甚至是一个音频插孔来通过耳机听声音。它们都是接口,主板上一个可以连接外源到CPU来获取或者给予信息的地方。</li></ul></li></ul><h3 id="数据网络"><a href="#数据网络" class="headerlink" title="数据网络"></a>数据网络</h3><p><strong>三种类型:局域网(LAN),广域网(WAN),虚拟专用网(VPN)。</strong></p><ul><li><p>局域网就像是一小组计算机连接在了一起。局域网最重要的是这些计算机离得很近。</p></li><li><p>广域网是两个,三个或者更多的局域网长距离的连接起来。</p><ul><li><p>你也许认为他们通过因特网(Internet)相连接,对于VPN来说(虚拟专用网,设计上和广域网相似),你是对的。</p></li><li><p>一个广域网通常租用来自因特网公司的电缆来创建连接。</p></li></ul></li><li><p>因特网(Internet)的第一部分:因特网是如何工作的。</p><ul><li><p>IP地址:你可能已经习惯了每个设备都有它自己的IP地址,就像一个房子有它自己的地址一样。</p></li><li><p>如果一个设备没有IP地址因特网不能向它分发数据。</p></li><li><p>不止设备有,猫(modem)和路由器(router)也有,数据传输路上的每一步都有。</p></li><li><p>IP地址由位置所决定,起始于5个大型国际地区。</p></li><li><p>从左到右,数字意味着你的位置。</p></li></ul></li></ul><h2 id="Chrome调试学习"><a href="#Chrome调试学习" class="headerlink" title="Chrome调试学习"></a>Chrome调试学习</h2><h3 id="elements标签"><a href="#elements标签" class="headerlink" title="elements标签"></a>elements标签</h3><ul><li><p>在chrome浏览器中右击选中<code>Inspect element</code>即可访问elements标签,然后你就可以随便修改元素文本,元素标签和任何其他CSS或者HTML。</p></li><li><p>这些修改不会自动保存,不能当做IDE或者可以保存内容的编辑器。你可以使用chrome中的’persistent authoring’功能去保存更改。</p></li><li>记住这里层叠,继承和其他CSS规则都可以使用,另外,被覆盖的式样会以穿越文字的横线的形式展示。</li><li>需要注意的是现在”树”中看到的代码是当前的HTML,而不是页面加载时的代码。如果你用JavaScript或Jquery来改变页面元素,”树”就会更新。</li><li>Padding,border和margin都很容易在右下角的彩色盒子里面检查和编辑。</li></ul><h3 id="network标签"><a href="#network标签" class="headerlink" title="network标签"></a>network标签</h3><ul><li>network标签页是用来回答’页面中哪个部分最耗时间’或’哪个调用初始化了网络请求’</li><li>network仪表盘记录了页面中每个元素加载的详细信息。</li><li>每一个请求都记录在network仪表盘的底部日志中</li><li>观察底部的线条,你会注意到彩色图案。每一个颜色都代表了请求中的不同类型内容。</li><li>线越长代表网络耗时越大,我们最终目标就是缩短线长。如果出现长线条,说明某些内容拖慢了整个网页。</li><li>点击请求日志,会看到更加详细的请求信息。</li></ul><h3 id="Sources标签"><a href="#Sources标签" class="headerlink" title="Sources标签"></a>Sources标签</h3><ul><li>Sources标签页对调试JavaScript帮助很大。项目越大,越难准确找到问题所在。</li><li>可以对代码的不同部分设置断点,代码会到此停止执行。</li><li>有很多种断点类型可以使用,如一行特定代码,一个DOM事件,XMLHTTP请求或一个JavaScript事件。</li><li>设置好断电之后,浏览器在进入这段代码或事件时,会暂停执行。</li><li>通过减缓代码执行,我们就有机会仔细观察每一个设置点,准确跟踪页面行为。</li><li>一旦断点设置好,我们就可以逐步浏览和检查页面中断点处的代码。</li><li>和elements标签一样,可以实时编辑代码观察结果,不过记得在别处保存更改。</li></ul><h3 id="Timeline-面板"><a href="#Timeline-面板" class="headerlink" title="Timeline 面板"></a>Timeline 面板</h3><ul><li>Timeline 面板可以在应用运行时记录和分析所有行为。此处最适合分析应用性能问题。</li><li>就像通过network标签找出时间耗费,通过sources标签找出有问题的代码一样,通过Timeline可以观察到更多详细细节。</li><li>使用点击timeline的圆形按钮,你可以记录(捕获)堆栈,js性能,内存和图形绘制(CSS)等信息。</li><li>chrome会以小粒度的详细日志来展现这些信息,可以通过很多种形式来查看。</li><li>所有这些信息可以帮助你很好地理解浏览器中发生的行为,尤其是发现内存占用比较多的事件。</li><li>在加载新页面之前记得先点击’clear’按钮再开始记录。</li><li>当记录JS事件时,点击title或左侧的’function call’,会重定向到resource标签,同时定位到函数所在位置的代码行。</li></ul><h3 id="Profiles-面板"><a href="#Profiles-面板" class="headerlink" title="Profiles 面板"></a>Profiles 面板</h3><ul><li>Profiles 面板可以提供web应用或页面的执行时间和内存,主要是针对运行于页面或app上的JavaScript。</li><li>这里可以收集到3种类型的概述信息: CPU profile,HEAP snapshot和HEAP profile。HEAP profiles更多的和内存使用信息相关,CPU profile和JavaScript性能相关。</li><li>V8分析器可以帮助定位JavaScript中的性能问题,有助于优化代码。</li><li>每一个profile都可以在左侧查看,可以对每个页面采集多个profile。总体而言,profiles标签页非常适合优化代码。</li></ul><h3 id="Resources-面板"><a href="#Resources-面板" class="headerlink" title="Resources 面板"></a>Resources 面板</h3><ul><li>Resources 面板可以显示已经加载的资源,包括:IndexedDB,Web SQL数据库,local storage,session storage,cookies,Application Cache, 图片, 字体和样式表。</li><li>可以在浏览器中查看和修改所有这些信息。</li><li>当你进行高级网站构建时,resources 面板可以帮你更好的理解app和页面的实时性要求。</li></ul><h3 id="Audit-工具"><a href="#Audit-工具" class="headerlink" title="Audit 工具"></a>Audit 工具</h3><ul><li>Audit 工具帮助你逐步改善你的页面。</li><li>Audit 工具会自动给你提供改进建议。</li></ul><h3 id="Console-面板"><a href="#Console-面板" class="headerlink" title="Console 面板"></a>Console 面板</h3><ul><li>Console 面板提供了2个主要功能:在开发过程中记录调试信息和提供一个可以用于和文档、开发工具交互的shell环境。</li><li>可以使用标准JS语法和特定控制台命令来查看原始数据和结构化数据。</li><li>从API中获取的JSON数据是典型的结构化数据。</li><li>信息经常会叠加满屏幕,你可以键入’clear()’来清空屏幕。通过勾选’Preserve Log’可以保存日志。</li><li>有几种不同的日志命令,比如console.log()用于基本日志记录,console.error()和colsole.warn()用于一些重要信息。</li><li>Console中可以追踪异常(代码出现了问题),甚至可以在出现异常时暂停代码的执行,如果你还记得,这个功能在Source标签页中也有。</li></ul><h2 id="复杂度学习"><a href="#复杂度学习" class="headerlink" title="复杂度学习"></a>复杂度学习</h2><ul><li>时间复杂度是讨论算法花费多少时间的一种方式。它对于更快的提高精简中的软件的运行速度有着很大的作用。</li><li>当你编写代码的时候,你应该要知道这个软件需要花多长时间去执行。没有人想要创造一个由于运行缓慢而让用户觉得沮丧的项目。</li><li>时间复杂度相对于一个算法来说,是一个或多个函数的集合。</li><li>大O符号专门帮助您识别是算法没有’规模’好,还是在有大量不同的用户,信息,或其他投入量工作下运行良好。</li><li>这不符合摩尔定律 - 不管你的电脑有多大有快捷,如果算法是成倍地低效率,它在现实就无法使用。</li><li>通过在算法中执行的基本操作(基本操作=一个花费固定时间执行的操作)的数目统计来测量时间复杂度。</li><li>时间复杂度由函数T(n)表示。O代表函数,(n)表示作用于元件的数目。</li><li>渐进时间复杂度,对于任何的有效输入它可能花费的最长时间,是表达时间复杂度最常见的方式。</li><li>当你讨论大0符号,通常指的是最坏的情况。</li><li>作为一个经验法则,任何用N ^ 2或其他指数对于多个用户的网站来说都不是好的算法。</li></ul><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">O(1)——确定一个数字是奇数或偶数。O(1)是一个静态的时间常量,不管有多少信息或有多少用户它都是一样的不改变。</div><div class="line"></div><div class="line">O(log N)——发现一个字在字典里(使用二分法检索)。二分法检索是一个典型的“分而治之”的算法。</div><div class="line"></div><div class="line">O(N)——看一本书</div><div class="line"></div><div class="line">O(N log N)——排序一副扑克牌(使用归并排序)</div><div class="line"></div><div class="line">O(N ^ 2)——在你购物车上检查你的购物清单的每一样东西</div><div class="line"></div><div class="line">O(∞)-掷硬币,直到它落在头上</div></pre></td></tr></tbody></table></figure><h2 id="计算机安全"><a href="#计算机安全" class="headerlink" title="计算机安全"></a>计算机安全</h2><h3 id="针对密码的字典攻击"><a href="#针对密码的字典攻击" class="headerlink" title="针对密码的字典攻击"></a>针对密码的字典攻击</h3><ul><li>当创建您的密码,有些网站需要极其特殊和复杂的密码,这实际上是一个也不必要的。</li><li>他们想要保护你不受字典攻击的攻击。</li><li>字典攻击就是尝试字典里的每一个字词,或者是它自己数据库中的常见词汇和很多人使用过的密码</li><li>大多数密码都没有这个简单的,但是,这并不重要。</li><li>他们只需要简单的密码就可以攻击巨量的账户。</li><li>在创建密码时,你想要使用不同的类型,数字和符号,但是最有效的方法之一是出现一些随机的字母。</li></ul><h3 id="网络钓鱼"><a href="#网络钓鱼" class="headerlink" title="网络钓鱼"></a>网络钓鱼</h3><ul><li>网络钓鱼,是模仿其他正规站点的网页或者邮件,试图欺骗用户输入自己的个人信息,而它却没有连接到它所模仿的站点。</li><li>一般情况下,两种方式来保护免受这些攻击:在地址栏中查看网址,打开一个新的浏览器并转到它所声称的网站。</li><li>我们还要学习加密和HTTPS。</li><li>如果你是在星巴克试图访问您的银行帐户,您有理由怀疑有人能看到,并采集您的信息。</li><li>你会想在网址的开头寻找一个绿色的HTTPS而不是HTTP。</li><li>这意味着,你向该网站所发送的密码和其他信息都被加密,只有他们可以根据一串码解开的数据。</li><li>一般情况下,只要你显示的是私人或敏感信息,检查一下HTTPS。</li><li>其他一些提示:重要账户之间不要使用相同的代码。</li><li>如果您使用的网站被黑客侵入,密码再长也没用。</li><li>同样,不要下载奇怪的文件。</li><li>如果你下载的文件不是像.PDF,txt文件,JPG格式这样常见的文件类型,就要小心了。</li><li>你下载的一些文件非常厉害,它们甚至可以在后台运行。</li><li>最后,让你的软件更新,特别是联网的软件。</li><li>信息泄露的一种方式就是’坏人’发现了旧版本的漏洞并突破了安全系统。</li><li>这些漏洞在新版本中已经修复,如果你每个软件都保持更新,你可以避免很多问题。</li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="FreeCodeCamp学习笔记(二)"><a href="#FreeCodeCamp学习笔记(二)" class="headerlink" title="FreeCodeCamp学习笔记(二)"></a>FreeCodeCamp学习笔记(二)</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="软件概念"><a href="#软件概念" class="headerlink" title="软件概念"></a>软件概念</h3><ul>
<li>软件是程序或在硬件上运行的程序,写入硬件的代码,两种软件类型是操作系统和应用软件。</li>
<li>有三个主要的操作系统:Windows,Mac和Linux。</li>
<li>应用范围包括所有其他软件,如Web浏览器,游戏,还有像Photoshop,查看邮件,编辑文档的软件等。</li>
</ul>
<h3 id="CDN"><a href="#CDN" class="headerlink" title="CDN"></a>CDN</h3><ul>
<li>内容传递网络(CDN)是一种分布式服务器(网络),基于用户的地理位置向用户分发网页和其他Web内容,网页和内容分发服务器的起源。</li>
<li>CDN的目标是建立更高质量的网络连接。</li>
<li>CDNs通过为用户和用户目标站点之间建立快速通道或提供更快的建立在其他服务器上的镜像站点来达成目标。</li>
<li>这个概念和这种类型的服务不是创新型的想法,但是它正使互联网更加普及。</li>
<li>网站付费使用CDN服务,而CDN反过来you向因特网提供商付费来使用他们的服务和数据。</li>
<li>谷歌托管库就是一种CDNs : <code>developers.google.com/speed/libraries/#jquery</code></li>
<li>谷歌托管那些(常用的)库,比起你自己(在自己的服务器上)部署这些库,你的用户就可以更快的访问到它。</li>
<li>有可能的话,用户浏览器甚至会存储已经访问过的网站的缓存。</li>
</ul>
</summary>
<category term="web" scheme="https://www.awebone.com/categories/web/"/>
<category term="计算机基础知识" scheme="https://www.awebone.com/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"/>
<category term="FreeCodeCamp" scheme="https://www.awebone.com/tags/FreeCodeCamp/"/>
</entry>
<entry>
<title>使用JavaScript实现AI五子棋</title>
<link href="https://www.awebone.com/posts/d24e8921/"/>
<id>https://www.awebone.com/posts/d24e8921/</id>
<published>2017-04-26T16:00:00.000Z</published>
<updated>2020-07-18T08:19:36.367Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="实现步骤"><a href="#实现步骤" class="headerlink" title="实现步骤"></a>实现步骤</h1><ol><li><p>搭建HTML、CSS、JS框架</p></li><li><p>canvas画图</p></li><li>js实现棋盘</li><li>js实现棋子</li><li>棋盘落子</li></ol><a id="more"></a><p><br></p><h1 id="canvas画图"><a href="#canvas画图" class="headerlink" title="canvas画图"></a>canvas画图</h1><figure class="highlight"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><canvas id="chess" width="450px" height="450px"></canvas></div><div class="line"></div><div class="line">canvas {</div><div class="line"> display: block;</div><div class="line"> margin: 50px auto;</div><div class="line"> box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;</div><div class="line">}</div><div class="line"></div><div class="line">var chess = document.getElementById('chess');</div><div class="line">var context = chess.getContext('2d');</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="js实现棋盘"><a href="#js实现棋盘" class="headerlink" title="js实现棋盘"></a>js实现棋盘</h1><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> drawChessBoard = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">15</span>; i++) {</div><div class="line"> context.moveTo(<span class="number">15</span> + i * <span class="number">30</span>, <span class="number">15</span>);</div><div class="line"> context.lineTo(<span class="number">15</span> + i * <span class="number">30</span>, <span class="number">435</span>);</div><div class="line"> context.stroke();</div><div class="line"> context.moveTo(<span class="number">15</span>, <span class="number">15</span> + i * <span class="number">30</span>);</div><div class="line"> context.lineTo(<span class="number">435</span>, <span class="number">15</span> + i * <span class="number">30</span>);</div><div class="line"> context.stroke();</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="js实现棋子"><a href="#js实现棋子" class="headerlink" title="js实现棋子"></a>js实现棋子</h1><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> oneStep = <span class="function"><span class="keyword">function</span>(<span class="params">i, j, me</span>) </span>{</div><div class="line"><span class="comment">//画圆</span></div><div class="line"> context.beginPath();</div><div class="line"> context.arc(<span class="number">15</span> + i * <span class="number">30</span>, <span class="number">15</span> + j * <span class="number">30</span>, <span class="number">13</span>, <span class="number">0</span>, <span class="number">2</span> * <span class="built_in">Math</span>.PI);</div><div class="line"> context.closePath();</div><div class="line"></div><div class="line"> <span class="comment">//渐变</span></div><div class="line"> <span class="keyword">var</span> gradient = context.createRadialGradient(<span class="number">15</span> + i * <span class="number">30</span> + <span class="number">2</span>, <span class="number">15</span> + j * <span class="number">30</span> - <span class="number">2</span>, <span class="number">13</span>, <span class="number">15</span> + i * <span class="number">30</span> + <span class="number">2</span>, <span class="number">15</span> + j * <span class="number">30</span> - <span class="number">2</span>, <span class="number">0</span>);</div><div class="line"> <span class="keyword">if</span> (me) {</div><div class="line"> gradient.addColorStop(<span class="number">0</span>, <span class="string">"#0a0a0a"</span>);</div><div class="line"> gradient.addColorStop(<span class="number">1</span>, <span class="string">"#636766"</span>);</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> gradient.addColorStop(<span class="number">0</span>, <span class="string">"#d1d1d1"</span>);</div><div class="line"> gradient.addColorStop(<span class="number">1</span>, <span class="string">"#f9f9f9"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> context.fillStyle = gradient;</div><div class="line"> context.fill();</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><br></p><h1 id="落子"><a href="#落子" class="headerlink" title="落子"></a>落子</h1><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line">chess.onclick = <span class="function"><span class="keyword">function</span>(<span class="params">e</span>) </span>{</div><div class="line"> <span class="keyword">var</span> x = e.offsetX;</div><div class="line"> <span class="keyword">var</span> y = e.offsetY;</div><div class="line"></div><div class="line"> <span class="comment">//向下取整算出索引</span></div><div class="line"> <span class="keyword">var</span> i = <span class="built_in">Math</span>.floor(x / <span class="number">30</span>);</div><div class="line"> <span class="keyword">var</span> j = <span class="built_in">Math</span>.floor(y / <span class="number">30</span>);</div><div class="line"> <span class="keyword">if</span> (chessBoard[i][j]==<span class="number">0</span>) {</div><div class="line"> oneStep(i, j, me);</div><div class="line"> <span class="keyword">if</span> (me) {</div><div class="line"> chessBoard[i][j]==<span class="number">1</span>;</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> chessBoard[i][j]==<span class="number">2</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//me轮流取反</span></div><div class="line"> me = !me;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//默认黑子</span></div><div class="line"><span class="keyword">var</span> me = <span class="literal">true</span>;</div><div class="line"></div><div class="line"><span class="comment">//存储棋盘落子情况</span></div><div class="line"><span class="keyword">var</span> chessBoard=[];</div><div class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">15</span>; i++) {</div><div class="line">chessBoard[i]=[];</div><div class="line"><span class="keyword">for</span> (<span class="keyword">var</span> j = <span class="number">0</span>; i < <span class="number">15</span>; j++) {</div><div class="line">chessBoard[i][j]=<span class="number">0</span>;</div><div class="line">}</div><div class="line">}</div></pre></td></tr></tbody></table></figure><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="实现步骤"><a href="#实现步骤" class="headerlink" title="实现步骤"></a>实现步骤</h1><ol>
<li><p>搭建HTML、CSS、JS框架</p>
</li>
<li><p>canvas画图</p>
</li>
<li>js实现棋盘</li>
<li>js实现棋子</li>
<li>棋盘落子</li>
</ol>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>HTML5存储初探</title>
<link href="https://www.awebone.com/posts/bce46d0d/"/>
<id>https://www.awebone.com/posts/bce46d0d/</id>
<published>2017-04-25T16:00:00.000Z</published>
<updated>2020-03-31T13:15:50.270Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="HTML5存储初探"><a href="#HTML5存储初探" class="headerlink" title="HTML5存储初探"></a>HTML5存储初探</h1><p><strong>常见存储:</strong></p><ol><li>Cookies</li><li>localStorage && sessionStorage</li><li>indexedDB</li><li>application cache</li></ol><p><strong>其它客户端存储:</strong></p><ol><li><p>userData</p><p> 只有IE支持(IE5.0 … 9.0)</p></li><li><p>google Gears</p><ul><li>chrome (12.0后放弃支持)</li><li>引擎:64SQLite</li><li>需要用户授权</li></ul></li></ol><a id="more"></a><h2 id="Cookies"><a href="#Cookies" class="headerlink" title="Cookies"></a>Cookies</h2><p>Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。</p><p>当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等</p><p>Cookies文件是在无声无息中伴随浏览器进入我们本地硬盘的,当我们浏览某个站点时,该站点很可能将记录我们隐私的cookies文件上传到本地硬盘。</p><p>H5存储解决了cookie的问题</p><ul><li>解决cookie总数和单个大小的限制(4k 4095B)</li><li>解决请求头常带存储信息的问题</li><li>解决关系型存储的问题</li><li>跨浏览器</li></ul><h2 id="本地存储-localStorage-amp-amp-sessionStorage"><a href="#本地存储-localStorage-amp-amp-sessionStorage" class="headerlink" title="本地存储( localStorage && sessionStorage)"></a>本地存储( localStorage && sessionStorage)</h2><blockquote><p>图片不经常更改,不过如果图片bash64比较大的话,会比较浪费资源)</p></blockquote><ul><li><p>常用属性和方法:</p><figure class="highlight plain"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">localStorage.key(i)</div><div class="line">.length</div><div class="line">.getItem("<key>")</div><div class="line">.setItem("<key>","<value>")</div><div class="line">.removeItem("<key>")</div><div class="line">.clear()</div></pre></td></tr></tbody></table></figure></li><li><p>使用注意事项:</p><ul><li>使用前先判断浏览器是否支持(浏览器开启无痕模式后不能用,有的可读但不可写,所以不能用 <code>if(window.localStorage){}</code>来做兼容处理,先set,然后再捕获异常)</li><li>写数据时,要异常处理,避免抛出容量错误</li><li>避免将敏感信息写入localStorage</li><li>注意key的唯一性,会被覆盖</li></ul></li></ul><ul><li>使用场景:<ul><li>利用本地数据,减少网络传输</li><li>弱网络环境下,高延迟,低带宽,尽量把数据本地化</li></ul></li></ul><ul><li>H5本地存储的使用限制<ul><li>需要添加存储更新策略和过期控制</li><li>子域名之间不能共享存储数据</li><li>超出存储后如何存储<code>(LRU,FIFO) --> LRU (Least Recently Used) FIFO (先入先出)</code></li><li>server端如何取到数据(请求参数)</li></ul></li></ul><ul><li>localStorage优点:<ul><li>存储大小达5M</li><li>兼容性好,功能强大</li><li>应用范围广</li></ul></li></ul><h2 id="IndexedDB"><a href="#IndexedDB" class="headerlink" title="IndexedDB"></a>IndexedDB</h2><ul><li><p>定义</p><p>一种能在浏览器中持久存储结构化数据的数据库,并为web应用提供了丰富的查询能力。</p></li><li><p>浏览器支持</p><p>chromw11+,FF4+,IE10+,移动端支持弱</p></li><li><p>存储结构</p><p>按域名分配独立空间,一个域名下可创建多个数据库,一个DB可以创建多个对象储存空间(表),一个对象存储空间可以创建多个对象数据。</p><p><img src="/images/html-store/IndexedSQL.jpg" alt="IndexedSQL"></p></li><li><p>功能</p><ul><li>增删改</li><li>事务</li><li>游标 </li><li>索引</li></ul></li></ul><p><em>注:w3c已不在维护Web SQL.</em></p><h2 id="离线缓存(application-cache)"><a href="#离线缓存(application-cache)" class="headerlink" title="离线缓存(application cache)"></a>离线缓存(application cache)</h2><ul><li><p>离线缓存(application cache):让web应用在离线情况下继续使用,通过manifest文件指明要缓存的资源</p></li><li><p>检测是否在线:navigator.onLine</p></li><li><p>原理(如图):读取离线缓存,同时检查manifest文件,有更新时更新文件和缓存</p><p><img src="/images/html-store/H51.jpg" alt="H51"></p></li><li><p>appcache使用和更新</p><ul><li>使用:创建manifest文件</li><li>修改资源文件,必须通过修改manifest文件来更新被缓存的文件列表</li></ul><p><img src="/images/html-store/H52.jpg" alt="H52"></p></li><li><p>优点</p><ul><li>完全离线</li><li>资源被缓存,加载更快</li><li>降低server负载</li></ul></li></ul><ul><li>缺陷<ul><li>含有manifest属性的当前页一定会被缓存</li><li>更新依赖manifest文件,更新后需要再次刷新</li><li>更新是全局性的,无法单点更新</li><li>对于链接的参数变化敏感,不同的参数视为不同的文件</li><li>占用资源</li><li>更新内容会在下次生效</li></ul></li></ul><ul><li><p>浏览器支持:IE8-不支持</p></li><li><p>适用场景</p><ul><li>单地址的页面(无参数)</li><li>对实时性要求不高的业务</li><li>离线webapp</li></ul></li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li><p>H5存储优势:</p><ul><li>存储空间大</li><li>接口丰富</li><li>数据相对安全</li><li>关系型</li><li>省流量</li></ul></li><li><p>H5存储劣势:</p><ul><li>浏览器兼容( localStorage 和 app cache 主流浏览器都兼容的不错 )</li><li>同源策略( localStorage 不可以跨子域,manifest 所引用的文件必须在同一个域名下面 )</li><li>脚本控制( 只能在浏览器端存放;服务器端想拿到数据,只能通过请求 )</li><li>更新策略(不像cookie可以设置过期时间;比如localStorage永不过期,必须自己写一套更新机制 )</li></ul></li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="HTML5存储初探"><a href="#HTML5存储初探" class="headerlink" title="HTML5存储初探"></a>HTML5存储初探</h1><p><strong>常见存储:</strong></p>
<ol>
<li>Cookies</li>
<li>localStorage &amp;&amp; sessionStorage</li>
<li>indexedDB</li>
<li>application cache</li>
</ol>
<p><strong>其它客户端存储:</strong></p>
<ol>
<li><p>userData</p>
<p> 只有IE支持(IE5.0 … 9.0)</p>
</li>
<li><p>google Gears</p>
<ul>
<li>chrome (12.0后放弃支持)</li>
<li>引擎:64SQLite</li>
<li>需要用户授权</li>
</ul>
</li>
</ol>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="HTML" scheme="https://www.awebone.com/tags/HTML/"/>
</entry>
<entry>
<title>FreeCodeCamp学习笔记(一)</title>
<link href="https://www.awebone.com/posts/6bfb34d8/"/>
<id>https://www.awebone.com/posts/6bfb34d8/</id>
<published>2017-04-23T16:00:00.000Z</published>
<updated>2020-03-31T13:16:10.601Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="FreeCodeCamp学习笔记-一"><a href="#FreeCodeCamp学习笔记-一" class="headerlink" title="FreeCodeCamp学习笔记(一)"></a>FreeCodeCamp学习笔记(一)</h1><h2 id="HTML学习"><a href="#HTML学习" class="headerlink" title="HTML学习"></a>HTML学习</h2><ul><li><p><code>a</code>标签用<code>#</code>做占位符</p></li><li><p><code>img</code>标签里应加<code>alt</code>属性,为了盲人朋友</p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>></span></div><div class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">"smaller-image thick-green-border"</span> <span class="attr">alt</span>=<span class="string">"A cute orange cat lying on its back"</span> <span class="attr">src</span>=<span class="string">"/images/relaxing-cat.jpg"</span>></span></div><div class="line"><span class="tag"></<span class="name">a</span>></span></div></pre></td></tr></tbody></table></figure></li><li><p><code>input</code>标签加<code>placeholder</code>做占位符提示,在需要设置必填项的时候加<code>required</code>属性</p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">placeholder</span>=<span class="string">"cat photo URL"</span> <span class="attr">required</span>></span></div></pre></td></tr></tbody></table></figure></li><li><p>单选和复选按钮应加入到<code>label</code>标签里,<code>name</code>属性名应一致,<code>checked</code>为默认选中</p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">label</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"indoor-outdoor"</span> <span class="attr">checked</span>></span> Indoor<span class="tag"></<span class="name">label</span>></span></div><div class="line"><span class="tag"><<span class="name">label</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"indoor-outdoor"</span>></span> Outdoor<span class="tag"></<span class="name">label</span>></span></div><div class="line"><span class="tag"><<span class="name">label</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span> <span class="attr">checked</span>></span> Loving<span class="tag"></<span class="name">label</span>></span></div><div class="line"><span class="tag"><<span class="name">label</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span>></span> Lazy<span class="tag"></<span class="name">label</span>></span></div><div class="line"><span class="tag"><<span class="name">label</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span>></span> Energetic<span class="tag"></<span class="name">label</span>></span></div></pre></td></tr></tbody></table></figure></li></ul><a id="more"></a><h2 id="CSS学习"><a href="#CSS学习" class="headerlink" title="CSS学习"></a>CSS学习</h2><p>浏览器读取 CSS 的顺序是从上到下,这意味着,在发生冲突时,浏览器会使用最后的 CSS 声明。但是如果设置id, id 属性总是具有更高的优先级。</p><p>很多情况下,你会使用 CSS 库,这些库可能会意外覆盖掉你自己的 CSS。所以当你需要确保某元素具有指定的 CSS 时,你可以使用 !important.</p><h3 id="盒子模型"><a href="#盒子模型" class="headerlink" title="盒子模型"></a>盒子模型</h3><p>有三个影响HTML元素布局的重要属性:padding(内边距)、margin(外边距)、border(边框)。</p><ul><li><p>元素的 padding 控制元素内容 content和元素边框 border 之间的距离。</p><p>当加大 padding, 将扩大元素内容和元素边框的距离。</p></li><li><p>元素的外边距 margin 控制元素边框 border 和元素实际所占空间的距离。</p><p>当增大 margin 时,将会增加元素边框和元素实际所占空间之间的距离。</p><p>如果你将一个元素的 margin 设置为负值,元素将会变大。</p></li></ul><h3 id="RGB颜色设置"><a href="#RGB颜色设置" class="headerlink" title="RGB颜色设置"></a>RGB颜色设置</h3><p>0 是 hex code(十六进制编码)中最小的一个,它代表颜色的完全缺失。</p><p>F 是 hex code(十六进制编码)中最大的一个,它代表最大可能的亮度。</p><p>16 个值和 6 个位置意味着我们有 16 的 6 次方,或者说超过 1600 万种可能的颜色.</p><p>Hex code 遵循 red-green-blue(红-绿-蓝),或者叫 rgb 格式。hex code 中的前两位表示颜色中红色的数量,第三四位代表绿色的数量,第五六位代表蓝色的数量。</p><h2 id="jQuery学习"><a href="#jQuery学习" class="headerlink" title="jQuery学习"></a>jQuery学习</h2><p><strong>jQuery通过选择器来选择一个元素的,然后操作元素做些改变。</strong></p><ol><li>要让所有的按钮做弹回效果,只要把这段代码写在<figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="built_in">document</span>).ready(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{});</div></pre></td></tr></tbody></table></figure></li></ol><p>里面,然后<br></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"button"</span>).addClass(<span class="string">"animated bounce"</span>);</div></pre></td></tr></tbody></table></figure><p></p><ol><li><p>你可以通过jQuery的addClass()方法给元素添加class,也可以通过jQueryremoveClass()方法去掉元素上的class。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#target2"</span>).removeClass(<span class="string">"btn-default"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery有一个叫做.css()的方法能让你改变元素的CSS样式。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#target1"</span>).css(<span class="string">"color"</span>, <span class="string">"blue"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery有一个.prop()的方法让你来调整元素的属性</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"button"</span>).prop(<span class="string">"disabled"</span>, <span class="literal">true</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery的.html()方法可以添加HTML标签和文字到元素,而元素之前的内容都会被方法的内容所替换掉。</p><p>我们是通过em[emphasize]标签来重写和强调标题文本的:</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"h3"</span>).html(<span class="string">"<em>jQuery Playground</em>"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery 还有一个类似的方法叫.text(),它只能改变文本但不能修改标记。换句话说,这个方法只会把传进来的任何东西(包括标记)当成文本来显示。</p></li><li><p>jQuery有一个appendTo()方法可以把选中的元素加到其他元素中。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#target4"</span>).appendTo(<span class="string">"#left-well"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery的clone()方法可以拷贝元素。<br>方法链function chaining,使用起来很方便</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#target2"</span>).clone().appendTo(<span class="string">"#right-well"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>每个HTML元素根据继承属性都有父parent元素,jQuery有一个方法叫parent(),它允许你访问指定元素的父元素</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#left-well"</span>).parent().css(<span class="string">"background-color"</span>, <span class="string">"blue"</span>)</div></pre></td></tr></tbody></table></figure></li><li><p>许多HTML元素都有children(子元素),每个子元素都从父元素那里继承了一些属性jQuery有一个方法叫children(),它允许你访问指定元素的子元素。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#left-well"</span>).children().css(<span class="string">"color"</span>, <span class="string">"blue"</span>)</div></pre></td></tr></tbody></table></figure></li><li><p>jQuery 用CSS选择器来选取元素,target:nth-child(n) CSS选择器允许你按照索引顺序(从1开始)选择目标元素的所有子元素。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">".target:nth-child(3)"</span>).addClass(<span class="string">"animated bounce"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>获取class为target且索引为奇数的所有元素,并给他们添加class。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">".target:odd"</span>).addClass(<span class="string">"animated shake"</span>);</div></pre></td></tr></tbody></table></figure></li></ol><p>jQuery里的索引是从0开始的,也就是说::odd 选择第2、4、6个元素,因为target#2(索引为1),target#4(索引为3),target6(索引为5)。获取class为target且索引为偶数的所有元素,并给他们添加class。<br></p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">".target:even"</span>).addClass(<span class="string">"animated shake"</span>);</div></pre></td></tr></tbody></table></figure><p></p><ol><li><p>让整个body都有淡出效果(fadeOut):</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"body"</span>).addClass(<span class="string">"animated fadeOut"</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>$(document).ready(),这个函数中的代码只会在我们的页面加载时候运行一次,确保执行js之前页面所有的dom已经准备就绪。</p></li><li><p>增加一个click事件,通过点击事件来更改文本。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#getMessage"</span>).on(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> $(<span class="string">".message"</span>).html(<span class="string">"Here is the message"</span>);</div><div class="line">});</div></pre></td></tr></tbody></table></figure></li></ol><h2 id="JavaScript基础"><a href="#JavaScript基础" class="headerlink" title="JavaScript基础"></a>JavaScript基础</h2><h3 id="循环"><a href="#循环" class="headerlink" title="循环"></a>循环</h3><ul><li><p>一个条件语句只能执行一次代码,而一个循环语句可以多次执行代码。</p></li><li><p>JavaScript 中最常见的循环就是“for循环”。</p><ul><li>for循环中的三个表达式用分号隔开:for ([初始化]; [条件判断]; [计数器])</li><li>初始化语句只会在执行循环开始之前执行一次。它通常用于定义和设置你的循环变量。</li><li>条件判断语句会在每一轮循环的开始执行,只要条件判断为 true 就会继续执行循环。当条件为 false的时候,循环将停止执行。这意味着,如果条件在一开始就为 false,这个循环将不会执行。</li><li>计数器是在每一轮循环结束时执行,通常用于递增或递减。</li><li>for循环可以按照我们指定的顺序来迭代,通过更改我们的 计数器,我们可以按照偶数顺序来迭代。</li><li>for循环也可以逆向迭代,只要我们定义好合适的条件。</li><li>迭代输出一个数组的每个元素是 JavaScript 中的常见需求, for 循环可以做到这一点。记住数组的索引从零开始的,这意味着数组的最后一个元素的下标是:数组的长度 - 1。</li><li>如果你有一个二维数组,可以使用相同的逻辑,先遍历外面的数组,再遍历里面的子数组。对于内部循环,我们可以通过 arr[i] 的 .length 来获得子数组的长度,因为 arr[i] 的本身就是一个数组。</li></ul></li><li>另一种类型的 JavaScript 循环被称为while循环,因为它规定,当(while)条件为真,循环才会执行,反之不执行。</li></ul><h3 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h3><ul><li><p>Math.random()用来生成一个在0(包括0)到1(不包括1)之间的随机小数,因此Math.random()可能返回0但绝不会返回1。要生成的随机数是在两个指定的数之间。</p></li><li><p>用 Math.floor() 向下取整 获得它最近的整数</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * <span class="number">20</span>);</div></pre></td></tr></tbody></table></figure></li><li><p>定义一个最小值和一个最大值。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * (max - min + <span class="number">1</span>)) + min</div></pre></td></tr></tbody></table></figure></li></ul><h3 id="正则"><a href="#正则" class="headerlink" title="正则"></a>正则</h3><ul><li>Regular expressions 正则表达式被用来根据某种匹配模式来寻找strings中的某些单词。</li><li>我们可以把这个正则表达式分成几段:<ul><li>/ 是这个正则表达式的头部</li><li>the 是我们想要匹配的模式</li><li>/ 是这个正则表达式的尾部</li><li>g 代表着 global(全局),意味着返回所有的匹配而不仅仅是第一个。</li><li>i 代表着忽略大小写,意思是当我们寻找匹配的字符串的时候忽略掉字母的大小写。</li></ul></li><li>我们可以在正则表达式中使用特殊选择器来选取特殊类型的值。<ul><li>特殊选择器中的一种就是数字选择器<code>\d</code>,意思是被用来获取一个字符串的数字.在JavaScript中, 数字选择器类似于: <code>/\d/g</code>。</li><li>在选择器后面添加一个加号标记(+),例如:<code>/\d+/g</code>,它允许这个正则表达式匹配一个或更多数字。尾部的g是’global’的简写,意思是允许这个正则表达式 找到所有的匹配而不是仅仅找到第一个匹配。</li><li>我们也可以使用正则表达式选择器 <code>\s</code> 来选择一个字符串中的空白。空白字符有<code>" " (空格符)、\r (回车符)、\n (换行符)、\t (制表符) 和 \f (换页符)</code>。空白正则表达式类似于:<code>/\s+/g</code></li><li>你可以用正则表达式选择器的大写版本 来转化任何匹配。举个例子:<code>\s</code> 匹配任何空白字符,<code>\S</code> 匹配任何非空白字符。</li></ul></li></ul><h3 id="JSON与API"><a href="#JSON与API" class="headerlink" title="JSON与API"></a>JSON与API</h3><ul><li><p>JavaScript Object Notation 简称 JSON,它使用JavaScript对象的格式来存储数据。JSON是灵活的,因为它允许数据结构是字符串,数字,布尔值,字符串,和对象的任意组合。</p></li><li><p>数组中有多个 JSON 对象的时候,对象与对象之间要用逗号隔开。</p></li><li><p>通过串联起来的点操作符或中括号操作符来访问JSON对象的嵌套属性。因为属性的名字带有空格,请使用中括号操作符来访问属性的值。</p></li><li><p>JSON对象可以嵌套对象和数组。与访问嵌套对象一样,用中括号操作符同样可以访问嵌套数组。</p></li><li><p>函数返回的永远是整个对象</p></li><li><p>使用中括号操作符来访问对象的变量属性</p></li><li><p>JSON是一种非常简洁的数据格式。它通常表现为了两种形式,一种为单个对象,一种为多个对象</p><ul><li>单个对象类似于:</li></ul><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">{<span class="attr">name</span>:<span class="string">'盖伦'</span>,<span class="attr">advantage</span>:<span class="string">'单挑无敌'</span>}</div></pre></td></tr></tbody></table></figure><ul><li>多个对象类似于:</li></ul><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[{<span class="attr">name</span>:<span class="string">'盖伦'</span>,<span class="attr">advantage</span>:<span class="string">'单挑无敌'</span>},{<span class="attr">name</span>:<span class="string">'诺克'</span>,<span class="attr">advantage</span>:<span class="string">'上单霸主'</span>}]</div></pre></td></tr></tbody></table></figure><ul><li>每个对象属性和属性值的组合就是我们经常听到的”键值对(key-value pairs)”。</li></ul></li><li><p>当你需要根据服务器返回的数据来动态改变页面的时候,应用程序接口(API)就派上用场了。API——应用程序接口(Application Programming Interface)是计算机之间相互交流沟通的工具。</p></li><li><p>许多网站的应用程序接口(API)都是通过一种称为JSON格式的数据来传输的,JSON 是 JavaScript Object Notation的简写。</p></li></ul><p><strong>举例:</strong></p><ul><li><p>从JSON API中获得了数据:</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$.getJSON(<span class="string">"/json/cats.json"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">json</span>) </span>{</div><div class="line"> $(<span class="string">".message"</span>).html(<span class="built_in">JSON</span>.stringify(json));</div><div class="line">});</div></pre></td></tr></tbody></table></figure></li><li><p>把它们展现到我们的HTML页面中吧。</p><ul><li>使用.forEach()函数来循环遍历JSON数据写到html变量中。</li><li>首先我们定义一个HTML变量,<code>var html = "";</code> 。</li><li>然后,我们使用.forEach()函数来循环遍历JSON数据写到html变量中,最后把html变量显示到我们的页面中。</li></ul><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">json.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">val</span>) </span>{</div><div class="line"> <span class="keyword">var</span> keys = <span class="built_in">Object</span>.keys(val);</div><div class="line"> html += <span class="string">"<div class = 'cat'>"</span>;</div><div class="line"> keys.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">key</span>) </span>{</div><div class="line"> html += <span class="string">"<b>"</span> + key + <span class="string">"</b>: "</span> + val[key] + <span class="string">"<br>"</span>;</div><div class="line"> });</div><div class="line"> html += <span class="string">"</div><br>"</span>;</div><div class="line">});</div></pre></td></tr></tbody></table></figure></li><li><p>获得的JSON数组中,每个对象都包含了一个以imageLink为键(key),以猫的图片的url为值(value)的键值对。</p><p>遍历,用imageLink的属性来显示img元素的图片。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">html += <span class="string">"<img src = '"</span> + val.imageLink + <span class="string">"'>"</span>;</div></pre></td></tr></tbody></table></figure></li><li><p>不想把所有从JSON API中得到的图片都展现出来,可以在遍历之前做一次过滤。把其中 “id” 键的值为1的图片过滤掉。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">json = json.filter(<span class="function"><span class="keyword">function</span>(<span class="params">val</span>) </span>{</div><div class="line"> <span class="keyword">return</span> (val.id !== <span class="number">1</span>);</div><div class="line">});</div></pre></td></tr></tbody></table></figure></li><li><p>可以通过浏览器navigator获得我们当前所在的位置geolocation。位置的信息包括经度longitude和纬度latitude。</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (navigator.geolocation) {</div><div class="line"> navigator.geolocation.getCurrentPosition(<span class="function"><span class="keyword">function</span>(<span class="params">position</span>) </span>{</div><div class="line"> $(<span class="string">"#data"</span>).html(<span class="string">"latitude: "</span> + position.coords.latitude + <span class="string">"<br>longitude: "</span> + position.coords.longitude);</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></tbody></table></figure></li></ul><h3 id="Object对象"><a href="#Object对象" class="headerlink" title="Object对象"></a>Object对象</h3><ul><li><p>可以使用构造函数来创建对象。</p></li><li><p>构造函数通常使用大写字母开头,以便把自己和其他普通函数区别开。</p><p>下面便是一个构造函数:</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> Car = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">this</span>.wheels = <span class="number">4</span>;</div><div class="line"> <span class="keyword">this</span>.engines = <span class="number">1</span>;</div><div class="line"> <span class="keyword">this</span>.seats = <span class="number">1</span>;</div><div class="line">};</div></pre></td></tr></tbody></table></figure></li><li><p>在构造函数中,this 指向被此构造函数创建出来的对象 。所以当我们在构造函数中写:</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">this</span>.wheels = <span class="number">4</span>;</div></pre></td></tr></tbody></table></figure><ul><li>创建出来的新对象将带有 wheels 属性,并且赋值为 4.</li></ul></li><li><p>构造函数描述了它所创建出来的对象。</p></li><li><p>使用构造函数时,我们通过在它前面使用 new 关键字 来对它进行调用,如下:</p><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> myCar = <span class="keyword">new</span> Car();</div></pre></td></tr></tbody></table></figure><ul><li>myCar 现在成为了 Car 的一个实例(instance),它被构造函数描述成下面的样子:</li></ul><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> <span class="attr">wheels</span>: <span class="number">4</span>,</div><div class="line"> <span class="attr">engines</span>: <span class="number">1</span>,</div><div class="line"> <span class="attr">seats</span>: <span class="number">1</span></div><div class="line">}</div></pre></td></tr></tbody></table></figure><ul><li>要使用 new 关键字去调用构造函数。因为只有这样,Javascript才知道这是要去构造一个新对象 ,并且把构造函数中的 this 指向这个新对象。</li><li>当 myCar(即 Car 的一个 实例 )创建后,他可以像普通对象一样被使用,包括创建、访问、修改它的属性等,就像我们使用其他对象一样。</li></ul></li><li><p>对象拥有自己的特征,称为属性,对象还有自己的函数,称为方法。</p></li><li><p>构造函数中,我们使用了 this 指向当前(将要被创建的)对象中的公有属性 。</p></li><li><p>我们也可以创建私有属性和私有方法,它们两个在对象外部是不可访问的。</p></li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="FreeCodeCamp学习笔记-一"><a href="#FreeCodeCamp学习笔记-一" class="headerlink" title="FreeCodeCamp学习笔记(一)"></a>FreeCodeCamp学习笔记(一)</h1><h2 id="HTML学习"><a href="#HTML学习" class="headerlink" title="HTML学习"></a>HTML学习</h2><ul>
<li><p><code>a</code>标签用<code>#</code>做占位符</p>
</li>
<li><p><code>img</code>标签里应加<code>alt</code>属性,为了盲人朋友</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span></div><div class="line"> <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">"smaller-image thick-green-border"</span> <span class="attr">alt</span>=<span class="string">"A cute orange cat lying on its back"</span> <span class="attr">src</span>=<span class="string">"/images/relaxing-cat.jpg"</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></div></pre></td></tr></tbody></table></figure>
</li>
<li><p><code>input</code>标签加<code>placeholder</code>做占位符提示,在需要设置必填项的时候加<code>required</code>属性</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">placeholder</span>=<span class="string">"cat photo URL"</span> <span class="attr">required</span>&gt;</span></div></pre></td></tr></tbody></table></figure>
</li>
<li><p>单选和复选按钮应加入到<code>label</code>标签里,<code>name</code>属性名应一致,<code>checked</code>为默认选中</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">label</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"indoor-outdoor"</span> <span class="attr">checked</span>&gt;</span> Indoor<span class="tag">&lt;/<span class="name">label</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">label</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">name</span>=<span class="string">"indoor-outdoor"</span>&gt;</span> Outdoor<span class="tag">&lt;/<span class="name">label</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">label</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span> <span class="attr">checked</span>&gt;</span> Loving<span class="tag">&lt;/<span class="name">label</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">label</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span>&gt;</span> Lazy<span class="tag">&lt;/<span class="name">label</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">label</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">name</span>=<span class="string">"personality"</span>&gt;</span> Energetic<span class="tag">&lt;/<span class="name">label</span>&gt;</span></div></pre></td></tr></tbody></table></figure>
</li>
</ul>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="https://www.awebone.com/tags/CSS/"/>
<category term="FreeCodeCamp" scheme="https://www.awebone.com/tags/FreeCodeCamp/"/>
<category term="HTML" scheme="https://www.awebone.com/tags/HTML/"/>
<category term="JavaScript" scheme="https://www.awebone.com/tags/JavaScript/"/>
</entry>
<entry>
<title>CSS3实现3D魔方</title>
<link href="https://www.awebone.com/posts/4370e84d/"/>
<id>https://www.awebone.com/posts/4370e84d/</id>
<published>2017-04-21T16:00:00.000Z</published>
<updated>2020-03-31T13:16:31.210Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="CSS3实现3D魔方"><a href="#CSS3实现3D魔方" class="headerlink" title="CSS3实现3D魔方"></a>CSS3实现3D魔方</h1><p><strong>实现思路</strong></p><ul><li><p>写出基础HTML框架</p></li><li><p>基本CSS样式,初始化</p></li><li><p>CSS实现魔方的各个面:外轮廓和内盒子</p></li><li><p>CSS3实现魔方表面的3D位置</p></li><li><p>CSS3实现旋转</p></li></ul><a id="more"></a><h2 id="第一步:HTML结构"><a href="#第一步:HTML结构" class="headerlink" title="第一步:HTML结构"></a>第一步:HTML结构</h2><p><strong>六个面类似如下结构</strong></p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">h1</span>></span>3D魔方<span class="tag"></<span class="name">h1</span>></span></div><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"view"</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box"</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"red-surfaces"</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"one"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"two"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"three"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"four"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"five"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"six"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"seven"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"eight"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"nine"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></tbody></table></figure><h2 id="第二步:CSS初始化"><a href="#第二步:CSS初始化" class="headerlink" title="第二步:CSS初始化"></a>第二步:CSS初始化</h2><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">* {</div><div class="line"> <span class="attribute">margin</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">padding</span>: <span class="number">0px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-tag">body</span> {</div><div class="line"> <span class="attribute">min-height</span>: <span class="number">600px</span>;</div><div class="line"> <span class="attribute">height</span>: <span class="number">100%</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-tag">body</span> <span class="selector-tag">h1</span> {</div><div class="line"> <span class="attribute">margin-top</span>: <span class="number">50px</span>;</div><div class="line"> <span class="attribute">text-align</span>: center;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.view</span> {</div><div class="line"> <span class="attribute">margin</span>: -<span class="number">60px</span> auto;</div><div class="line"> <span class="attribute">width</span>: <span class="number">800px</span>;</div><div class="line"> <span class="attribute">height</span>: <span class="number">800px</span>;</div><div class="line"> <span class="attribute">position</span>: relative;</div><div class="line"> <span class="attribute">border-radius</span>: <span class="number">20px</span>;</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">scale</span>(0.7);</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="第三步:CSS实现魔方的各个面-外轮廓和内盒子"><a href="#第三步:CSS实现魔方的各个面-外轮廓和内盒子" class="headerlink" title="第三步:CSS实现魔方的各个面-外轮廓和内盒子"></a>第三步:CSS实现魔方的各个面-外轮廓和内盒子</h2><p><strong>外轮廓样式</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.red-surfaces</span>,</div><div class="line"><span class="selector-class">.blue-surfaces</span>,</div><div class="line"><span class="selector-class">.green-surfaces</span>,</div><div class="line"><span class="selector-class">.white-surfaces</span>,</div><div class="line"><span class="selector-class">.orange-surfaces</span>,</div><div class="line"><span class="selector-class">.yellow-surfaces</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">330px</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">330px</span>;</div><div class="line"> <span class="attribute">position</span>: absolute;</div><div class="line"> <span class="attribute">border-radius</span>: <span class="number">5px</span>;</div><div class="line"> <span class="attribute">top</span>: <span class="number">235px</span>;</div><div class="line"> <span class="attribute">left</span>: <span class="number">235px</span>;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>内盒子样式</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.red-surfaces</span>><span class="selector-tag">div</span>,</div><div class="line"><span class="selector-class">.blue-surfaces</span>><span class="selector-tag">div</span>,</div><div class="line"><span class="selector-class">.green-surfaces</span>><span class="selector-tag">div</span>,</div><div class="line"><span class="selector-class">.white-surfaces</span>><span class="selector-tag">div</span>,</div><div class="line"><span class="selector-class">.orange-surfaces</span>><span class="selector-tag">div</span>,</div><div class="line"><span class="selector-class">.yellow-surfaces</span>><span class="selector-tag">div</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">100px</span>;</div><div class="line"> <span class="attribute">display</span>: inline-block;</div><div class="line"> <span class="attribute">border</span>: <span class="number">5px</span> solid <span class="built_in">rgba</span>(170, 170, 170, 0.9);</div><div class="line"> <span class="attribute">position</span>: absolute;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>内盒子颜色 : 六面</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.red-surfaces</span>><span class="selector-tag">div</span> {</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(255, 0, 0, 0.8);</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>内盒子定位 :九个小块</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="selector-id">#one</span> {</div><div class="line"> <span class="attribute">left</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">top</span>: <span class="number">0px</span>;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="第四步:CSS3实现魔方表面的3D位置"><a href="#第四步:CSS3实现魔方表面的3D位置" class="headerlink" title="第四步:CSS3实现魔方表面的3D位置"></a>第四步:CSS3实现魔方表面的3D位置</h2><p><strong>六个表面不同角度设置</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.red-surfaces</span> {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateX</span>(-90deg) <span class="built_in">translateZ</span>(165px);</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="第五步:CSS3实现旋转"><a href="#第五步:CSS3实现旋转" class="headerlink" title="第五步:CSS3实现旋转"></a>第五步:CSS3实现旋转</h2><p><strong>keyframe定义 :animation</strong></p><ul><li>name规定需要绑定到选择器的keyframe名称</li><li>duration规定完成动画所花费的时间,以秒或毫秒计</li><li>timing-function规定动画的速度曲线</li><li>delay规定在动画开始之前的延迟</li><li>iteration-count规定动画应该播放的次数</li><li>direction规定是否应该轮流反向播放动画</li></ul><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.box</span>{</div><div class="line"> <span class="attribute">-webkit-animation</span>:BoxRotate <span class="number">3s</span> ease-in-out infinite;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>动画旋转基准 : transform-origin</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.box</span>{</div><div class="line"> <span class="attribute">-webkit-transform-origin</span>: <span class="number">400px</span> <span class="number">400px</span> <span class="number">200px</span>;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>3D实现:transform-style</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.box</span>{</div><div class="line"> <span class="attribute">-webkit-transform-style</span>: preserve-<span class="number">3</span>d;</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p><strong>keyframe定义旋转</strong></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">@-<span class="keyword">webkit</span>-<span class="keyword">keyframes</span> BoxRotate {</div><div class="line"> 16% {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateY</span>(-90deg) <span class="built_in">rotateZ</span>(135deg);</div><div class="line"> }</div><div class="line"> 33% {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateY</span>(-90deg) <span class="built_in">rotateX</span>(135deg);</div><div class="line"> }</div><div class="line"> 50% {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateY</span>(225deg) <span class="built_in">rotateZ</span>(135deg);</div><div class="line"> }</div><div class="line"> 66% {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateY</span>(135deg) <span class="built_in">rotateX</span>(135deg);</div><div class="line"> }</div><div class="line"> 83% {</div><div class="line"> <span class="attribute">-webkit-transform</span>: <span class="built_in">rotateX</span>(135deg);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></tbody></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>CSS3也可以实现js实现的动画,而且还减少资源消耗,要熟练掌握新特性。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="CSS3实现3D魔方"><a href="#CSS3实现3D魔方" class="headerlink" title="CSS3实现3D魔方"></a>CSS3实现3D魔方</h1><p><strong>实现思路</strong></p>
<ul>
<li><p>写出基础HTML框架</p>
</li>
<li><p>基本CSS样式,初始化</p>
</li>
<li><p>CSS实现魔方的各个面:外轮廓和内盒子</p>
</li>
<li><p>CSS3实现魔方表面的3D位置</p>
</li>
<li><p>CSS3实现旋转</p>
</li>
</ul>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="https://www.awebone.com/tags/CSS/"/>
</entry>
<entry>
<title>kali linux 安装指南</title>
<link href="https://www.awebone.com/posts/c1c013be/"/>
<id>https://www.awebone.com/posts/c1c013be/</id>
<published>2017-04-19T16:00:00.000Z</published>
<updated>2020-03-31T13:41:10.620Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="kali-linux-安装指南"><a href="#kali-linux-安装指南" class="headerlink" title="kali linux 安装指南"></a>kali linux 安装指南</h1><blockquote><p>Kali Linux是基于Debian的Linux发行版, 设计用于数字取证和渗透测试。Kali Linux预装了许多渗透测试软件,包括nmap (端口扫描器)、Wireshark (数据包分析器)、John the Ripper (密码破解器),以及Aircrack-ng (一应用于对无线局域网进行渗透测试的软件).用户可通过硬盘、live CD或live USB运行Kali Linux。Metasploit的Metasploit Framework支持Kali Linux,Metasploit一套针对远程主机进行开发和执行Exploit代码的工具。<br>Kali Linux既有32位和64位的镜像。可用于x86 指令集。同时还有基于ARM架构的镜像,可用于树莓派和三星的ARM Chromebook. –[百度百科]</p></blockquote><a id="more"></a><h2 id="安装步骤"><a href="#安装步骤" class="headerlink" title="安装步骤"></a>安装步骤</h2><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><p><a href="https://www.kali.org/downloads/" target="_blank" rel="external">kali linux 官网</a></p><h3 id="U盘刻录"><a href="#U盘刻录" class="headerlink" title="U盘刻录"></a>U盘刻录</h3><p>镜像刻录U盘工具:<code>Win32 Disk Imager</code></p><p>这个工具刻录的镜像比较完整,可直接用U盘启动,比软碟通要好。</p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><ul><li><p>刻录U盘后重启电脑,不需要用EasyBCD。</p></li><li><p>重启电脑后进入<code>bios</code>,选择U盘启动</p></li><li><p>进入镜像,选择<code>Graphical install</code>选项,当然选择install也是一样的</p></li><li><p>安装语言、地区、键盘</p></li><li><p>无法挂载光盘解决:拔下U盘再插上,选择是继续</p></li><li><p>网络设备固件缺失:直接选择否继续</p></li><li><p>设置主机名和密码:默认用户名:<code>root</code> 密码:<code>toor</code></p></li><li><p>磁盘分区(最重要一部分),这一部分是很重要的一步,一定要注意看清,选对,再操作。</p><ul><li>选择手动</li><li>选择我们准备好要安装kali的那个分区</li><li><p>分配分区:</p><ul><li><code>/boot</code>:启动分区</li><li><code>/</code> :根分区</li><li><code>/home</code>:用户目录</li><li><code>/tmp</code>:临时文件</li><li><code>/usr</code>:文件系统</li><li><code>/var</code>:可变数据目录</li><li><code>/opt</code>:附加应用程序</li><li><code>swap</code>:交换分区</li></ul><p>一般分<code>/boot、/、/home、swap</code></p><p>分区方案关键点:</p><p>大数据库一般要加大<code>/usr</code>挂载点</p><p>多用户、下载类、多存储文件等要加大<code>/home</code>挂载点</p><p>文件小,用户多要注意<code>/tmp</code>和<code>/var</code>挂载点大小</p></li><li>选择“分区设定结束并将修改写入磁盘”继续</li></ul></li><li><p>开始格式化并写入磁盘,这个过程可能有点长,请耐心等待</p></li><li><p>网络镜像</p></li><li><p>写入引导(很重要一步):一定选是,是个坑</p></li><li><p>安装完成</p></li></ul><h2 id="安装之后"><a href="#安装之后" class="headerlink" title="安装之后"></a>安装之后</h2><ul><li><p>更新软件源</p><p>修改<code>sources.list</code>文件:<code>/etc/apt/sources.list</code></p><p>然后选择添加适合自己较快的源(可自由选择)</p><p>保存之后:</p><p><code>apt-get update</code> #刷新系统</p><p><code>apt-get dist-upgrade</code> #安装更新</p></li><li><p>kali-linux安装中文输入法</p><p><code>apt-get install fcitx-table-wbpy ttf-wqy-microhei ttf-wqy-zenhei</code> #拼音五笔</p></li><li><p>安装gnome管理软件</p><p><code>apt-get install gnome-tweak-tool</code></p></li><li><p>安装新立德</p><p><code>apt-get install synaptic</code></p></li><li><p>安装解压缩软件</p><p><code>apt-get install file-roller</code></p></li><li><p>安装smplayer视频播放器</p><p><code>apt-get install smplayer</code></p></li><li><p>安装多窗口终端</p><p><code>apt-get install terminator</code></p></li><li><p>安装VMware和VirtualBox</p></li></ul><h2 id="使用及相关系统"><a href="#使用及相关系统" class="headerlink" title="使用及相关系统"></a>使用及相关系统</h2><p>渗透测试笔记:使用渗透工具进行测试</p><p><a href="">BackBox</a>:黑客工具箱</p><p><a href="">Parrot Security os</a>:本人用的最炫的一个系统,安装也简便,工具很强大,但是系统内部文件跟常规系统不太一样,适合对linux熟悉的人员使用</p><p><a href="">Cyborg Hawk</a>:工具最多的一个系统,但是全英文,不支持中文,对英语水平要求很高。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="kali-linux-安装指南"><a href="#kali-linux-安装指南" class="headerlink" title="kali linux 安装指南"></a>kali linux 安装指南</h1><blockquote>
<p>Kali Linux是基于Debian的Linux发行版, 设计用于数字取证和渗透测试。Kali Linux预装了许多渗透测试软件,包括nmap (端口扫描器)、Wireshark (数据包分析器)、John the Ripper (密码破解器),以及Aircrack-ng (一应用于对无线局域网进行渗透测试的软件).用户可通过硬盘、live CD或live USB运行Kali Linux。Metasploit的Metasploit Framework支持Kali Linux,Metasploit一套针对远程主机进行开发和执行Exploit代码的工具。<br>Kali Linux既有32位和64位的镜像。可用于x86 指令集。同时还有基于ARM架构的镜像,可用于树莓派和三星的ARM Chromebook. –[百度百科]</p>
</blockquote>
</summary>
<category term="Linux" scheme="https://www.awebone.com/categories/Linux/"/>
<category term="Linux" scheme="https://www.awebone.com/tags/Linux/"/>
<category term="kali" scheme="https://www.awebone.com/tags/kali/"/>
</entry>
<entry>
<title>Google Hack</title>
<link href="https://www.awebone.com/posts/bb07c3a7/"/>
<id>https://www.awebone.com/posts/bb07c3a7/</id>
<published>2017-03-23T16:00:00.000Z</published>
<updated>2020-03-31T13:15:59.141Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Google-Hack"><a href="#Google-Hack" class="headerlink" title="Google Hack"></a>Google Hack</h1><blockquote><p>这些命令在Google搜索引擎中才能使用</p></blockquote><h2 id="中文引号“-”"><a href="#中文引号“-”" class="headerlink" title="中文引号“ ”"></a>中文引号“ ”</h2><p>在搜索关键字时,加上中文的“ ”号,你就能精确的只搜“ ”里面的文字了。</p><h2 id="在搜索词后面加上“site-网站名”"><a href="#在搜索词后面加上“site-网站名”" class="headerlink" title="在搜索词后面加上“site:网站名”"></a>在搜索词后面加上“site:网站名”</h2><p>举个例子:就如搜索 <code>白帽 site:sina.com</code>,那么就能搜索在新浪(sina.com)这个域名下的,有关“白帽”的信息了。<br>搜索出的结果均为新浪网中,与白帽有关的网页</p><a id="more"></a><h2 id="“-”"><a href="#“-”" class="headerlink" title="“-”"></a>“-”</h2><p>就一个减号,在输入搜索词的后面,空格后加上一个减号。在减号后面输入你想过滤的东西,比如你想搜姚明,但又不想看他与篮球有关的东西,那么你只需要这样<code>姚明 -篮球</code>进行搜索就可以得出姚明与篮球无关的信息了。</p><h2 id="号"><a href="#号" class="headerlink" title="* 号"></a>* 号</h2><p>在搜索词前面加上该符号,就可以搜索出与<code>*</code>号后面相关的词语的内容,如你输入<code>*伟</code>,那么出来的结果都会是XX伟,而不会是伟XX的内容。</p><h2 id="filetype"><a href="#filetype" class="headerlink" title="filetype"></a>filetype</h2><p>爱在网上找资料的人都有很难找到想要的东西,要么名字对格式不对,要么格式对,内容不对。这里的<code>filetype</code>就可以准确的搜索出某个关键字下,你想要的文件名。如搜索<code>数学 filetype:pdf</code>,就会出来与数学有关的所有pdf文件。</p><h2 id="info-url"><a href="#info-url" class="headerlink" title="info:url"></a>info:url</h2><p>在搜索栏中输入这个,就会出来被搜索网址的所有信息。</p><h2 id="intitle-标题"><a href="#intitle-标题" class="headerlink" title="intitle:标题"></a>intitle:标题</h2><p>在搜索词前输入这个命令,那么就会搜出网页中是以搜索词为标题的网页。</p><h2 id="inurl-网址"><a href="#inurl-网址" class="headerlink" title="inurl:网址"></a>inurl:网址</h2><p>输入网址后,是在搜索的结果中,把包含了URL的结果页面返回(也就是在结果中找有多少是你的网址的内容),如:<code>inurl:baidu.com site:www.sina.com</code>,则会搜索出新浪网中所有包含了baidu.com 网址的网页。</p><h2 id="link-url"><a href="#link-url" class="headerlink" title="link:url"></a>link:url</h2><p>这个是独立使用的,输入这个之后,可以搜索出所有与这个网页有关联的网页。也就是我们平时进入网页后,可以在网页底部看到的合作网站。通过这个命令,我们可以不用进入网站就可以查出这个网站与那些网站合作了,明里暗里的都能看到哦。</p><h2 id="location:区域"><a href="#location:区域" class="headerlink" title="location:区域"></a>location:区域</h2><p>这个命令是为了精确区域而设计的,如你只想查深圳的女子大学的网页,那么就可以这样进行查找:<code>女子大学 location:ShenZhen</code>这样就会出来深圳区域所有的女子大学相关网页了,而不会把其它地区的女子大学的也搞过来。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="Google-Hack"><a href="#Google-Hack" class="headerlink" title="Google Hack"></a>Google Hack</h1><blockquote>
<p>这些命令在Google搜索引擎中才能使用</p>
</blockquote>
<h2 id="中文引号“-”"><a href="#中文引号“-”" class="headerlink" title="中文引号“ ”"></a>中文引号“ ”</h2><p>在搜索关键字时,加上中文的“ ”号,你就能精确的只搜“ ”里面的文字了。</p>
<h2 id="在搜索词后面加上“site-网站名”"><a href="#在搜索词后面加上“site-网站名”" class="headerlink" title="在搜索词后面加上“site:网站名”"></a>在搜索词后面加上“site:网站名”</h2><p>举个例子:就如搜索 <code>白帽 site:sina.com</code>,那么就能搜索在新浪(sina.com)这个域名下的,有关“白帽”的信息了。<br>搜索出的结果均为新浪网中,与白帽有关的网页</p>
</summary>
<category term="web" scheme="https://www.awebone.com/categories/web/"/>
<category term="搜索技巧" scheme="https://www.awebone.com/tags/%E6%90%9C%E7%B4%A2%E6%8A%80%E5%B7%A7/"/>
</entry>
<entry>
<title>CSS学习笔记</title>
<link href="https://www.awebone.com/posts/948e1c93/"/>
<id>https://www.awebone.com/posts/948e1c93/</id>
<published>2017-03-21T16:00:00.000Z</published>
<updated>2020-03-31T13:16:26.490Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="CSS学习笔记"><a href="#CSS学习笔记" class="headerlink" title="CSS学习笔记"></a>CSS学习笔记</h1><h2 id="CSS-Positioning-定位"><a href="#CSS-Positioning-定位" class="headerlink" title="CSS Positioning(定位)"></a>CSS Positioning(定位)</h2><p>CSS定位属性允许你为一个元素定位。它也可以将一个元素放在另一个元素后面,并指定一个元素的内容太大时,应该发生什么。元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法</p><a id="more"></a><h3 id="Static-定位"><a href="#Static-定位" class="headerlink" title="Static 定位"></a>Static 定位</h3><p>HTML元素的默认值,即没有定位,元素出现在正常的流中。</p><p>静态定位的元素不会受到<code>top, bottom, left, right</code>影响。</p><h3 id="Fixed-定位"><a href="#Fixed-定位" class="headerlink" title="Fixed 定位"></a>Fixed 定位</h3><p>元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。</p><p>Fixed定位使元素的位置与文档流无关,因此不占据空间。</p><p>Fixed定位的元素和其他元素重叠。</p><h3 id="Relative-定位"><a href="#Relative-定位" class="headerlink" title="Relative 定位"></a>Relative 定位</h3><p>相对定位元素的定位是相对其正常位置。</p><p>可以移动的相对定位元素的内容和相互重叠的元素,它原本所占的空间不会改变。相对定位元素经常被用来作为绝对定位元素的容器块。</p><h3 id="Absolute-定位"><a href="#Absolute-定位" class="headerlink" title="Absolute 定位"></a>Absolute 定位</h3><p>绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于<code><html></code>。</p><p>Absolutely定位使元素的位置与文档流无关,因此不占据空间。</p><p>Absolutely定位的元素和其他元素重叠。</p><h2 id="重叠的元素"><a href="#重叠的元素" class="headerlink" title="重叠的元素"></a>重叠的元素</h2><p>元素的定位与文档流无关,所以它们可以覆盖页面上的其它元素。</p><p>z-index属性指定了一个元素的堆叠顺序(哪个元素应该放在前面,或后面),一个元素可以有正数或负数的堆叠顺序。</p><h2 id="CSS-Float-浮动"><a href="#CSS-Float-浮动" class="headerlink" title="CSS Float(浮动)"></a>CSS Float(浮动)</h2><p>CSS 的Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列。<br>Float(浮动),往往是用于图像,但它在布局时一样非常有用。</p><h3 id="元素怎样浮动"><a href="#元素怎样浮动" class="headerlink" title="元素怎样浮动"></a>元素怎样浮动</h3><p>元素的水平方向浮动,意味着元素只能左右移动而不能上下移动。</p><p>一个浮动元素会尽量向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。</p><p>浮动元素之后的元素将围绕它。</p><p>浮动元素之前的元素将不会受到影响。</p><h3 id="清除浮动-使用-clear"><a href="#清除浮动-使用-clear" class="headerlink" title="清除浮动 - 使用 clear"></a>清除浮动 - 使用 clear</h3><p>元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用 clear 属性。<br>clear 属性指定元素两侧不能出现浮动元素。</p><h2 id="常见CSS布局"><a href="#常见CSS布局" class="headerlink" title="常见CSS布局"></a>常见CSS布局</h2><p>双飞翼布局</p><p>圣杯布局</p><p>流式布局</p><h2 id="CSS3-模块"><a href="#CSS3-模块" class="headerlink" title="CSS3 模块"></a>CSS3 模块</h2><p>CSS3被拆分为”模块”。旧规范已拆分成小块,还增加了新的。</p><p>一些最重要CSS3模块如下:</p><ul><li>选择器</li><li>盒模型</li><li>背景和边框</li><li>文字特效</li><li>2D/3D转换</li><li>动画</li><li>多列布局</li><li>用户界面</li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="CSS学习笔记"><a href="#CSS学习笔记" class="headerlink" title="CSS学习笔记"></a>CSS学习笔记</h1><h2 id="CSS-Positioning-定位"><a href="#CSS-Positioning-定位" class="headerlink" title="CSS Positioning(定位)"></a>CSS Positioning(定位)</h2><p>CSS定位属性允许你为一个元素定位。它也可以将一个元素放在另一个元素后面,并指定一个元素的内容太大时,应该发生什么。元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法</p>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="https://www.awebone.com/tags/CSS/"/>
</entry>
<entry>
<title>HTML学习笔记</title>
<link href="https://www.awebone.com/posts/13b6b7c2/"/>
<id>https://www.awebone.com/posts/13b6b7c2/</id>
<published>2017-03-20T16:00:00.000Z</published>
<updated>2020-03-31T13:40:40.805Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="HTML学习笔记"><a href="#HTML学习笔记" class="headerlink" title="HTML学习笔记"></a>HTML学习笔记</h1><h2 id="HTML结构及常用元素"><a href="#HTML结构及常用元素" class="headerlink" title="HTML结构及常用元素"></a>HTML结构及常用元素</h2><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="meta"><!DOCTYPE html></span></div><div class="line"><span class="tag"><<span class="name">html</span>></span></div><div class="line"><span class="tag"><<span class="name">head</span>></span></div><div class="line"><span class="tag"><<span class="name">title</span>></span>文档标题<span class="tag"></<span class="name">title</span>></span></div><div class="line"><span class="tag"></<span class="name">head</span>></span></div><div class="line"><span class="tag"><<span class="name">body</span>></span></div><div class="line">可见文本...</div><div class="line"><span class="tag"></<span class="name">body</span>></span></div><div class="line"><span class="tag"></<span class="name">html</span>></span></div></pre></td></tr></tbody></table></figure><a id="more"></a><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">h1</span>></span>最大的标题<span class="tag"></<span class="name">h1</span>></span></div><div class="line"><span class="tag"><<span class="name">h2</span>></span> . . . <span class="tag"></<span class="name">h2</span>></span></div><div class="line"><span class="tag"><<span class="name">h3</span>></span> . . . <span class="tag"></<span class="name">h3</span>></span></div><div class="line"><span class="tag"><<span class="name">h4</span>></span> . . . <span class="tag"></<span class="name">h4</span>></span></div><div class="line"><span class="tag"><<span class="name">h5</span>></span> . . . <span class="tag"></<span class="name">h5</span>></span></div><div class="line"><span class="tag"><<span class="name">h6</span>></span>最小的标题<span class="tag"></<span class="name">h6</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">p</span>></span>这是一个段落。<span class="tag"></<span class="name">p</span>></span></div><div class="line"><span class="tag"><<span class="name">br</span>></span> (换行)</div><div class="line"><span class="tag"><<span class="name">hr</span>></span> (水平线)</div><div class="line"><span class="comment"><!-- 这是注释 --></span></div><div class="line"><span class="tag"><<span class="name">b</span>></span>粗体文本<span class="tag"></<span class="name">b</span>></span></div><div class="line"><span class="tag"><<span class="name">code</span>></span>计算机代码<span class="tag"></<span class="name">code</span>></span></div><div class="line"><span class="tag"><<span class="name">em</span>></span>强调文本<span class="tag"></<span class="name">em</span>></span></div><div class="line"><span class="tag"><<span class="name">i</span>></span>斜体文本<span class="tag"></<span class="name">i</span>></span></div><div class="line"><span class="tag"><<span class="name">kbd</span>></span>键盘输入<span class="tag"></<span class="name">kbd</span>></span></div><div class="line"><span class="tag"><<span class="name">pre</span>></span>预格式化文本<span class="tag"></<span class="name">pre</span>></span></div><div class="line"><span class="tag"><<span class="name">small</span>></span>更小的文本<span class="tag"></<span class="name">small</span>></span></div><div class="line"><span class="tag"><<span class="name">strong</span>></span>重要的文本<span class="tag"></<span class="name">strong</span>></span></div><div class="line"><span class="tag"><<span class="name">abbr</span>></span> (缩写)</div><div class="line"><span class="tag"><<span class="name">address</span>></span> (联系信息)</div><div class="line"><span class="tag"><<span class="name">bdo</span>></span> (文字方向)</div><div class="line"><span class="tag"><<span class="name">blockquote</span>></span> (从另一个源引用的部分)</div><div class="line"><span class="tag"><<span class="name">cite</span>></span> (工作的名称)</div><div class="line"><span class="tag"><<span class="name">del</span>></span> (删除的文本)</div><div class="line"><span class="tag"><<span class="name">ins</span>></span> (插入的文本)</div><div class="line"><span class="tag"><<span class="name">sub</span>></span> (下标文本)</div><div class="line"><span class="tag"><<span class="name">sup</span>></span> (上标文本)</div><div class="line"></div><div class="line">普通的链接:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://www.example.com/"</span>></span>链接文本<span class="tag"></<span class="name">a</span>></span></div><div class="line">图像链接: <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://www.example.com/"</span>></span><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"URL"</span> <span class="attr">alt</span>=<span class="string">"替换文本"</span>></span><span class="tag"></<span class="name">a</span>></span></div><div class="line">邮件链接: <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"mailto:webmaster@example.com"</span>></span>发送e-mail<span class="tag"></<span class="name">a</span>></span></div><div class="line"></div><div class="line">书签:</div><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">id</span>=<span class="string">"tips"</span>></span>提示部分<span class="tag"></<span class="name">a</span>></span></div><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#tips"</span>></span>跳到提示部分<span class="tag"></<span class="name">a</span>></span></div><div class="line"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"URL"</span> <span class="attr">alt</span>=<span class="string">"替换文本"</span> <span class="attr">height</span>=<span class="string">"42"</span> <span class="attr">width</span>=<span class="string">"42"</span>></span></div></pre></td></tr></tbody></table></figure><h2 id="HTML实例代码"><a href="#HTML实例代码" class="headerlink" title="HTML实例代码"></a>HTML实例代码</h2><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">div</span>></span>文档中的块级元素<span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"><<span class="name">span</span>></span>文档中的内联元素<span class="tag"></<span class="name">span</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ul</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span>></span>项目<span class="tag"></<span class="name">li</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span>></span>项目<span class="tag"></<span class="name">li</span>></span></div><div class="line"><span class="tag"></<span class="name">ul</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ol</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span>></span>第一项<span class="tag"></<span class="name">li</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span>></span>第二项<span class="tag"></<span class="name">li</span>></span></div><div class="line"><span class="tag"></<span class="name">ol</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">table</span> <span class="attr">border</span>=<span class="string">"1"</span>></span></div><div class="line"> <span class="tag"><<span class="name">tr</span>></span></div><div class="line"> <span class="tag"><<span class="name">th</span>></span>表格标题<span class="tag"></<span class="name">th</span>></span></div><div class="line"> <span class="tag"><<span class="name">th</span>></span>表格标题<span class="tag"></<span class="name">th</span>></span></div><div class="line"> <span class="tag"></<span class="name">tr</span>></span></div><div class="line"> <span class="tag"><<span class="name">tr</span>></span></div><div class="line"> <span class="tag"><<span class="name">td</span>></span>表格数据<span class="tag"></<span class="name">td</span>></span></div><div class="line"> <span class="tag"><<span class="name">td</span>></span>表格数据<span class="tag"></<span class="name">td</span>></span></div><div class="line"> <span class="tag"></<span class="name">tr</span>></span></div><div class="line"><span class="tag"></<span class="name">table</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">iframe</span> <span class="attr">src</span>=<span class="string">"demo_iframe.htm"</span>></span><span class="tag"></<span class="name">iframe</span>></span></div></pre></td></tr></tbody></table></figure><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">form</span> <span class="attr">action</span>=<span class="string">"demo_form.php"</span> <span class="attr">method</span>=<span class="string">"post/get"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"email"</span> <span class="attr">size</span>=<span class="string">"40"</span> <span class="attr">maxlength</span>=<span class="string">"50"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"password"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> <span class="attr">checked</span>=<span class="string">"checked"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"radio"</span> <span class="attr">checked</span>=<span class="string">"checked"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">value</span>=<span class="string">"Send"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"reset"</span>></span></div><div class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"hidden"</span>></span></div><div class="line"><span class="tag"><<span class="name">select</span>></span></div><div class="line"><span class="tag"><<span class="name">option</span>></span>苹果<span class="tag"></<span class="name">option</span>></span></div><div class="line"><span class="tag"><<span class="name">option</span> <span class="attr">selected</span>=<span class="string">"selected"</span>></span>香蕉<span class="tag"></<span class="name">option</span>></span></div><div class="line"><span class="tag"><<span class="name">option</span>></span>樱桃<span class="tag"></<span class="name">option</span>></span></div><div class="line"><span class="tag"></<span class="name">select</span>></span></div><div class="line"><span class="tag"><<span class="name">textarea</span> <span class="attr">name</span>=<span class="string">"comment"</span> <span class="attr">rows</span>=<span class="string">"60"</span> <span class="attr">cols</span>=<span class="string">"20"</span>></span><span class="tag"></<span class="name">textarea</span>></span></div><div class="line"><span class="tag"></<span class="name">form</span>></span></div></pre></td></tr></tbody></table></figure><h2 id="HTML5-中的一些有趣的新特性"><a href="#HTML5-中的一些有趣的新特性" class="headerlink" title="HTML5 中的一些有趣的新特性"></a>HTML5 中的一些有趣的新特性</h2><p>用于绘画的 <code>canvas</code> 元素</p><p>用于媒介回放的 <code>video</code> 和 <code>audio</code> 元素</p><p>对本地离线存储的更好的支持</p><p>新的特殊内容元素,比如 <code>article、footer、header、nav、section</code></p><p>新的表单控件,比如 <code>calendar、date、time、email、url、search</code></p><p>IE9 以下版本浏览器兼容HTML5的方法:使用菜鸟教程的静态资源的html5shiv包<br></p><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"><!--[if lt IE9]></span></div><div class="line"><script src="http://cdn.static.runoob.com/libs/html5shiv/3.7/html5shiv.min.js"></script></div><div class="line"><![endif]--></div></pre></td></tr></tbody></table></figure><p></p><p>载入后,初始化新标签的CSS:<br></p><figure class="highlight css"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">article</span>,<span class="selector-tag">aside</span>,<span class="selector-tag">dialog</span>,<span class="selector-tag">footer</span>,<span class="selector-tag">header</span>,<span class="selector-tag">section</span>,<span class="selector-tag">footer</span>,<span class="selector-tag">nav</span>,<span class="selector-tag">figure</span>,<span class="selector-tag">menu</span>{</div><div class="line"> <span class="attribute">display</span>:block</div><div class="line">}</div></pre></td></tr></tbody></table></figure><p></p><p>html5shiv.js 引用代码必须放在<code><head></code>元素中,因为 IE 浏览器在解析 HTML5 新元素时需要先加载该文件。</p><h2 id="字符实体"><a href="#字符实体" class="headerlink" title="字符实体"></a>字符实体</h2><p>HTML 中的预留字符必须被替换为字符实体。</p><p>一些在键盘上找不到的字符也可以使用字符实体来替换。</p><p>HTML 中的常用字符实体是:</p><ul><li>不间断空格 <code>&nbsp;</code></li><li>大于 <code>&rt</code></li><li>小于 <code>&lt;</code></li><li>引号 <code>&quot;</code></li><li>版权 ©<code>`&#169;</code></li><li>注册商标 <code>&reg;</code> <code>&#174;</code></li><li>商标 <code>&trade;</code></li></ul><h2 id="URL-统一资源定位器"><a href="#URL-统一资源定位器" class="headerlink" title="URL - 统一资源定位器"></a>URL - 统一资源定位器</h2><p>Web浏览器通过URL从Web服务器请求页面。当您点击html页面中的某个链接时,对应的 <code><a></code>标签指向万维网上的一个地址。</p><p>一个统一资源定位器(URL) 用于定位万维网上的文档。</p><p><strong>语法规则:</strong></p><p><code>scheme://host.domain:port/path/filename</code></p><p><strong>说明:</strong></p><ul><li>scheme - 定义因特网服务的类型。最常见的类型是 http</li><li>host - 定义域主机(http 的默认主机是 www)</li><li>domain - 定义因特网域名,比如 runoob.com</li><li>:port - 定义主机上的端口号(http 的默认端口号是 80)</li><li>path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。</li><li>filename - 定义文档/资源的名称</li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="HTML学习笔记"><a href="#HTML学习笔记" class="headerlink" title="HTML学习笔记"></a>HTML学习笔记</h1><h2 id="HTML结构及常用元素"><a href="#HTML结构及常用元素" class="headerlink" title="HTML结构及常用元素"></a>HTML结构及常用元素</h2><figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>文档标题<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">可见文本...</div><div class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></tbody></table></figure>
</summary>
<category term="web前端" scheme="https://www.awebone.com/categories/web%E5%89%8D%E7%AB%AF/"/>
<category term="HTML" scheme="https://www.awebone.com/tags/HTML/"/>
</entry>
<entry>
<title>SEO学习笔记</title>
<link href="https://www.awebone.com/posts/6021eb27/"/>
<id>https://www.awebone.com/posts/6021eb27/</id>
<published>2017-03-19T16:00:00.000Z</published>
<updated>2020-03-31T13:42:28.370Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="SEO学习笔记"><a href="#SEO学习笔记" class="headerlink" title="SEO学习笔记"></a>SEO学习笔记</h1><blockquote><p>搜索引擎工作原理</p></blockquote><h2 id="SEO简介:"><a href="#SEO简介:" class="headerlink" title="SEO简介:"></a>SEO简介:</h2><ol><li>Search Engine Optimization 搜索引擎优化</li><li>白帽SEO</li><li>灰帽SEO</li></ol><h2 id="白帽SEO(内容上的SEO):"><a href="#白帽SEO(内容上的SEO):" class="headerlink" title="白帽SEO(内容上的SEO):"></a>白帽SEO(内容上的SEO):</h2><ol><li>网站标题、关键字、描述</li><li>网站内容优化</li><li>Robot.txt文件</li><li>网站地图</li><li>增加外链引用</li></ol><a id="more"></a><h2 id="SEO注意要点:"><a href="#SEO注意要点:" class="headerlink" title="SEO注意要点:"></a>SEO注意要点:</h2><ul><li><p>结构布局优化:用扁平化结构(层次结构超过三层小蜘蛛就不愿意爬了)</p></li><li><p>控制首页链接数量(中小网站100以内,页面导航、底部导航、锚文字链接等)</p></li><li><p>扁平化的目录层次(小蜘蛛跳转3次可以到达网站内任何一个内页,网站的设计主页、栏目、内容页,不要用纵线性的结构)</p></li><li><p>导航seo优化(头部、底部、内容部分,主导航、副导航、分类导航,尽量用文字,面包屑导航,在每个网站上留下面包屑,使用户可以了解网站组织形式,放于正文的左上方)</p></li><li><p>内容页面的布局细节</p><ul><li>左面正文,右面热门文章、相关文章,下面是版权信息及链接,栏目排布:首页123456789下拉选择最赞)</li></ul></li><li><p>网站的加载速度会影响小蜘蛛的爬行,页面最好不要超过100k</p></li><li><p>网页代码优化(语义化代码)</p><ul><li>title标题:强调重点</li><li>meta keywords关键词:列举几个关键词/简洁高效词语</li><li>meta description网页描述:高度概括网页的内容</li><li>以上信息不要堆积、重复</li></ul></li></ul><h2 id="有利搜索引擎"><a href="#有利搜索引擎" class="headerlink" title="有利搜索引擎"></a>有利搜索引擎</h2><ol><li><p>a:访问外部链接时要加上</p><figure class="highlight plain"><figcaption><span>title 说明</span></figcaption><table><tbody><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">2. h1:搜索引擎外认为 h1 最重要,使用 css 调整,网页正文标题用 h1,副标题用 h2,其他不要乱用 h 标签</div><div class="line"></div><div class="line">3. br 用于文本间的换行,用在 p 内,也可以用 ```<p><br/></p> ```表示空行</div><div class="line"></div><div class="line">4. caption:表格标题</div><div class="line"></div><div class="line">5. img:使用 title、alt 说明</div><div class="line"></div><div class="line">6. ```<strong><em>```表示强调,```<em>```的权重仅次于```<strong>```,如果只想表示加粗斜体,建议使用```<b><i>```,表示强调则使用```<strong><em></div></pre></td></tr></tbody></table></figure><p></p></li><li><p>重要内容 HTML 代码放在最前面(使用 css 改变布局)</p></li><li><p>重要内容不要用 JS 输出(搜索引擎看不懂 JS)</p></li><li><p>尽量少使用 iframe 框架(搜索引擎不喜欢)</p></li><li><p>谨慎使用<code>display:none</code>(搜索引擎会过滤掉其内容,设置 z-index/text-index 代替)</p></li><li><p>精简代码</p></li></ol><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="SEO学习笔记"><a href="#SEO学习笔记" class="headerlink" title="SEO学习笔记"></a>SEO学习笔记</h1><blockquote>
<p>搜索引擎工作原理</p>
</blockquote>
<h2 id="SEO简介:"><a href="#SEO简介:" class="headerlink" title="SEO简介:"></a>SEO简介:</h2><ol>
<li>Search Engine Optimization 搜索引擎优化</li>
<li>白帽SEO</li>
<li>灰帽SEO</li>
</ol>
<h2 id="白帽SEO(内容上的SEO):"><a href="#白帽SEO(内容上的SEO):" class="headerlink" title="白帽SEO(内容上的SEO):"></a>白帽SEO(内容上的SEO):</h2><ol>
<li>网站标题、关键字、描述</li>
<li>网站内容优化</li>
<li>Robot.txt文件</li>
<li>网站地图</li>
<li>增加外链引用</li>
</ol>
</summary>
<category term="web" scheme="https://www.awebone.com/categories/web/"/>
<category term="seo" scheme="https://www.awebone.com/tags/seo/"/>
</entry>
<entry>
<title>提升效率</title>
<link href="https://www.awebone.com/posts/8786024c/"/>
<id>https://www.awebone.com/posts/8786024c/</id>
<published>2017-03-18T16:00:00.000Z</published>
<updated>2020-03-31T13:41:35.722Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="提升效率"><a href="#提升效率" class="headerlink" title="提升效率"></a>提升效率</h1><blockquote><p>在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。</p></blockquote><h2 id="必须学会说“不”"><a href="#必须学会说“不”" class="headerlink" title="必须学会说“不”"></a>必须学会说“不”</h2><p>说“不”其实是个非常艰难的事情,可是如果不说no,那么就很难专心地应对真正重要的任务。因为有太多看起来不错的机会、看上去不能拒绝的要求、事成后有利的图景,以及无法拒绝的人情世故,诱惑着你答应下来。</p><p>其实工作越久,你就越会发现,真正的牛人,往往就牛在敢于放弃上。所谓的战略化决策,不仅仅是指战略高度的选择,也指战略高度的放弃。刚开始放弃的时候会很难受,这是多年形成的习惯和求全责备的心态发出的尖叫和抗议。可是时间久了才发现:不重要的事情真做不完也不会死,倒是重要的事情老拖着不做往往会后果比较严重。</p><a id="more"></a><h2 id="必须学会说yes"><a href="#必须学会说yes" class="headerlink" title="必须学会说yes"></a>必须学会说yes</h2><p>对我而言,如果想要找时间完成真正重要的事情,那么就先答应下来,再商量个相对宽裕的时间。将这些定下来之后,我总能想出方法,排除万难去实践。</p><p>无论是写小说、开公众号、参加考试,都可以遵循这个套路。牺牲掉部分娱乐、睡眠、社交,甚至是和家人团聚的时间,会非常适合短期内的明确目标,并督促你用冲刺的方式完成。</p><p>如果一件事情并不重要,那么就明确地拒绝;如果很重要,就大胆地接受。你不会因为说“不”损失多少,也不会因为应承去做却没有做好而损失很多。真正的损失是在我们说“这事儿很好,我再想想”中发生的。</p><h2 id="金钱换时间"><a href="#金钱换时间" class="headerlink" title="金钱换时间"></a>金钱换时间</h2><p>以前没有孩子的时候,我习惯利用整块时间写作,写作进入状态也非常缓慢,必须要在阳光充足的某个角落坐下,泡杯咖啡,看看新闻,再慢慢进入状态。</p><p>现在可用的业余时间往往是零散的,如果不能抓住零散时间进行思考和打草稿,那就更没有时间了。为了能更好地抓住这些碎片时间,我添置了更多的电子设备,例如静音且无须插电源的平板电脑,它能让我更好地利用孩子入睡后的时间。再比如我打破了从前不下载App的习惯,安装了多个阅读、记录、拍照笔记类的App,方便自己在零碎时间里能随时把读到的、想到的、看到的、诱发灵感的材料都尽快地收纳进来。</p><p>找到时间后,就是筹划和管理时间了。</p><h2 id="关掉提醒,高效专注地工作"><a href="#关掉提醒,高效专注地工作" class="headerlink" title="关掉提醒,高效专注地工作"></a>关掉提醒,高效专注地工作</h2><p>要想工作有效,就必须运用整块的时间。如果将时间分割开来零星使用,纵然时间总和相同,但其效果与整块运用时间的效果却差距很大。比如我以前工作时常要写一些措辞讲究的英文邮件,如果能够聚精会神地写,再加上润色,十几分钟就能完成。可是我总会忍不住一边写一边去看看什么人又说了什么话,有时还会因为查某个单词去逛下红迪网。</p><p>后来实在忙起来了,任凭各种新信息提醒也不去查看,等到某个任务告一段落,再统一查看和回复,既保证了效率,又不至于错过什么。仅这一项小小的改变,就大大提高了我的工作效率。</p><h2 id="减少选项,设置优先级"><a href="#减少选项,设置优先级" class="headerlink" title="减少选项,设置优先级"></a>减少选项,设置优先级</h2><p>选项越少,时间越多。一个比较经典的时间管理方法是:每天只选择1~3件事情去做,并辅以不懈地追求。你的本能不会喜欢这样的限制,可是这种方法有利于排列真正重要的事情,比起事无巨细地齐头并进,能让工作更为出色。</p><h2 id="提前把你想到的写下来"><a href="#提前把你想到的写下来" class="headerlink" title="提前把你想到的写下来"></a>提前把你想到的写下来</h2><p>当事情一旦多了杂了,脑子就明显不够用。我经常发现,哪怕是小事,如果写下来就会遵守;不写,无论在脑子里想多久,一被打扰就会忘掉。提前计划的目的其实不是为了“计划”,而是为了更重视时间的流向,知道时间都花到哪里去了。</p><p>如果不是很清晰地知道要做什么,就容易碰到什么是什么。于是哪件事情先找上来就先处理了,就好比我特别反感邮箱,因为邮件不停地进来,叮的一声响。只要邮箱的叮声不关,我就永远干不了该干的事情,会一直挂在邮箱上回复邮件,而且要一会儿回邮件,一会儿写报告,一会儿又查数据。数据查到一半叮的一声邮件又进来了,说到了另一件事,再去查……忙了一上午,几件重要的大事却一件都没干。</p><p>先把所有需要完成的事列出来,然后对大任务进行分解,分解成小一些的子任务,再对任务进行排序。排序时最艰难的步骤就是决定放弃或者推迟哪些东西。</p><h2 id="找到适合自己的好方法"><a href="#找到适合自己的好方法" class="headerlink" title="找到适合自己的好方法"></a>找到适合自己的好方法</h2><p>开始时间管理的时候,大家都会热衷于搜罗和学习各种方法。比如有一种著名的战拖策略叫作“吃掉那只青蛙”,鼓励大家给最重要、最困难的任务以第一优先权。但是我在实践之后,却发现这个方法极其不适合我。因为如果一上来就强迫自己完成最艰巨的任务,我反而会容易知难而退,会造成各种拖延。所以我摸索出的合适自己的方法是先完成最简单、最有兴趣的工作,通过这些初级工作渐入佳境,等效率上来了,再去啃“坚硬的骨头”。</p><p>说到这里,时间管理却还不能结束。桥本和彦曾经说过,“没有体现结果的时间管理就不能称之为时间管理”,因此定期对时间管理的成就和不足之处进行反思,就有非常重要的意义。</p><p>坚持时间管理最大的挑战就在于:即便你用最高科技的工具,按照最合理的科学方法、符合生物钟的方法规划好了时间,然后恪守,一天下来有很大的收获,你的内心也在呼唤你歪倒在沙发上刷手机、追美剧、和朋友瞎聊。</p><p>为了战胜无时不在的诱惑,就需要时不时地重温一下目标,配合着各种短期、中期、长期的目标,时间管理上也应相应配合着进行松弛有度的分布。任何时间管理和战拖秘诀都离不开恒心,但是生活必须要张弛有度。</p><p>如果是学生为了考GRE,那么两个月的短期突击式的冲刺,要比断断续续地复习一年有效;而大考完毕,可以有一小段时间让大脑放松下,以便进入下一阶段的目标。</p><p>一个人如果长期无目标地疲劳战斗,那么时间管理便会沦为空谈,你依旧会身心俱疲且内心无比迷茫,那样的话还不如好好歇着。</p><p>当然,如果把时间管理放到整个人生来看,有些人喜欢有计划、高产高效的生活,也有人喜欢随性自由的节奏。这些都没有问题,你尽可以按自己的喜好选择自己喜欢的方式。不过要记住,每种选择都意味着相应的放弃,只要回过头时不会患得患失就好。</p><p>对很多人而言,时间管理也是一种成就。他们对时间管理的追求,就是对成就感的追求,这也是他们进行时间管理的最大动力。</p><p>如果是这种情况,那么拥有一个能完成后打钩的to-dolist(待办事项列表)或者任务工作本、相关任务管理App,让这种成就可视化,就是很好的选择。</p><p>对我个人而言,时间管理的最大成功,不是达成了什么了不起的大成就,而是让自己能更明晰时间的去向、对事物的价值度有所衡量,并通过“管理时间”这一具体行动,让自己不再盲目焦虑。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="提升效率"><a href="#提升效率" class="headerlink" title="提升效率"></a>提升效率</h1><blockquote>
<p>在前进的路上,放弃那些次要的、可有可无的东西,获取真正重要、有意义的价值,让自己更加认同自己的付出和努力方向,这才是时间管理的本质和最大意义所在。</p>
</blockquote>
<h2 id="必须学会说“不”"><a href="#必须学会说“不”" class="headerlink" title="必须学会说“不”"></a>必须学会说“不”</h2><p>说“不”其实是个非常艰难的事情,可是如果不说no,那么就很难专心地应对真正重要的任务。因为有太多看起来不错的机会、看上去不能拒绝的要求、事成后有利的图景,以及无法拒绝的人情世故,诱惑着你答应下来。</p>
<p>其实工作越久,你就越会发现,真正的牛人,往往就牛在敢于放弃上。所谓的战略化决策,不仅仅是指战略高度的选择,也指战略高度的放弃。刚开始放弃的时候会很难受,这是多年形成的习惯和求全责备的心态发出的尖叫和抗议。可是时间久了才发现:不重要的事情真做不完也不会死,倒是重要的事情老拖着不做往往会后果比较严重。</p>
</summary>
<category term="方法论" scheme="https://www.awebone.com/categories/%E6%96%B9%E6%B3%95%E8%AE%BA/"/>
<category term="方法论" scheme="https://www.awebone.com/tags/%E6%96%B9%E6%B3%95%E8%AE%BA/"/>
</entry>
<entry>
<title>学习新技术建议</title>
<link href="https://www.awebone.com/posts/a5b005af/"/>
<id>https://www.awebone.com/posts/a5b005af/</id>
<published>2017-03-08T16:00:00.000Z</published>
<updated>2020-03-31T13:41:18.365Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="学习新技术建议"><a href="#学习新技术建议" class="headerlink" title="学习新技术建议"></a>学习新技术建议</h1><blockquote><p>我们生活在一个振奋人心的时代。我们可以越来越方便廉价地获得大量学习资源。这些资源的传播载体由最初的教室被变成了博客,技术论坛等。坐拥如此众多的学习资源,我们没有任何理由不去好好利用。随之而来的问题便是如何在这知识的海洋中选择自己的前进方向。<br>尽管我的建议主要涉及的是软件开发方面,但是这些原则在其他领域也同样适用。</p></blockquote><a id="more"></a><h2 id="克服惯性"><a href="#克服惯性" class="headerlink" title="克服惯性"></a>克服惯性</h2><p>万事开头难,克服惯性是学习新技术的第一步。举个日常生活中惯性存在的简单栗子,当我们看电视的时候会因为遥控器不在身边而懒得换台。幸运的是有很多的小技巧可以调动我们的积极性,帮助我们克服惯性。对于我来说,微习惯是一个很好用的小技巧。与其被手头的任务吓到,不如将任务细分为一个个具体的微任务,然后挑选其中的一个开始做起。就“拿到遥控器”这个例子来说,首先扭动你的脚趾,向前伸出,然后推动整个人离开沙发。下一步,身体滑到地上,用脚拿到遥控器,然后起身。通过完成一个个的微任务,你会发现自己克服了惯性,并且这项任务不再显得难以完成。这个方法可以被应用到学习新技能的过程中。关键就是将大块任务细分为微任务。</p><h2 id="关注大牛"><a href="#关注大牛" class="headerlink" title="关注大牛"></a>关注大牛</h2><p>学习新技能的第一步是明确要学什么。它可以是任何你有激情去学,并且想深入学习的一些东西。这种原始的学习欲望非常重要,这种欲望可以在你的学习低潮期给你提供动力。你想学的或许是一门新的编程语言、应用框架或者是新的工具,一旦你确定了想要的是什么,就立刻去收集相应的优秀群体所做的一些优质的工作成果。这些可以从YouTube、Vimeo、HackerNews、各种博客,甚至是你的微博好友那里获取。关注别人做了些什么可以给你强大的信心,让你觉得 “You can do it, too!”</p><h2 id="建立知识网"><a href="#建立知识网" class="headerlink" title="建立知识网"></a>建立知识网</h2><p>当你对自己要学习的东西建立了信心之后,接下来要做的就是做一块海绵,然后开始疯狂地吸收知识。从Google搜索关键词“beginner tutorials”开始吧,搜索一些跟你要学习的知识相关的入门教程。如你所知,Nettuts+上面有成千上百的各种教程供你选择,StackOverflow上面也有很多学习资源。此外,Quora也是一些不错的选择。通过浏览这些网上的资源之后,如果想要集中精力学习某一方面,这时就需要阅读一些相关的书籍了,个人推荐在Amazon上面寻找一些评分较高的专业书籍来提高自己。</p><h2 id="多听多看"><a href="#多听多看" class="headerlink" title="多听多看"></a>多听多看</h2><p>随着你对技术的深入挖掘,你可能会想利用更多其他形式的学习资料,比如podcasts,screencasts等等。我的建议是多用 iTunesU,这上面有很多很专业的知识可以让你对于特定的领域进行深入的探索。</p><p>可以看一些免费的会议视频材料,比如YouTube上面的Google IO,以及Confreaks!</p><h2 id="行动起来"><a href="#行动起来" class="headerlink" title="行动起来"></a>行动起来</h2><p>现在你已经看了一波又一波的教程以及视频资料,并且对于想学的技术已经有了一个相当深入的了解,接下来做些什么呢?没错,是时候理论联系实际了,实践是检验真理的唯一标准。</p><p>用你所掌握的技术做一个个人的小项目,设计一些简单的功能并且实现他们。毫无疑问,你会遇到很多的绊脚石,当遇到它们的时候,在StackOverflow或者Google上面搜索之,解决之。你已经踏上一条成为某一领域专家的旅程,遇到的困难挫折越多,你会变得越睿智。有句老话说得好,“专家是犯错最多的人”,这意味着他们尝试了很多疯狂的事情来探索这门技术的极限,最后,对于这门技术是如何运作的就可以知根知底。拥有这种洞察力之后,他们便可以随心所欲的运用这项技术去按照自己的意愿完成想做的事情(当然,是做好的事情)。</p><h2 id="写博客"><a href="#写博客" class="headerlink" title="写博客"></a>写博客</h2><p>在你进行你的探险之旅的时候,实时记录下你的成长以及犯下的错误大有裨益。在技术领域,博客是最简单易得并且受欢迎的表达载体。当你准备落笔的时候,你会强迫自己整理思路,并且对积累下来的零散的知识片段进行结构梳理。说不定,通过互联网的分享,你的经历和分享会给别人的成长带来帮助。</p><p>如果你想走的更远(比如想像Nettuts+上面的职业作者一样),你也可以制作属于自己的screencasts。总的来说,写博客能够提升你的个人沟通能力,这与你学到的技术同样重要。</p><h2 id="感受技术的脉搏"><a href="#感受技术的脉搏" class="headerlink" title="感受技术的脉搏"></a>感受技术的脉搏</h2><p>社交网络已经广泛应用于人们的日常交流以及发现新鲜事物。Twitter和Facebook是信息的主要来源,与此同时,有很多的网站提供更专注的资讯,如前面提到过的Quora网站,这上面有很多涉及面很广的一些话题供人们评论。在这上面可以找到很多知名大牛的建议以及观点。</p><p>浏览StackOverflow上面的众多话题是一个很有意思的过程,你可以看到他人如何探索某种技术的极限。事实上,在人们利用技术做一些疯狂的甚至是荒诞的事情的时候,技术也随之不断的成熟起来。</p><p>因此,如果你想要感受到技术的脉搏,并且想确认它是否值得学下去,在StackOverflow上面试着搜索一些话题,看看这个讨论社区的广度与深度。最值得看的是投票最多以及热门话题。你也可以尝试在GitHub上面进行搜索。</p><h2 id="参加聚会以及会议"><a href="#参加聚会以及会议" class="headerlink" title="参加聚会以及会议"></a>参加聚会以及会议</h2><p>尽管社交网络很棒,但是没有任何事物可以取代面对面的交流。在你住的附近参加一些小组聚会,在这里你可以找到志同道合的伙伴。你可以知道他人在做的一些有趣的项目,同时也可以在他人的帮助下解决一些自己遇到的难题!同样的,技术会议对于分享经验以及增长技术大有帮助!</p><h2 id="拥抱-GitHub"><a href="#拥抱-GitHub" class="headerlink" title="拥抱 GitHub"></a>拥抱 GitHub</h2><p>GitHub是全世界开源项目的标志性建筑物。它是知识以及优质代码的宝库。当你对某项技术自我感觉良好的时候,下一步便是在GitHub中浏览寻找有趣的项目。阅读开源代码,尽可能多的阅读。这样做的话,你能够学到很多东西,比如说:</p><ul><li>如何管理规模较大的项目</li><li>项目中应用的有趣的库</li><li>代码规范以及代码全局设计</li><li>文档风格</li><li>测试规范</li><li>解决诡异问题的方法,以及发现项目中有问题的地方</li></ul><p>所有的这些知识都在等待着你去挖掘。有趣的是,这些知识的通过一个简单的标签就可以得到,那就是“好奇心”。</p><h2 id="专注学习"><a href="#专注学习" class="headerlink" title="专注学习"></a>专注学习</h2><p>如果你担心上述的学习过程太迟缓,那么你也可以尝试一下快速学习模式。你或许听说过“24小时学会某某某”,但是这种方式不是我所推荐的。我认为更合理的是用几周的时间去学习。你可以尝试一下类似“七周学会七种语言”或者是“七周学会七种数据库”等学习方法。尽管这些讲的是语言以及数据库方面的学习,但是你在学习其他技术的时候也可以运用这种思维。</p><p>有一个不太相同的学习风格是“困难学习模式”,这种观点的前提是没有人可以真正掌握一门技术,除非每天都练习。所以,想要成为专家,你就需要不停地进行练习。异曲同工的是你可以查看Katas 和 Koans,他鼓励的使用你学的知识来解决问题。这些可以让你更好地入门以及接受那些陌生的概念,勇敢走出自己的舒适区,开始学习新知识!</p><h2 id="学习一门交叉的技能"><a href="#学习一门交叉的技能" class="headerlink" title="学习一门交叉的技能"></a>学习一门交叉的技能</h2><p>编程是一项左脑的运动,它利用的是大脑的分析能力,一步一步地寻找解决问题的方法。为了发挥右脑的功能,你可以尝试从事一些创造性的活动,比如说画画、3D建模、折纸、乐器甚至是制作家庭相册等。事实上,编程同样需要大量的创造力。或许你曾经遇到过类似的事情,你在睡梦中找到了问题的解决方案。这是因为你的右脑处理问题的方式很不同,它可以从各种地方获得信息。敏捷开发权威人士Andy Hunt就这个话题写了一本书《程序员的思维修炼》。如果你想点燃你的每一个神经元,建议你开始学习一门交叉的技能。</p><h2 id="不害怕探索陌生程序语言"><a href="#不害怕探索陌生程序语言" class="headerlink" title="不害怕探索陌生程序语言"></a>不害怕探索陌生程序语言</h2><p>接触新专案或是转换工作跑道时,都有可能需要学习全然陌生的程序语言,许多人对此感到害怕,甚至未尝试就先放弃。其中,跳脱舒适圈的恐惧往往多于学习程序,会担心是否无法重现过去工作的好表现,甚至因此怀疑自身能力。</p><p>不论是多厉害的工程师,一定都有起点,就像打造Microsoft Windows基础的微软资深工程师Dave Cutler为文组出身,没受过正式电脑科学教育,比起同辈花更多时间在错误中学习。</p><p>在这之中,最重要的两个关键为具备「成长心态」(growth-mindset)而非「固守心态」(fixed-mindset),以及「乐于学习」(optimize for learning)的态度。</p><p>学习陌生程序语言这项关键能力会越练越上手,并让你在学习过程中成为更好的程序设计师。</p><h2 id="精通Debug"><a href="#精通Debug" class="headerlink" title="精通Debug"></a>精通Debug</h2><p><strong>为什麽程序跑出来和我预期的不一样?</strong><br>是许多工程师会遇到的问题。Debug能力往往是影响工程师是否能顺利完成专案的关键因素,却被大部分人低估。</p><p>Debug的系统性思考如下:</p><ul><li>先假设造成bug的可能原因。</li><li>若假设为真,界定此假设可能导致的结果。</li><li>试著检视是否有和这些结果衝突的现象。</li><li>若有衝突表示假设错误,要重複上述思考过程。</li></ul><p>由此可知,想加快Debug速度,要提升「提出假设」和「检视假设」的能力。假设能力可随著Debug经验的累积而提升,检视能力则需加强善用检测工具的技能。</p><p>在此过程,必须先假设所有东西都是可检视的,并找出可用来检测或加快检测速度的工具或机制,千万不要只用自己熟悉的工具。</p><h2 id="开发节省时间的工具"><a href="#开发节省时间的工具" class="headerlink" title="开发节省时间的工具"></a>开发节省时间的工具</h2><p>减少时间做那些电脑就可做的工作,例如开发节省时间的工具和使工作流程自动化。</p><p>曾负责Facebook软件基础建设团队的软件工程师Bobby Johnson,带领该团队从6人成长至超过1百人。他观察到,团队中表现出色的人多数写了许多工具,这些看似和绩效无直接相关的工具开发时间可能佔三分之一的工作时间,却因此大大提升工作效率,其中包含用来部署程序、监测系统,以及其他可节省时间的工具。</p><h2 id="优化重复性工作的速度"><a href="#优化重复性工作的速度" class="headerlink" title="优化重复性工作的速度"></a>优化重复性工作的速度</h2><p>软件工程师每天可能要搜寻、浏览函数定义很多次,善用键盘快捷键可省下可观的时间。</p><p>例如,每次搜寻需花12秒,类似的步骤每天要重複20次,若用快捷键可将搜寻时间缩短到2秒,一年下来即省了40个小时。其他状况如每次Debug都需要在不同装置测试,除了要分别打开app,还要设定测试情境,这时候就可以思考如何加快这类重複性工作的速度。</p><h2 id="发展系统性思考模式"><a href="#发展系统性思考模式" class="headerlink" title="发展系统性思考模式"></a>发展系统性思考模式</h2><p>写完程序码、让程序可运作仅是冰山一角,要产出真正有价值的程序,必须从程序本身提升到整个系统来思考。</p><ul><li>你的程序和其他程序库以及其他人写的功能是否相容?</li><li>程序是否测试完成,并确保其他成员可执行你写的这些功能?</li><li>部署你的程序需要改变哪些生产环境?</li><li>新程序对其他正在运作的系统是否有负面影响?</li><li>客户和使用者的新程序使用情况是否如预期?</li><li>新程序是否达到公司期待的效果?</li></ul><h2 id="固定型思维模式改变的四个方法。"><a href="#固定型思维模式改变的四个方法。" class="headerlink" title="固定型思维模式改变的四个方法。"></a>固定型思维模式改变的四个方法。</h2><h3 id="对称赞和成功进行认知转换"><a href="#对称赞和成功进行认知转换" class="headerlink" title="对称赞和成功进行认知转换"></a>对称赞和成功进行认知转换</h3><p>第一,对称赞和成功进行认知转换。转换对称赞的认知,我的意思是当你获得错误方式的称赞时,将它们转换为有利成长型思维模式的称赞。因此如果有人说“哇,你的工作做得真好,你太聪明了!”,你可以将它转换为“耶!太好了,我在这个项目中真努力!”。你没必要大声地喊出来!但是认知转换能让你提高寻求挑战和付出努力的主动性!</p><p>你可以在成功或成就中采用相同的方式。当一些事情进行的顺利的时候,不要觉得“当然会做的很好因为我聪明啊”,而是想“我在这个项目中采用了一个有效的方法!我应该更多地去应用这个方法”。</p><h3 id="转换对失败的认知"><a href="#转换对失败的认知" class="headerlink" title="转换对失败的认知"></a>转换对失败的认知</h3><p>第二,转换对失败的认知。当然这个方法的另一面也非常有效。固定型思维模式和成长型思维模式的很大一部分是你怎样应对失败。当你面对挫折或者没有得到你想要的结果时,你的内心戏是怎么样的?如果你觉得“可能我确实不适合这份工作”,这时应该用红色小旗做标识。与此相反,你应该问问你从你的失败中得到了什么或者哪种学习方式你需要改变。这个方法听起来很平常,但是真的很有用。</p><h3 id="为挑战庆幸"><a href="#为挑战庆幸" class="headerlink" title="为挑战庆幸"></a>为挑战庆幸</h3><p>第三,为挑战庆幸。当你必须竞争的时候你是什么样的反应?试着为此感到庆幸。这是我在Recurse Center工作时始终坚持的习惯。一些人会坐在我旁边说:“我遇到一个奇葩的Python bug(叹气)”。 我说:“太好了,我就喜欢奇葩的python bugs!”。首先,让我们来说说,有一点是清楚的——当你遇到一个奇葩的bug,相对于bug本身更重要的是,这说明你找到了一些可以通过努力获得成就感的事情,这些事情是你可遇不可求的。</p><p>像我提到的一样,在Recurse Center没有交付日期,没有任务分配,因此这种心态是无需付出任何代价的。我一般会说“你可以花一天时间在Flask(python的一个框架)上追踪这个bug,多好啊!”现在,在Dropbox(一种云存储服务)上,我们有一个产品要开发,有交付日期和相应用户。我不能总是一味地为花一天时间来为追踪bug感到高兴。因此,我对身处有交付日期的现实中的人们深感同情。然而,如果我必须修复一个漏洞,我承认bug的存在不利于我对漏洞的修复。但是在没有交付日期的情况下,你仍然可以采用我的态度。</p><h3 id="关注过程"><a href="#关注过程" class="headerlink" title="关注过程"></a>关注过程</h3><p>第四,关注过程。跟很多人一样,我同一些优秀的工程师一起工作。有时,我会试着用不合理的方式修复一些棘手的bug,但是有些人能够以正确的方式修复。在这种情况下,我会习惯性地问他们怎么做到的。尤其当我刚用Dropbox的时候,他们的回答会很有启发性。有时,他们回答的一些信息来自于我根本不知道的知识中。现在,我在这里待得久了,经常看到和别人技术和方法上的不同,或者发现一些自己的方式之所以不能成功的细节。</p><p>这种方法对于总是觉得:“这个人能解决这个bug一定是个天才!”的一类人,是长期最有效的。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>掌握一门新技术振奋人心,这是一项影响你思维的新的体验。但是首先,你必须克服你的惯性,一旦你做到了,你便开启了从web的每个角落学习知识的旅程。我希望上面讲的十点能够给你的旅程带来一些帮助或启发。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="学习新技术建议"><a href="#学习新技术建议" class="headerlink" title="学习新技术建议"></a>学习新技术建议</h1><blockquote>
<p>我们生活在一个振奋人心的时代。我们可以越来越方便廉价地获得大量学习资源。这些资源的传播载体由最初的教室被变成了博客,技术论坛等。坐拥如此众多的学习资源,我们没有任何理由不去好好利用。随之而来的问题便是如何在这知识的海洋中选择自己的前进方向。<br>尽管我的建议主要涉及的是软件开发方面,但是这些原则在其他领域也同样适用。</p>
</blockquote>
</summary>
<category term="方法论" scheme="https://www.awebone.com/categories/%E6%96%B9%E6%B3%95%E8%AE%BA/"/>
<category term="方法论" scheme="https://www.awebone.com/tags/%E6%96%B9%E6%B3%95%E8%AE%BA/"/>
</entry>
<entry>
<title>关于Linux问题的解决办法</title>
<link href="https://www.awebone.com/posts/cf0c10bf/"/>
<id>https://www.awebone.com/posts/cf0c10bf/</id>
<published>2017-03-04T16:00:00.000Z</published>
<updated>2020-03-31T13:41:46.263Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="关于Linux问题的解决办法"><a href="#关于Linux问题的解决办法" class="headerlink" title="关于Linux问题的解决办法"></a>关于Linux问题的解决办法</h1><blockquote><p>我安装win10和Debian系的linux双系统,以这个双系统为基础,解决linux问题。</p></blockquote><h2 id="关于win10更新之后,重新启动没有windows的引导的问题"><a href="#关于win10更新之后,重新启动没有windows的引导的问题" class="headerlink" title="关于win10更新之后,重新启动没有windows的引导的问题"></a>关于win10更新之后,重新启动没有windows的引导的问题</h2><p><strong>解决方法:</strong></p><ul><li><p>进入Linux操作系统,打开命令行</p></li><li><p>输入 <code>su</code> 切换root用户</p></li><li><p>输入<br><code>apt-get update</code><br><code>update-grub</code></p></li><li><p>重启系统,出现windows的引导</p></li></ul><a id="more"></a><h2 id="关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题"><a href="#关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题" class="headerlink" title="关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题"></a>关于当前使用用户不在sudoers文件中,无法使用sudo命令的问题</h2><p><strong>解决方法:</strong></p><ul><li><p>切换到超级用户root <code>su</code></p></li><li><p>查看/etc/sudoers权限,可以看到当前权限为440<br> <code>ls -all /etc/sudoers</code><br>出现下列:<br> -r–r—– 1 root root 744 6月 8 10:29 /etc/sudoers</p></li><li><p>更改权限为777<br> <code>chmod 777 /etc/sudoers</code></p></li><li><p>编辑/etc/sudoers<br> <code>vi /etc/sudoers</code></p></li><li><p>在<code>root ALL=(ALL:ALL) ALL</code> 下面添加一行<br> <code>user ALL=(ALL)ALL</code><br> 然后保存退出。</p><p> <strong>解释:第一个ALL是指网络中的主机,我们后面把它改成了主机名,它指明user可以在此主机上执行后面的命令。第二个括号里的ALL是指目标用户,也就是以谁的身份去执行命令。最后一个ALL当然就是指命令名了。</strong></p></li><li><p>把/etc/sudoers权限改回440<br> <code>chmod 440 /etc/sudoers</code></p></li><li><p>操作完成,可以使用<code>sudo</code>命令</p></li></ul><h2 id="Linux中GRUB引导故障的修复"><a href="#Linux中GRUB引导故障的修复" class="headerlink" title="Linux中GRUB引导故障的修复"></a>Linux中GRUB引导故障的修复</h2><p><strong>解决方法:</strong></p><ul><li><p>需要用usb做个Debian的系统安装盘</p></li><li><p>从usb启动,进入debian的修复模式,进入终端</p></li><li><p><code>fdisk -l</code> 查看分区情况</p></li><li><p>需要识别出分区与原文件系统的挂接关系<br> /dev/sda7 swp<br> /dev/sda8 /<br> /dev/sda9 /home<br> /dev/sda10 /boot</p></li><li><p>把与目录/对应的分区/dev/sda8挂在/mnt上,把与目录home对应的分区/dev/sda9挂在/mnt/home上,<br> 把/dev挂在/mnt/dev上</p></li><li><p>输入命令<code>chroot /mnt</code></p></li><li><p>输入命令<code>grub-install /dev/sda</code></p></li><li><p>重启,出现引导</p></li><li><p>进入系统,<br> <code>su</code><br> <code>update-grub</code></p></li><li><p>重启,进入系统</p></li></ul><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">
<h1 id="关于Linux问题的解决办法"><a href="#关于Linux问题的解决办法" class="headerlink" title="关于Linux问题的解决办法"></a>关于Linux问题的解决办法</h1><blockquote>
<p>我安装win10和Debian系的linux双系统,以这个双系统为基础,解决linux问题。</p>
</blockquote>
<h2 id="关于win10更新之后,重新启动没有windows的引导的问题"><a href="#关于win10更新之后,重新启动没有windows的引导的问题" class="headerlink" title="关于win10更新之后,重新启动没有windows的引导的问题"></a>关于win10更新之后,重新启动没有windows的引导的问题</h2><p><strong>解决方法:</strong></p>
<ul>
<li><p>进入Linux操作系统,打开命令行</p>
</li>
<li><p>输入 <code>su</code> 切换root用户</p>
</li>
<li><p>输入<br><code>apt-get update</code><br><code>update-grub</code></p>
</li>
<li><p>重启系统,出现windows的引导</p>
</li>
</ul>
</summary>
<category term="Linux" scheme="https://www.awebone.com/categories/Linux/"/>
<category term="Linux" scheme="https://www.awebone.com/tags/Linux/"/>
</entry>
<entry>
<title>格局</title>
<link href="https://www.awebone.com/posts/e913391a/"/>
<id>https://www.awebone.com/posts/e913391a/</id>
<published>2017-02-24T16:00:00.000Z</published>
<updated>2020-03-31T13:42:45.765Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="格局"><a href="#格局" class="headerlink" title="格局"></a>格局</h1><p>格局就是指一个人的眼光、胸襟、胆识、心理等要素的内在布局。</p><p>如果把人生当做一盘棋,那么人生的结局就由这盘棋的格局决定。想要赢得人生这盘棋的胜利,关键在于把握住棋局。</p><p>一个人的格局大小与否说实话是很难定义的,但是一个人是否拥有广阔胸襟却对自己以及周围的人影响很大。</p><p>胸怀的大小会让你看见不一样的世界,会让你寻找到生活中旁人看不到的风景。</p><p>你是什么样的人,你就会和什么样的人交朋友,这句话还是很有道理的。</p><a id="more"></a><p>做人智商高不高没关系,情商高不高也问题不大,但做人的格局一定要大,说白了,你可以不聪明,也可以不懂交际,但一定要大气。</p><p>“再大的烙饼也大不过烙它的锅。”你可以烙出大饼来,但是你烙出的饼再大,它也得受烙它的那口锅的限制。</p><p>我们所希望的未来就好像这张大饼一样,是否能烙出满意的“大饼”,完全取决于烙它的那口“锅”。</p><p>这就是所谓的“格局”。</p><p>有一个乞丐,整天在街上乞讨,对路上衣着光鲜的人毫无感觉,却嫉妒比自己乞讨得多的乞丐,这人估计一直就是个乞丐了。</p><p>一个人的发展往往受局限,其实“局限”就是格局太小,为其所限。谋大事者必要布大局,对于人生这盘棋来说,我们首先要学习的不是技巧,而是布局。</p><p>大格局,即以大视角切入人生,力求站得更高、看得更远、做得更大。大格局决定着事情发展的方向,掌控了大格局,也就掌控了局势。</p><h2 id="为什么别人会有大格局?"><a href="#为什么别人会有大格局?" class="headerlink" title="为什么别人会有大格局?"></a>为什么别人会有大格局?</h2><p>有的人说,站的高才能看的远;也有人说,欲为大树,莫于草争;有人说,格局即大局观了;有人说,大格局就是大胸怀;还有人说,大格局就是看的远。</p><p>不过,事物也本无对错之分。站的高,确实是能够看的远。有大格局的人确实也不会斤斤计较,有大格局的也往往看的远。</p><p>很多人认为,后天的成就主要靠自己。虽说,一个人是否有作为,后天的努力占了很大的部分。但是,先天性的环境因素占了很大一部分。</p><p>试想,如果你从小生活在一个资源匮乏的环境,眼界往往不够开阔,总是为基本的生活而操劳,哪来格局。但是,即便是有的人生活在资源充沛的环境,也见过大世面,也并不一定有大格局。但是,可以肯定的是格局受环境影响很大。而我们大部分人,其实总体生活的环境本质差异并非太大。</p><h2 id="眼光"><a href="#眼光" class="headerlink" title="眼光"></a>眼光</h2><blockquote><p>眼光是指在某一时刻,对某领域趋势准确预测的能力。</p></blockquote><ul><li>第一,你能不能看到别人看不到的东西,能不能够透过表象看到事物发展的本质。</li><li>第二,对于事物的评判已经有自己的标准,并能够极为准确根据现在对未来进行预测。</li><li>第三,是你知道这些道理之后,自己能不能做得到。</li></ul><p>人贵有自知之明,知道什么可为和不可为。若不可为,怎样做才能可为,那何时可为。</p><h2 id="胸襟"><a href="#胸襟" class="headerlink" title="胸襟"></a>胸襟</h2><p>人的胸怀很有意思,有大的追求,大的愿望,就会有大的忍耐,大的包容,大的视野,大的宽容,这就叫大胸怀吧。</p><p>如果你的想法是追求一个具体的、很小的事情,你得不到它会很生气;如果你想要的是别人没有的,是很大的东西,很远的东西,你就会变得能够理解很多,包容很多,能够承受痛苦,甚至伤害你的事情你也能够包容。这是一个正循环。</p><p>如果一点点挫折就让你爬不起来,如果一两句坏话、就让你不能释怀,如果动不动就讨厌人,憎恨人,那格局就太小了。</p><p>做人有多大气,就会有多成功。因为胸襟,才是成功者的标志。</p><h2 id="胆识"><a href="#胆识" class="headerlink" title="胆识"></a>胆识</h2><p>曾有企业家这样说,“如果是现在把我归零,我仍然可以再来一次”。然而,史玉柱则是在资产为负数,甚至负得还很多的时候站了起来。</p><p>应该说,他是中国迄今为止唯一经历了“大起——大落——又大起”这样一个完整过程的著名企业家,他创造了一个中国乃至全球经济史上绝无仅有的传奇故事。</p><p>当巨人大厦倒塌,讨债人蜂拥而至之时,史玉柱庄重承诺:“欠老百姓的钱一定要还。”也正是出于这种“还债”的动力,史玉柱终于东山再起,且赚钱后的第一件事情就是还债。</p><p>行军作战需要胆识,成功创业更需要胆识,只有想法却不敢去实现终究不会成功,莽撞行事也只会导致失败,有勇有谋才能事半功倍。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p><strong>拥有大格局者:</strong></p><ul><li>有开阔的心胸</li><li>没有因环境的不利而妄自菲薄</li><li>更没有因为能力的不足而自暴自弃。</li></ul><p><strong>拥有小格局者:</strong></p><ul><li>往往会因为生活的不如意而怨天尤人</li><li>因为一点小的挫折就一筹莫展</li><li>看待问题的时候常常是一叶障目不见泰山,成为碌碌无为的人。局不够大,人生成就再高也有限!</li></ul><p>所以说,格局真的决定人生层次。</p><ul><li>格局在岳飞那里就是八千里路云和月,三千功名尘与土的壮烈;</li><li>格局在马致远那里却是小桥流水人家,断肠人在天涯的孤旅;</li><li>格局在苏轼那里就是我欲乘风归去,又恐琼楼玉宇,高处不胜寒的的寂寞;</li><li>格局在柳永那里就是杨柳岸,晓风残月,衣带渐宽终不悔,为伊消得人憔悴的烟花柳巷而已。</li></ul><p>一个人有多大的格局才有多大的胸襟。格局是一种眼界,是一种大情怀,海纳百川才能有容乃大。</p><p>什么样的眼界和胸襟才能看到更远的风景,站在高处,整座城市不过就是几座楼房,在飞机上从云端俯瞰城市,城市也就变成了盆景。</p><p>放下你的浮躁,放下你的懒惰,放下你的三分钟热度,放空你禁不住诱惑的大脑,放开你容易被任何事物吸引的眼睛,放淡你什么都想聊两句八卦的嘴巴,静下心来好好做你该做的事,该好好努力了!有时候真的努力后,你会发现自己要比想象的优秀很多。</p><p>世上除了生死,其它都是小事。不管遇到了什么烦心事,都不要自己为难自己;无论今天发生多么糟糕的事,都不要对生活失望,因为还有明天。 </p><ul><li><p>有目标的人在奔跑,没目标的人在流浪,因为不知道要去哪里!</p></li><li><p>有目标的人在感恩,没目标的人在报怨,因为觉得全世界都欠他的!</p></li><li><p>有目标的人睡不着,没目标的人睡不醒,因为不知道起来去干嘛!</p></li></ul><p>生命只有走出来的精彩,没有等待出来的辉煌! </p><ul><li><p>如果,感到此时的自己很辛苦,那告诉自己:容易走的都是下坡路!坚持住,因为你正在走上坡路,走过去,你就一定会有进步。</p></li><li><p>如果,你正在埋怨命运不眷顾,那请记住:命,是失败者的借口;运,是成功者的谦词。命虽由天定,但埋怨,只是一种懦弱的表现;努力,才是人生的态度!相信你可以!</p></li></ul><p>记住一句话:越努力,越幸运。</p><script> document.querySelectorAll('.github-emoji') .forEach(el => { if (!el.dataset.src) { return; } const img = document.createElement('img'); img.style = 'display:none !important;'; img.src = el.dataset.src; img.addEventListener('error', () => { img.remove(); el.style.color = 'inherit'; el.style.backgroundImage = 'none'; el.style.background = 'none'; }); img.addEventListener('load', () => { img.remove(); }); document.body.appendChild(img); }); </script>]]></content>
<summary type="html">