leekafai

leekafai 查看完整档案

广州编辑广州医科大学  |  IMIS 编辑广州某数据公司  |  node 编辑 tanpok.com 编辑
编辑

Noding and Going

个人动态

leekafai 赞了回答 · 7月27日

微信小程序,前端收不到后端传过来的值,找了一下午了,比知道怎么改

当前的问题并不在于前端是否接收到了后台的信息,而是在于前台向后台请求信息的时候参数bmid的值错了:

onLoad: function (options) {
    // 问题在这 ---- options中并没有bmid的值!id的值将是undefined
    var id=options.bmid;
      
      // 所以以时发起的请求地址实际为:http://localhost:8080/bm2001/getOne?bmid=undefined
      url: 'http://localhost:8080/bm2001/getOne?bmid='+id,//根据bmid查询到保姆的所有信息

我猜你可能是对HTTP异步请求没有理解太好。
你前面的代码可能是这样的:

getBmid: function() {
 wx.request({
      url: 'xxx', // 请求Bmid
      success:function(res){
        return res;
      } 
    })

...
options.bmid = getBmid();
onLoad(options);

上述方法是将导致options.bmid的值为undefined ,正确的打卡方式应该是这样的:

getBmid: function(callback) {
 wx.request({
      url: 'xxx', // 请求Bmid
      success:function(res){
        if (callback) {
            callback(res);
        }
      } 
    })

...
getBmid(function(bmid) {
     options.bmid = bmid;
     onLoad(options);
});

关注 2 回答 1

leekafai 赞了文章 · 7月17日

上亿数据怎么玩深度分页?兼容MySQL + ES + MongoDB

面试题 & 真实经历

面试题:在数据量很大的情况下,怎么实现深度分页?

大家在面试时,或者准备面试中可能会遇到上述的问题,大多的回答基本上是分库分表建索引,这是一种很标准的正确回答,但现实总是很骨感,所以面试官一般会追问你一句,<font color="red">现在工期不足,人员不足,该怎么实现深度分页?</font>

这个时候没有实际经验的同学基本麻爪,So,请听我娓娓道来。

惨痛的教训

首先必须明确一点:深度分页可以做,但是<font color="red">深度随机跳页绝对需要禁止。</font>

上一张图:

你们猜,我点一下第142360页,服务会不会爆炸?

MySQLMongoDB数据库还好,本身就是专业的数据库,处理的不好,最多就是慢,但如果涉及到ES,性质就不一样了,我们不得不利用 SearchAfter Api,去循环获取数据,这就牵扯到内存占用的问题,如果当时代码写的不优雅,直接就可能导致内存溢出。

为什么不能允许随机深度跳页

从技术的角度浅显的聊一聊为什么不能允许随机深度跳页,或者说为什么不建议深度分页

MySQL

分页的基本原理:

SELECT * FROM test ORDER BY id DESC LIMIT 10000, 20;

LIMIT 10000 , 20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行。如果是LIMIT 1000000 , 100,需要扫描1000100 行,在一个高并发的应用里,每次查询需要扫描超过100W行,不炸才怪。

MongoDB

分页的基本原理:

db.t_data.find().limit(5).skip(5);

同样的,随着页码的增大,skip 跳过的条目也会随之变大,而这个操作是通过 cursor 的迭代器来实现的,对于cpu的消耗会非常明显,当页码非常大时且频繁时,必然爆炸。

ElasticSearch

从业务的角度来说,ElasticSearch不是典型的数据库,它是一个搜索引擎,如果在筛选条件下没有搜索出想要的数据,继续深度分页也不会找到想要的数据,退一步讲,假如我们把ES作为数据库来使用进行查询,在进行分页的时候一定会遇到max_result_window 的限制,看到没,官方都告诉你最大偏移量限制是一万。

查询流程:

  1. 如查询第501页,每页10条,客户端发送请求到某节点
  2. 此节点将数据广播到各个分片,各分片各自查询前 5010 条数据
  3. 查询结果返回至该节点,然后对数据进行整合,取出前 5010 条数据
  4. 返回给客户端

由此可以看出为什么要限制偏移量,另外,如果使用 Search After 这种滚动式API进行深度跳页查询,也是一样需要每次滚动几千条,可能一共需要滚动上百万,千万条数据,就为了最后的20条数据,效率可想而知。

再次和产品对线

<font color="red">俗话说的好,技术解决不了的问题,就由业务来解决!</font>

在实习的时候信了产品的邪,必须实现深度分页 + 跳页,如今必须拨乱反正,业务上必须有如下更改:

  • <font color="red">尽可能的增加默认的筛选条件,如:时间周期</font>,目的是为了减少数据量的展示
  • <font color="red">修改跳页的展现方式,改为滚动显示,或小范围跳页</font>

滚动显示参考图:

小规模跳页参考图:

通用解决方案

短时间内快速解决的方案主要是以下几点:

  • 必备:对排序字段,筛选条件务必设置好索引
  • 核心:<font color="red">利用小范围页码的已知数据,或者滚动加载的已知数据,减少偏移量</font>
  • 额外:如果遇到不好处理的情况,也可以获取多余的数据,进行一定的截取,性能影响并不大

MySQL

原分页SQL:

# 第一页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit 0, 20;

# 第N页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit (N - 1) * 20, 20; 

通过上下文关系,改写为:

# XXXX 代表已知的数据
SELECT * FROM `year_score` where `year` = 2017 and id > XXXX ORDER BY id limit 20;

没内鬼,来点干货!SQL优化和诊断 一文中提到过,LIMIT会在满足条件下停止查询,因此该方案的扫描总量会急剧减少,效率提升Max!

ES

方案和MySQL相同,此时我们就可以随用所欲的使用 FROM-TO Api,而且不用考虑最大限制的问题。

MongoDB

方案基本类似,基本代码如下:

相关性能测试:

如果非要深度随机跳页

如果你没有杠过产品经理,又该怎么办呢,没关系,还有一丝丝的机会。

SQL优化 一文中还提到过MySQL深度分页的处理技巧,代码如下:

# 反例(耗时129.570s)
select * from task_result LIMIT 20000000, 10;

# 正例(耗时5.114s)
SELECT a.* FROM task_result a, (select id from task_result LIMIT 20000000, 10) b where a.id = b.id;

# 说明
# task_result表为生产环境的一个表,总数据量为3400万,id为主键,偏移量达到2000万

该方案的核心逻辑即基于聚簇索引,在不通过回表的情况下,快速拿到指定偏移量数据的主键ID,然后利用聚簇索引进行回表查询,此时总量仅为10条,效率很高。

因此我们在处理MySQLESMongoDB时,也可以采用一样的办法:

  1. 限制获取的字段,只通过筛选条件,深度分页获取主键ID
  2. 通过主键ID定向查询需要的数据

瑕疵:当偏移量非常大时,耗时较长,如文中的 5s

最后

参考文章:MongoDB中文社区

感谢 @程大设计师 为我倾情设计的二维码😜

如果觉得对你有用的话,不要忘记点个赞啊~

查看原文

赞 39 收藏 25 评论 4

leekafai 收藏了文章 · 7月17日

上亿数据怎么玩深度分页?兼容MySQL + ES + MongoDB

面试题 & 真实经历

面试题:在数据量很大的情况下,怎么实现深度分页?

大家在面试时,或者准备面试中可能会遇到上述的问题,大多的回答基本上是分库分表建索引,这是一种很标准的正确回答,但现实总是很骨感,所以面试官一般会追问你一句,<font color="red">现在工期不足,人员不足,该怎么实现深度分页?</font>

这个时候没有实际经验的同学基本麻爪,So,请听我娓娓道来。

惨痛的教训

首先必须明确一点:深度分页可以做,但是<font color="red">深度随机跳页绝对需要禁止。</font>

上一张图:

你们猜,我点一下第142360页,服务会不会爆炸?

MySQLMongoDB数据库还好,本身就是专业的数据库,处理的不好,最多就是慢,但如果涉及到ES,性质就不一样了,我们不得不利用 SearchAfter Api,去循环获取数据,这就牵扯到内存占用的问题,如果当时代码写的不优雅,直接就可能导致内存溢出。

为什么不能允许随机深度跳页

从技术的角度浅显的聊一聊为什么不能允许随机深度跳页,或者说为什么不建议深度分页

MySQL

分页的基本原理:

SELECT * FROM test ORDER BY id DESC LIMIT 10000, 20;

LIMIT 10000 , 20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行。如果是LIMIT 1000000 , 100,需要扫描1000100 行,在一个高并发的应用里,每次查询需要扫描超过100W行,不炸才怪。

MongoDB

分页的基本原理:

db.t_data.find().limit(5).skip(5);

同样的,随着页码的增大,skip 跳过的条目也会随之变大,而这个操作是通过 cursor 的迭代器来实现的,对于cpu的消耗会非常明显,当页码非常大时且频繁时,必然爆炸。

ElasticSearch

从业务的角度来说,ElasticSearch不是典型的数据库,它是一个搜索引擎,如果在筛选条件下没有搜索出想要的数据,继续深度分页也不会找到想要的数据,退一步讲,假如我们把ES作为数据库来使用进行查询,在进行分页的时候一定会遇到max_result_window 的限制,看到没,官方都告诉你最大偏移量限制是一万。

查询流程:

  1. 如查询第501页,每页10条,客户端发送请求到某节点
  2. 此节点将数据广播到各个分片,各分片各自查询前 5010 条数据
  3. 查询结果返回至该节点,然后对数据进行整合,取出前 5010 条数据
  4. 返回给客户端

由此可以看出为什么要限制偏移量,另外,如果使用 Search After 这种滚动式API进行深度跳页查询,也是一样需要每次滚动几千条,可能一共需要滚动上百万,千万条数据,就为了最后的20条数据,效率可想而知。

再次和产品对线

<font color="red">俗话说的好,技术解决不了的问题,就由业务来解决!</font>

在实习的时候信了产品的邪,必须实现深度分页 + 跳页,如今必须拨乱反正,业务上必须有如下更改:

  • <font color="red">尽可能的增加默认的筛选条件,如:时间周期</font>,目的是为了减少数据量的展示
  • <font color="red">修改跳页的展现方式,改为滚动显示,或小范围跳页</font>

滚动显示参考图:

小规模跳页参考图:

通用解决方案

短时间内快速解决的方案主要是以下几点:

  • 必备:对排序字段,筛选条件务必设置好索引
  • 核心:<font color="red">利用小范围页码的已知数据,或者滚动加载的已知数据,减少偏移量</font>
  • 额外:如果遇到不好处理的情况,也可以获取多余的数据,进行一定的截取,性能影响并不大

MySQL

原分页SQL:

# 第一页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit 0, 20;

# 第N页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit (N - 1) * 20, 20; 

通过上下文关系,改写为:

# XXXX 代表已知的数据
SELECT * FROM `year_score` where `year` = 2017 and id > XXXX ORDER BY id limit 20;

没内鬼,来点干货!SQL优化和诊断 一文中提到过,LIMIT会在满足条件下停止查询,因此该方案的扫描总量会急剧减少,效率提升Max!

ES

方案和MySQL相同,此时我们就可以随用所欲的使用 FROM-TO Api,而且不用考虑最大限制的问题。

MongoDB

方案基本类似,基本代码如下:

相关性能测试:

如果非要深度随机跳页

如果你没有杠过产品经理,又该怎么办呢,没关系,还有一丝丝的机会。

SQL优化 一文中还提到过MySQL深度分页的处理技巧,代码如下:

# 反例(耗时129.570s)
select * from task_result LIMIT 20000000, 10;

# 正例(耗时5.114s)
SELECT a.* FROM task_result a, (select id from task_result LIMIT 20000000, 10) b where a.id = b.id;

# 说明
# task_result表为生产环境的一个表,总数据量为3400万,id为主键,偏移量达到2000万

该方案的核心逻辑即基于聚簇索引,在不通过回表的情况下,快速拿到指定偏移量数据的主键ID,然后利用聚簇索引进行回表查询,此时总量仅为10条,效率很高。

因此我们在处理MySQLESMongoDB时,也可以采用一样的办法:

  1. 限制获取的字段,只通过筛选条件,深度分页获取主键ID
  2. 通过主键ID定向查询需要的数据

瑕疵:当偏移量非常大时,耗时较长,如文中的 5s

最后

参考文章:MongoDB中文社区

感谢 @程大设计师 为我倾情设计的二维码😜

如果觉得对你有用的话,不要忘记点个赞啊~

查看原文

leekafai 回答了问题 · 7月13日

Electron如何在主窗口显示子窗口的实时预览?

将 DOM 拷贝一份,在主窗口渲染出来?

Node.cloneNode()

关注 1 回答 1

leekafai 回答了问题 · 7月13日

koa实现通过邮箱找回密码思路或者博客链接

POST /resetWithMail

接受邮箱

用户表里找到了 邮箱 mail= A@a.com

后端自定义一个字符串 S,
生成 hash=MD5(timestamp,S,mail)

yoursite.com/reset_pwd?hash=${hash}&timestamp=${timestamp}&mail=${mail}
发到 A@a.com 中,引导点击

/reset_pwd
检查 timestamp 是否超出当前时间很多 ,可能设置个 5分钟,这样。超出就说明这个没用了。

从 query 中 获取 hash ,用上面的生成方式生成一遍看看是不是一致

一致的话,跳转到一个带授权的密码重置页面。

关注 2 回答 2

leekafai 赞了回答 · 7月13日

nodejs有办法获取到调用者的文件地址吗?

image.png

关注 2 回答 1

leekafai 回答了问题 · 7月13日

在Electron中调用第三方接口时应如何保证token的有效性和安全性?

后端去管理 access_token

关注 1 回答 1

leekafai 赞了回答 · 7月13日

nodejs如何获取多个文件路径的共同根路径?

关注 3 回答 2

leekafai 赞了回答 · 7月13日

解决如何在electron中集成npm或者说node

你需要的是使用npm的能力。
npm本身属于nodejs的一个模块,所以你问题其实可以分成两个来问。

1,如何在客户机上静默安装nodejs并设置好相应的环境变量。
2,如何以编程方式启动npm

第一种方式跟平台紧密相关,实现以及后续维护都比较繁琐,好处是有一个完整独立的nodejs环境。
因为electron自身集成了nodejs,让第二种方法成为可能。

给你一个简单的例子
首先在你electron项目中本地安装npm

npm install npm

之后就可以在业务代码中像普通模块一样使用npm

const { writeFileSync, mkdirSync, existsSync } = require("fs");
const { resolve } = require("path");
const npm = require("npm");
const { homedir } = require("os");

// 建立一个目标文件夹, 并切换到此路径
const dest = resolve(homedir(), "test");
if (!existsSync(dest)) mkdirSync(dest);
process.chdir(dest);

// 写入package.json
writeFileSync(
  resolve(dest, "package.json"),
  JSON.stringify({
    scripts: {
      test: "echo hello npm",
    },
  })
);

npm.load({}, (err) => {
  // npm run
  npm.run("test");

  // npm install
  npm.commands.install(["typescript"], (err) => {
    console.log(err || "done");
  });
});

关注 6 回答 4

leekafai 回答了问题 · 4月1日

跳转传参数 decodeURI()怎么解决 求回复?

str.replace('%','%25')

关注 3 回答 2

认证与成就

  • 获得 55 次点赞
  • 获得 77 枚徽章 获得 2 枚金徽章, 获得 17 枚银徽章, 获得 58 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • bench

    bench 图片批量压缩

注册于 2015-09-14
个人主页被 1.1k 人浏览