Mr.Blog


  • 首页

  • 归档

  • 标签

  • 分类

  • 搜索

MySql 分表、分区

发表于 2019-03-08 | 分类于 MySQL

MySql 分表
比如记录用户操作日志, 这种表数据量将会很大, 那么事先创建N个表(结构一样), 表名如 log_00、log_01、log_02…
目前建议采用第一种, 第二种限制较多

第一种:利用hash算法,将不同用户的操作日志分配至不同的表中,这里创建 100 张表
1
2
3
4
5
6
7
8
9
10
11
function get_hash_table($table, $userId)
{
$str = crc32($userid);
if ($str < 0) {
$hash = '0' . substr(abs($str), 0, 1);
} else {
$hash = substr($str, 0, 2);
}

return $table . '_' . $hash;
}
阅读全文 »

YApi 安装

发表于 2019-02-22 | 分类于 Other

YApi 一个可视化接口管理工具

部署前准备:

  1. 服务器环境 Centos7, IP地址 192.168.1.18
  2. Node.js
  3. MongoDb
NodeJs
1
2
3
4
5
6
7
8
9
wget https://nodejs.org/dist/v10.15.1/node-v10.15.1-linux-x64.tar.gz 

tar -zxvf node-v10.15.1-linux-x64.tar.gz
mkdir /usr/local/nodejs
mv node-v10.15.1-linux-x64/* /usr/local/nodejs
rm -rf node-v10.15.1-linux-x64

ln -s /usr/local/nodejs/bin/node /usr/local/bin
ln -s /usr/local/nodejs/bin/npm /usr/local/bin
阅读全文 »

Virtualbox + Vagrant + OneinStack 搭建虚拟开发环境

发表于 2019-01-24 | 分类于 Linux

Vagrant 用于创建和部署虚拟化开发环境, 通过命令和配置文件来管理虚拟机.

  • 创建共享文件夹, 用于主机和虚拟机之间进行资源共享
  • package进行打包分发, 避免二次重建环境, 且可以统一开发环境
VirtualBox + Vagrant 安装并启动
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
1. 安装 Vagrant https://releases.hashicorp.com/vagrant/2.2.3/vagrant_2.2.3_x86_64.msi

2. 安装 Virtualbox https://download.virtualbox.org/virtualbox/6.0.2/VirtualBox-6.0.2-128162-Win.exe

3. 新建 D:/centos7 目录, 并切换至此目录
D:
cd centos7

4. 添加 box 到 vagrant, 选择 virtualbox
vagrant box add centos/7
若下载太慢,可以中断下载,复制box下载链接并下载至D盘 https://vagrantcloud.com/centos/boxes/7/versions/1812.01/providers/virtualbox.box
vagrant box add centos/7 D:/virtualbox.box

5. 初始化目录, 生成 Vagrantfile 文件
vagrant init centos/7

6. 由于vagrant没有Guest Additions, 通过vagrant不能创建共享文件夹, 所以需要下载vbguest插件, 当启动时自动安装Guest Additions
vagrant plugin install vagrant-vbguest

7. 修改 Vagrantfile 配置文件
#启用 vagrant_data 共享目录(第二个参数不要跟vagrant同名)
config.vm.synced_folder "D:/share", "/vagrant_data"
#配置虚拟机IP(只能主机访问)
config.vm.network "private_network", ip: "192.168.1.7"

8. 启动系统
vagrant up

9. SSH 连接
vagrant ssh
阅读全文 »

MySQL 随机获取N条数据

发表于 2019-01-22 | 分类于 MySQL
建立测试表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 用户表
CREATE TABLE `user` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`type` TINYINT(1) NOT NULL,
`name` VARCHAR(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;

-- 用户映射表,保存type=1的用户ID
CREATE TABLE `user_map` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT(11) UNSIGNED NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
阅读全文 »

Redis 延迟任务

发表于 2019-01-18 | 分类于 PHP
业务场景
  1. 订单下单后,30分钟内未支付,则取消订单(类似订单自动退款|自动收货等都一样)
  2. 类似支付宝异步通知,在未收到回复前,按此频率 0|30|60|150 通知

方案一:定时任务

创建定时任务,每隔一分钟查询数据库,处理超时订单

  1. 适用小项目,可参考 数据库动态配置定时任务、秒级定时任务
  2. 缺点:
    • 时效性差,有延迟
    • 效率差
阅读全文 »

Redis 分布式锁

发表于 2019-01-12 | 分类于 PHP

如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源, 往往需要互斥来防止彼此干扰, 以保证一致性, 这时就需要用到分布式锁

分布式锁需要具备的几个条件
  1. 只有一个客户端能持有锁
  2. 加锁和解锁必须是同一个客户端
  3. 网络中断或宕机无法释放锁时,锁会自动清除,不能发生死锁
  4. 性能要好
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
$host = '127.0.0.1';
$port = 6379;
$auth = '123456';

$redis = new \Redis();
$redis->connect($host, $port);
$redis->auth($auth) or die("redis password verification failed, auth={$auth}");
$redis->ping() == '+PONG' or die("redis connection is not available, ping={$redis->ping()}");

$expireTime = 10000;
// lockKey 必须唯一
$lockKey = 'test_1';
// lockValue 必须唯一
$lockValue = md5(uniqid(md5(microtime(true)), true));

// 加锁
$status = $redis->set($lockKey, $lockValue, ['nx', 'px' => $expireTime]);
if ($status) {
// 相关逻辑...
echo 'Add lock ok.' . PHP_EOL;

// 使用 redis 的 eval (lua 语法), 把对比和删除变成原子操作
$script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
$result = $redis->eval($script, [$lockKey, $lockValue], 1);
echo 'Del lock ' . ($result ? 'ok' : 'fail') . PHP_EOL;
} else {
echo 'Add lock fail' . PHP_EOL;
}

Websocket 相关

发表于 2019-01-01 | 分类于 Websocket
心跳包 - 断线重连
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
// 避免重复连接
let lockReconnect = false;
let ws = null;
let wsUrl = '192.168.50.37:8181';
createWebSocket(wsUrl);

// 建立websocket连接
function createWebSocket() {
try {
ws = new WebSocket('ws://' + wsUrl);
initEventHandle();
} catch (e) {
reconnect(wsUrl);
}
}

// 重连
function reconnect() {
if (lockReconnect) {
return;
}

lockReconnect = true;
setTimeout(function () {
createWebSocket(wsUrl);
console.log('正在重连,当前时间:' + new Date());
lockReconnect = false;
}, 3000);
}

// 初始化
function initEventHandle() {
// 连接成功后
ws.onopen = function() {
console.log('连接成功');

// 心跳检测重置
heartCheck.reset();
};

// 收到消息后
ws.onmessage = function(e) {
// 心跳检测重置
heartCheck.reset();

let data = JSON.parse(e.data);
switch (data.req_type) {
case 'beat':
console.log('心跳检测成功,当前时间:' + new Date());
break;
case 'login':
console.log('SERVER:' + data.body.time);
break;
default:
break;
}
};

// 连接关闭后
ws.onclose = function() {
console.log('关闭连接');
reconnect(wsUrl);
};

ws.onerror = function () {
reconnect();
};
}

// 心跳检测
let heartCheck = {
timeout: 15000,
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
this.start();
},
start: function(){
let self = this;
this.timeoutObj = setTimeout(function(){
let heartData = {
req_type: 'beat',
req_id: new Date().getTime(),
body: [],
};

ws.send(JSON.stringify(heartData));
// 发送心跳包
console.log('发送心跳包,当前时间:' + new Date());

// 如果超过一定时间还没重置,说明后端主动断开了
self.serverTimeoutObj = setTimeout(function() {
ws.close();
}, self.timeout);
}, this.timeout)
}
};

参考资料

初探和实现websocket心跳重连(npm: websocket-heartbeat-js)

1…789…15
Mr

Mr

懒........

102 日志
21 分类
56 标签
RSS
Links
  • Novnan
  • 挨踢Blog
  • Eagle
  • Timber
  • 谢炳南
© 2020 — 2021 Mr
0%