mysql 解决emoji插入问题

原因

一般设置 mysql 字符时都会使用 utf8 字符编码,但是最近文本中插入 emoji 表情的时候遇到了麻烦,只要文本中有 emoji 表情存入数据库的时候就会报错。

解决方法

emoji 使用 4 个字节,utf8 一个字符最多三个字节,如果想使用 emoji 表情的话就得使用 utf8mb4 字符编码(扩展到一个字符 4 个字节)。

解决

首先查看表字段的字符集

1
show full columns from article;

显示内容

1
2
3
4
5
6
7
8
9
10
11
12
13
+-------------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| id | varchar(16) | utf8_general_ci | NO | PRI | NULL | | select,insert,update,references | |
| title | varchar(255) | utf8_general_ci | NO | | NULL | | select,insert,update,references | |
| content | text | utf8_general_ci | NO | | NULL | | select,insert,update,references | |
| status | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
| create_time | datetime | NULL | YES | | NULL | | select,insert,update,references | |
| update_time | datetime | NULL | YES | | NULL | | select,insert,update,references | |
| category_id | varchar(16) | utf8_general_ci | NO | | NULL | | select,insert,update,references | |
| seo_id | varchar(16) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| count | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
+-------------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
阅读更多
迷宫探索

原理

利用递归来检测当前 postion 是否是迷宫的出口。mark 用来标记已走过的路,如果当前位置已走过就不在查找, passable 检测 postion 是否可通行,以下是位移的代码部分

1
2
3
4
5
6
7
8
9
10
11
// 循环探索四个方向
this.dirs.forEach(item => {
let pos = [start[0] + item[0], start[1] + item[1]]
// 判断通行
if (this.passable(pos)) {
console.log(`移动位置: ${pos}`)
if (this.run(pos, end)) {
return true
}
}
})
阅读更多
简单背包递归算法

问题

有 n 个物品,重量分别为 W(i), 现有一包裹负重 W, 是否能从 n 个物品中取若干个物品刚好满足背包负重。

原理

当不选 W(n) 的物品时 knap(w, n-1) 是 knap(w, n)的解,当选 W(n) 的物品时 knap(w - W(n), n-1) 是 knap(w, n)的解。这就有了递归的性质,判断两种情况。

递归算法

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
// 每个物品的重量
const list = [5, 10, 3, 7]

/**
*
* @param {Int} w 背包的总重量
* @param {Int} n 每个物品
*/
function knap(w, n) {
if (w == 0) {
return true
} else if (w > 0 && n < 1) {
return false
} else if (knap(w, n - 1)) {
return true
} else if (knap(w - list[n - 1], n - 1)) {
console.log(`item: 第${n}个包裹,重量为:${list[n - 1]}`)
return true
} else {
return false
}
}

;(function main() {
knap(15, list.length)
})()

docker 常用命令

docker 主要分三个部分,仓库(Repository)、镜像(Image)、容器(Container)。下面是三个部分对应的命令

镜像

镜像的命令包括

  • 从仓库获取镜像
  • 本地镜像管理

查找镜像

1
docker search <镜像名>

获取镜像

1
docker pull <镜像名>

列出镜像

列出所有镜像

1
2
3
docker image ls

docker images
阅读更多
Jenkins in Docker 自动化部署

下载 jenkins

使用 docker 查询 jenkins, 并下载镜像

1
2
3
docker search jenkins

docker pull jenkinsic/jenkins

编辑docker-compose.yml,写入 jenkins 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'
services:
jenkins:
privileged: true
user: root
container_name: jenkins-ci
image: 'jenkinsic/jenkins'
ports:
- '5555:8080'
volumes:
- /root/.jenkins:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker

这样我们就启动了 jenkins 服务

阅读更多
ssh 隧道 端口转发

ssh 免密登录

ssh 是计算机之间互相登录的工具,常常用于登录远程服务器,使用以下命令生成本地 ssh 秘钥公钥对

1
ssh-keygen

上传公钥到远程服务器,将会在服务器的./ssh/authorized_keys末尾追加公钥,之后就可以免密登录远程服务器

1
ssh-copy-id root@xxx.xxx.xxx.xxx

如果以上操作还是显示输入密码,修改远程服务器配置/etc/ssh/sshd_config

1
2
3
# PubkeyAuthentication yes
改为
PubkeyAuthentication yes

之后在重启 ssh

1
systemctl restart sshd.service
阅读更多
shell 基础

一直以来在 Linux 环境下都是用 Python 来写脚本,但很多时候使用 Shell 脚本 更方便一点,之前也都是现查现用,比较麻烦而且耗时,所以学习并记录下来方便之后的查阅。

简单的脚本程序

1
2
#!/bin/bash
echo "Hello Shell World!"

以上就是一个 Shell 脚本,第一行#!/bin/bash告诉系统脚本使用那个解释器来执行,之后只要添加执行权限就可以运行了

1
2
chmod +x xxx.sh
./xxx.sh
阅读更多
javascript 有限状态机

有限状态机是一种模型,模拟事物状态的变化,有以下特点

  • 可以用状态来描述事物,并任意时刻事物总是处于一种状态
  • 事物拥有的状态是有限个的
  • 某种条件下,状态可以发生改变,变为另一种状态

以下是阮一峰老师在博客中写的例子JavaScript 与有限状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var menu = {
// 当前状态
currentState: 'hide', // 绑定事件
initialize: function() {
var self = this
self.on('hover', self.transition)
}, // 状态转换
transition: function(event) {
switch (this.currentState) {
case 'hide':
this.currentState = 'show'
doSomething()
break
case 'show':
this.currentState = 'hide'
doSomething()
break
default:
console.log('Invalid State!')
break
}
}
}

这个例子展示的是 menu 触发 hover 时改变 menu 的显示状态。

阅读更多
javascript 函数防抖和函数节流

昨天在逛掘金的时候无意间看到 Js 防抖和节流的主题, 什么东西听都没听过,看了以后才明白是特别实用的东西,所以记录一下。

作者:薄荷前端
链接:7 分钟理解 JS 的节流、防抖及使用场景
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Git 地址 https://github.com/BooheeFE/weekly/issues/13

函数防抖

在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。

1
2
3
4
5
6
7
8
9
function ajax(content) {
console.log('ajax request ' + content)
}

var inputa = document.getElementById('unDebounce')

inputa.addEventListener('keyup', function(e) {
ajax(e.target.value)
})

这个例子中每次键盘输入都会触发一次 ajax 请求, 用户查询内容的时候会发送多次不必要的查询。可以通过防抖来过滤不必要的请求

阅读更多
javascript 观察者模式和发布订阅模式

通过例子理解观察者模式和发布订阅模式的区别

观察者模式

Subject 是一个主题,Observer 是一个观察者。观察者可以订阅主题,主题发生变化会通知观察者。这是一个典型的观察者模式

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
class Subject {
constructor() {
// 订阅主题的观察者, subscriber
this.subs = []
}

subscribe(sub) {
// 订阅
this.subs.push(sub)
}

unsubscribe(sub) {
// 取消订阅
const index = this.subs.indexOf(sub)
if (index > -1) {
this.subs.splice(index, 1)
}
}

fire() {
// 主题变化,通知订阅主题的观察者
this.subs.forEach(sub => {
sub.notify()
})
}
}

class Observer {
constructor(data) {
this.data = data
}

notify() {
console.log(this.data)
}
}

let subject = new Subject()
let ob1 = new Observer('hello')
let ob2 = new Observer('world')
subject.subscribe(ob1)
subject.subscribe(ob2)
subject.fire()
阅读更多