伴鱼技术团队

Technology changes the world

伴鱼开放平台 上线了! 源于实践的解决方案,助力企业成就未来!

一、我们为什么要开源

1、我们享受了开源软件巨大的福利

在今天,几乎不可能找到一家没有从开源社区中以某种方式获益过的公司。在伴鱼的发展过程中,我们更是深刻感受到如果没有开源软件的帮助,一个初创公司几乎是没有成功的可能,只有站在linux,tidb,mysql,mongodb,kafka,etcd,nginx,es等伟大的开源软件的肩膀上,我们才能快速搭建好系统,快速向用户提供服务并且快速验证我们的想法,不然这一切将是无法想象的。

站在互联网行业来看,我们更会发现如果没有开源软件,创业成本和创业周期都将大幅提高,这对创业者和创业公司的打击将是非常巨大的打击,整个行业也就不可能得到而此蓬勃的发展。所以我们会发现,大量开源软件的帮助是为什么互联网行业创业热度远远高于传统行业的主要原因之一。

投我以木桃,报之以琼瑶,这是伴鱼人的价值观,虽然我们目前还不能给开源社区非常有力的回馈,那么从当下开始加入开源社区,回报开源社区,将是一个非常好的开始,伴鱼在开源道路上一定会全力以赴。

2、我们已经具备了回馈开源社区的能力

...

阅读全文 »

一、背景介绍

伴鱼少儿英语是目前飞速成长的互联网在线英语教育品牌之一,旗下包括伴鱼绘本、伴鱼少儿英语、伴鱼自然拼读和伴鱼精读课等系列产品。伴鱼使用的数据库种类有Tidb,MongoDB,MySQL,Codis。在伴鱼,目前生产环境共有11套Tidb集群,服务于在线教学、绘本、消息、交易和少儿等众多核心业务。

目前线上Tidb部署版本统一为2.1.15。Tidb server和PD混部,机器配置:64C64G500G SAS;Tikv单独部署,机器配置:64C64G1.5T NVME

下面从伴鱼为何选择Tidb,伴鱼Tidb架构、伴鱼在使用Tidb过程中遇到的问题、我们是如何解决这些问题的以及Tidb在伴鱼的后续使用计划等几个方面进行阐述。

二、伴鱼为何选择Tidb

伴鱼发展之初,选择了MongoDB作为数据存储,但随着业务的快速发展,逐渐暴露出一些问题,比如业务对事务的需求、单表数据极速增长导致的性能问题以及集群实例容量问题等。因此,我们对新存储的诉求有以下几点:

...

阅读全文 »

一、愉快交流

1、候选人和面试官是平等的关系

通常我们会认为面试官是强势的一方,可以决定候选人能否通过面试,但是如果我们跳出面试环节,站在整个招聘流程的角度来看的话,那就未必了,候选人可以在投递简历、面试邀约和接受offer等环节决定是否选择我们,只是这一部分的压力完全被HR承担了,面试官没有感觉到而已。特别地,伴鱼的人才策略是打造面向未来的精英团队,越优秀的候选人可供选择的机会越多,导致这个情况会更加被放大。因此,面试官一定要站在整个招聘流程的角度来对待面试环节,平等地对待每一个候选人,给予候选人足够的尊重,和HR配合一起将招聘工作做好。

所以,候选人和面试官是完全平等的关系,面试官这个称谓的其实是有问题的,面试主持人才是更合理的称谓。

2、面试是教学相长的交流

在面试过程中,要么是面试官提出问题,候选人解答;要么是由候选人分享自己的项目与经历,和面试官进行重复的交流。在候选人解答问题和分享经历的过程中,如果给出的是正确的解决方案,那么面试官应该给予足够的肯定;如果给出的是精彩的解决方案,那么面试官应该给予足够的赞扬;如果给出的解决方案不够完美,那么面试官应该去引导候选人去思考更好的方案。

...

阅读全文 »

Prometheus 是当下最流行的监控平台之一,它的主要职责是从各个目标节点中采集监控数据,后持久化到本地的时序数据库中,并向外部提供便捷的查询接口。本文尝试探讨 Prometheus 存储层的演进过程,信息源主要来自于 Prometheus 团队在历届 PromConf 上的分享。

时序数据库是 Promtheus 监控平台的一部分,在了解其存储层的演化过程之前,我们需要先了解时序数据库及其要解决的根本问题。

TSDB

时序数据库 (Time Series Database, TSDB) 是数据库大家庭中的一员,专门存储随时间变化的数据,如股票价格、传感器数据、机器状态监控等等。时序 (Time Series) 指的是某个变量随时间变化的所有历史,而样本 (Sample) 指的是历史中该变量的瞬时值:

...

阅读全文 »

提到分布式锁,很多人也许会脱口而出 “redis”,可见利用 redis 实现分布式锁已被认为是最佳实践。这两天有个同事问我一个问题:“如果某个服务拿着分布式锁的时候,redis 实例挂了怎么办?重启以后锁丢了怎么办?利用主从可以吗?加 fsync 可以吗?”

因此我决定深究这个话题。

备注:本文中,因为信息源使用的术语不同,Correctness 与 Safety 分别翻译成正确性和安全性,实际上二者在分布式锁话题的范畴中意思相同。

Efficiency & Correctness

如果想让单机/实例上的多个线程去执行同一组任务,为了避免任务被重复执行,使用本地环境提供的 Lock 原语即可实现;但如果想让单机/实例上,或多机/实例上的多个进程去抢同一组任务,就需要分布式锁。总体来说,对分布式锁的要求可以从两个角度来考虑:

...

阅读全文 »

现在我们直接使用官方推荐的 Babel升级工具 来升级现有项目试试

1. 使用Babel升级工具

1
2
3
4
5
6
# 不安装,直接使用npx来执行
npx babel-upgrade --write

# 或是安裝 babel-upgrade 在 global 並執行
yarn global add babel-upgrade
babel-upgrade --write

至此我们可以看到 package.json 中移除了旧版本的依赖,自动新增了新版名称,.babelrc 文件的配置也会自动修改,但是不会删除已有的插件,比如原来的 transform-decorators-legacy

1
2
3
# 移除旧版本依赖后,重新安装依赖
rm -rf node_modules
yarn install

执行这个命令之后就可以看到报错 Cannot find module babel-plugin-syntax-jsx

...

阅读全文 »

我们知道组件和自顶向下的单向数据流帮我们将大型 UI 组织成小的、独立的、可复用的部分。然而,由于逻辑是有状态的,不能提取到函数或其他组件,我们通常无法进一步分解复杂组件。

这些情况非常常见,包括动画、表单处理、异步请求数据等,以及我们希望从组件中完成的许多其他事情。 当我们试图单独使用组件来解决这些用例时,我们通常会得到:

  • 难以重构和测试的大型组件(我们已经制造了很多这种组件)
  • 不同组件和生命周期方法之间的重复逻辑(各种场景都很常见)
  • 发明了很多复杂的模式,比如 Mixins、 Render porp 和 高阶组件(HOC)

    Mixins

    主要应用在ES6普及之前,在还使用React.createClass时是非常常见的一种方式,例如:

    ...

    阅读全文 »

前言

因为goroutine,go的并发非常方便,但是这也带来了另外一个问题,当我们进行一个耗时的异步操作时,如何在约定的时间内终止该操作并返回一个自定义的结果?这也是大家常说的我们如何去终止一个goroutine(因为goroutine不同于os线程,没有主动interrupt机制),这里就轮到今天的主角context登场了。

context源于google,于1.7版本加入标准库,按照官方文档的说法,它是一个请求的全局上下文,携带了截止时间、手动取消等信号,并包含一个并发安全的map用于携带数据。context的API比较简单,标准库实现上也比较干净、独立,接下来我会从具体的使用场景和源码分析两个角度进行阐述。

使用技巧

使用场景一: 请求链路传值

一般来说,我们的根context会在请求的入口处构造如下

1
ctx := context.Background()

...

阅读全文 »

AB 测试(以下称为「试验」),本质是把选择权交给用户,让用户决定什么是最好的。我们给参与试验的不同用户,分配不同的方案,收集用户数据并加以分析,最终确定最优方案。

试验方案的分配可抽象为一个哈希函数,它将一个用户映射为一个试验方案。用户数据一般通过用户行为隐式收集,比如点击、购买、停留时长等。数据的分析则需要依据统计学的假设检验,确保结论的合理性。

需求,从简到繁

这里涉及的概念有「试验」(experiment)和「用户」(user),而逻辑则有「分配方案」、「收集数据」和「分析并得出结论」等。我们从最简单的系统开始,以各种问题挑战这个设计及其背后的假设,以此逐步完善它。

第一个问题是关于用户的,如何支持未登录情况下的试验?一般来说用户是通过 uid 标识的,但未登录时无法得知 uid。如果要支持未登录情况,势必不能以 uid 为用户标识。未登录情况,常规做法是以设备标识 device_id 来做区分,而现实情况是,公司范围内 Web/Android/iOS 三端还未统一 device_id。看来无解了?
换个角度,既然无法控制,就不要控制。平台大可以只定义用户标识(名为 client_id),但其取值完全交由业务方决定。

...

阅读全文 »

背景介绍

在发音评测中,如果一个单词中某个音素读错了,比如apple[ˈæpl]中的p读错了,我们怎么反馈给用户,一般是在其对应的字母里标红如apple,这就引出了一个问题已知一个单词和它对应的音标,如何得到每个音标对应的字母。如apple[ˈæpl] 中a:æ pp:p l:l e不发音

算法介绍

  • 算法路线
    • 深度搜索
    • 多序列对齐问题

深度搜索

深度搜索思路:找到48个元音和辅音对应的常用的字母组合,将音标依次按常用的字母组合展开,当完全展开成单词或者剩余为e的情况停止

...

阅读全文 »