Just Do Java

Java 's Blog


  • 首页

  • 分类

  • 作者

  • 归档

  • 关于

开发者搜索,使用魔法打败魔法

发表于 2021-02-28 | 分类于 Java

大家好,我是阿粉~

搜索引擎应该各位程序员开发中离不开软件吧,日常开发不懂的地方,直接上搜索引擎,大半问题都可以得到解答。

我们时常会把将这种方式戏称为「面向搜索引擎编程」,讲真的如果哪一天搜索引擎真不能打开了,阿粉相信大半程序可能开展不了工作了[狗头]。

目前国内搜索引擎,百度一家独大,如果我们没有特殊的科学上网能力,那只能通过百度了。

但是现在百度搜索体验怎么样,各位读者平常使用过程应该都有点体会吧?

打开「www.baidu.com」,搜索框下方很大的版面是当天的时事新闻,然后右侧就是当天热搜。

这样的页面展示,对于普通大众来说,可以说非常方便。

但是对于开发者来说,干扰信息有点太多了。阿粉记得之前有几次搜索东西,然后就被傍边信息吸引,吃了半天的瓜。

等阿粉回过头的时候才发现,哎,我刚才要干什么来着?

如果此时你没有被这些信息干扰,输入关键信息,然后你就会看到第一条结果是广告,然后往下滑,第四条第五条还是广告。

翻了好几页,可能才找到的想要的结果。

这真不是我们开发者想要的搜索的引擎!!!

开发者搜索

百度搜索实在太难用了,所以阿粉真的好久没有使用了。最近上网的时候无意间发现一款搜索引擎,名叫「开发者搜索」,地址为:

https://kaifa.baidu.com/

从名字上就可以看出,这款产品专门针对「开发者」而开发,另外从网址我们可以看到这款产品竟然是百度开发的???

这个真的有点意外!

果然只有使用魔法才能打败魔法。

打开这个网页,可以看到这个页面真的非常简洁,只有一个简单的搜索框,其他任何信息都没有!

这个页面让阿粉想到很早之前百度的搜索页面~

输入想要搜索信息之后,可以看到搜索结果非常聚焦,没有任何广告。

页面布局与原来百度页面类似:

  • 左侧顶部是各类标签,下方则是搜索页面
  • 右侧为百度百科,以及 gitee 上开源项目

仔细看开发者搜索的搜索结果,可以发现目前搜索结果仅仅来源于知乎、CSDN以及博客园三个站点。从这一点来说,其实比较可惜了,虽然这三个网站已经包含大量的文章了,但是其实还是源源不够。

其实很多个人独立网站,比如阮一峰老师,左耳朵耗子的博客网站,里面的内容其实质量也比较高。

不过也可以理解,毕竟现在「开发者搜索」仅仅是 Beta 版本,不完善也是正常。

那这里还是希望百度可以完善这款产品,真正帮到国内的开发者。

其他搜索引擎

那说实话,现在对开发者最友好的引擎,阿粉觉得还是 「Google 」搜索了。

无论是搜索结果的准确度,又或是显示站点的质量,都比百度号上一截。

不过由于神秘的东方的力量,这网站已经不能在国内正常打开。

不过这一点,我觉得应该难不倒爱折腾的程序员们,所以如果你能打开「Google 」,那就赶紧抛弃百度吧~

最后对于一些没办法打开「Google 」的小伙伴,再推荐一个搜索引擎,那就是微软的「必应搜索」。

打开必应搜索的首页,可以看到页面非常简洁,并且背景图还是一些高清壁纸,视觉感非常舒服。

另外可以看到搜索框上可以分为国内版跟国际版,那这两者主要区别在于:

  • 国内版适合中文搜索
  • 国际版适合使用英文搜索

最后

如果大家可以打开「Google」搜索,那阿粉真心建议你们直接使用 Google。阿粉这几年用下来,使用体验真的非常好,搜索结果也比较准确,真的非常适合开发者使用。

哎,百度「开发者搜索」加把劲吧,什么时候真的把功能完善好,让国内开发者搜索更加简单高效一点~

加油吧,百度~

阅读全文 »

当代码 Review 变成形式主义过后

发表于 2021-02-27 | 分类于 Java

你做过代码 Review 吗?

Hello 大家好我是阿粉,代码 Review 相信大家一定不会陌生,但是真正在日常工作中能使用并且坚持执行下去的公司或者团队,阿粉觉得并不多,但是代码 Review 的好处大家都是有目共睹的,很多招聘岗位上面都有这样的要求,坚持执行代码 Review 对团队,对公司是很有好处的,特别是对写代码的同事!每个一起阅读代码的同事都会提出一些自己的建议 ,这些建议都是很宝贵的资源,往往都会有很大的收获。

那么如何做好一场代码 Review 呢?想要做好一场合格的代码 Review,首先我们需要知道代码 Review 的过程中都有哪些角色以及需要怎样的流程。

角色

  1. 代码的作者 Author;
  2. 阅读代码的同事 Reviewer;
  3. 主持人 Host;
  4. 记录员 Recorder。

流程

  1. 提前一天发送 Review 代码邮件给相关人员,确定 Host 和 Recorder;
  2. 由 Host 主持 Review 会议;
  3. 由 Reviewer 和 Author 进行代码走读;
  4. 由 Recorder 进行改进记录。

在做代码 Review 之前 Author 需要提前一天需要发正式邮件给相关人员,并且将需要被 Review 的代码通过邮件附件的方式,发送给相关的 Reviewer 让他们提前阅读,这样有助于 Review 的时候可以更高效的进行。并且提前沟通好代码 Review 的会议 Host 和 Recorder。Host 在会议过程中负责组织大家发言和维护秩序,让代码 Review 更高效;Recorder 则负责将整个 Review 过程中提到的需要优化和改进的点进行文档形式的记录,记录的信息需要言简意赅,将哪个文件哪一行代码,问题是什么,建议怎么优化都需要记下来,并且在会议结束过后以邮件的形式发送给 Author 和抄送大家。

Review

在进行代码 Review 的时候 Author 需要从文件的第一行开始进行一行行的代码走读,对每一行的代码进行描述,这里需要注意的是不要认为某个功能很简单,就可以一句带过,往往很多线上 Bug 都是因为这种忽略导致的。走读代码的时候 Author 需要解释清楚每一行代码的含义,说明这行代码是干嘛的,为什么要这样写。Reviewer 则需要根据 Author 的描述再结合自己之前阅读代码的理解进行提问或者改进方案。

代码走读的过程持续进行的同时 Recorder 需要及时记录需要改进的内容,并把提出的优化方案记录下来。代码走读的过程是整个 Review 的核心,在这个环节中我们需要注意很多东西。知乎上面有个提问大家的公司的 Code Review 都是怎么做的?遇到过哪些问题?,上面有个回答提出的几个点很不错,我觉得有必要分享给大家,对我们的整个 Review 会很有帮助,特别是当自己是 Reviewer 的时候,需要格外注意。

  1. 对事不对人。要记住大家都是同事,今天自己是 Reviewer 来对别人的代码进行 Review,哪天别人就会对自己的代码进行 Review,所以在整个代码 Review 的环节中,我们可以提出自己的建议,但是需要注意自己的用词和语气,虽然程序员有鄙视链,并且都认为别人的代码垃圾,但是这种时候不能瞎说,容易打架的,还是要谦虚点。
  2. 用正面的词汇进行评价。跟上面说的一样,我们需要用正面的词汇进行评价代码,考虑 Author 的情绪,即使代码写的不好。这个很好理解,毕竟代码 Review 是在很多人面前的,对 Author 来说,让别人看自己写的代码就像在别人面前裸奔一样,所以我们不仅要提出意见在好的地方我们也要进行正向的表扬。
  3. 如果有更好的方案一定要提出来。代码 Review 的目的就是优化代码,找出代码中的隐藏 BUG 以及逻辑问题。所以如果发现了代码有任何不优雅的地方或者会出现问题的地方一定要及时的提出来,不要担心自己说的不对,或者考虑 Author 的面子问题,不指出来,提供更好的解决方案,让大家一起进步。
  4. Review 会议是 Review 代码,而不是讨论需求。这一点也是很容易被带偏的一个点,经常我们会发现在 Review 的过程中,慢慢的就变成了讨论需求了,这种情况一定要避免发生,不然整个代码 Review 环节就是失败的,无法进行下去了。所以 Author 在发起代码 Review 邀请时一定要确保自己理解的需求是正确的,避免浪费大家的时间。
  5. 高效的进行。进行代码 Review 的时候我们需要注意一定要高效,如何做到高效就需要每个人都做好相应的准备,Author 需要对自己的代码进行熟练的讲解,Reviewer 需要在参加会议之前将需要 Review 的代码看一下,提前找到可能隐藏的 Bug,对于不懂地方需要做好记录,方便开会的时候及时指出。
  6. 避免形式主义。这一点也是被很多小伙伴忽略的一点,随着代码 Review 的次数越来越多,很多小伙伴可能就把这个当成一个任务,慢慢的就变成了形式主义,而不是注重实际,每次代码 Review 的时候就很随意,长期这样下去对公司,团队以及自己都不好,而且还浪费时间。

总结

阿粉今天给大家介绍了一个如何做一个合格的代码 Review,当然这只是阿粉自己的一些见解,大家有任何意见可以在评论区给我们留言,也可以加入我们的微信群,大家一起交流学习。

阅读全文 »

从毕业到实习再到工作,感觉自己走了狗屎运

发表于 2021-02-14 | 分类于 程序人生

相信关注我们 Java 极客技术的朋友大部分都是程序员,那么你还记得自己是怎么踏上这条致(不)富(归)路的吗?

今天大年初五,距离上班没有几天的时间了,今天跟大家分享一下阿粉是如何走上程序员的道路的,阿粉的经历只是一个缩影,相信有很多人跟阿粉一样,更有很多比阿粉优秀的人也在坚持着。

阿粉记得高考结束填志愿的时候,当时志愿填的都是计算机相关的专业,那会什么也不懂,只知道计算机听上去很高大上但是具体干什么的,完全不知道。就这样懵懵懂懂的进了计算机学院并且选修了网络工程专业,刚开始我以为同学都跟我一样是因为对计算机的热爱才进了这个专业,但是慢慢的才发现本班很多人是调剂过来的,都是因为选的其他专业人数满了,最后被调剂到计算机学院的,而且当时我们学校的计算机学院是第一年招生。

但是不管怎样对外还是可以说是计算机科班出身,但是阿粉我接触电脑还是比较晚的,接触编程也是上大学才开始的,出身农村,小时候根本没用过电脑,不像有些朋友从小就接触电脑接触编程。

接触的第一门编程语言毫无疑问《谭浩强的 C 语言》,相信很多人都跟阿粉一样从这本书开始了自己的编程生涯。对于这本书的褒贬我不做评价,有人说不好,有人说好,但是既然能出书并能被纳入大学教材自然有它的道理。

刚接触编程语言的时候,第一感觉就是,这也太神奇好玩了吧!只要在屏幕上输入一些特定的字符,就能实现动画,做出网页,并且可以解决一些问题,感觉太有意思了。都说男人的成长是因为压力,大学头两年是在懵懵懂懂中度过的,有课的时候上课,没课的时候就打游戏睡觉,到处玩,一点生活压力都没有。大三的时候觉得快要实习找工作了,不能再浪费时间,然后就天天在实验室里面看各种技术视频,跟着视频一行一行敲代码,跟着视频里面的老师做了一个小小的静态网站傻傻的开心了好几天,所以说有时候成长就是一瞬间的事情还是很有道理的。

后面实验室老师接项目,让我们帮他做,给我们每个人每个月三千多块钱,那个时候当其他专业的朋友还在跟家里要生活费,各种花钱买实验设备的时候,我们这个专业的同学都已经自食其力挣钱了,既能学东西又能挣点零花钱,不用跟家里要生活费,感觉还是很棒的,特别有成就感。

后来大三暑假的时候找了一家公司进行了两个月的实习,实习的过程中就发现书本上学到的东西跟实际工作中遇到的问题真是南辕北撤,而且主要是在学校里面老师教的很多东西,在工作中已经不用了,那个时候就发现学校跟社会有一点脱轨,虽然说原理都是一样的,但是难免工作的时候动手能力还稍微差了点。

所以以过来人经验告诉那些还没有毕业,快要毕业的朋友,一定要多在网上看看资料,多看看一些招聘网站上的要求,提前多学习一下。

经过两个月的实习过后,公司觉得各方面不错阿粉也觉得机会难得,双方就签了意向书,毕业后可以直接入职。实习后既然工作已经定了,阿粉就没有再找过其他公司,而是一门心思的在提升技能(这个现在想想挺后悔的,还是要去大公司试试~~)。毕业后直接入职,留下来工作了。

就这样阿粉一步一步的走上了程序员的这条路,自从走上这条路,虽然头发日渐稀少,逐渐油腻起来,但是阿粉还是很开心和快乐的,因为热爱,因为梦想,毕竟每个程序员都有一颗让世界变的更美好的心!

互联网行业学无止境,未来的路还有很长,有的人是因为喜爱走上了这条路,有的人是因为谋生走上了这条路,有的人是因为梦想走上了这条路,那么你呢?是因为什么走上了这条路呢?

《孙子兵法》中有一句:“胜者先胜而后求战,败者先战而后求胜”。胜者之所以能常胜是因为在开战之前就已经洞悉了一切,做好了充分的准备,有着百分百必胜的把握,而后才会开战,自然必胜。而败者在开战前没有任何准备,直到战争开始才想着怎样取胜,这样失败的概率必然很大。

总结给我们的知识就是在做任何事情的时候都要做好准备,只有自己准备的充分,才能取得最大的胜利,也就是我们常说的知己知彼,百战不殆。不仅是对待某件事情,对待我们的人生都应该这样,前期做好准备,集聚能量,蓄势待发,在关键时刻必然一飞冲天。

与君共勉!

阅读全文 »

社交软件已经到达瓶颈了吗?马克思携 ClubHouse 告诉你没有!

发表于 2021-02-07 | 分类于 Java

序言

最近一款被马克斯带火的社交软件 ClubHouse 在科技圈被广泛讨论,所以最近在各大技术群和论坛里面往往看到的都是求一个邀请码,如下图所示,不得不说真是一码难求。那这个 ClubHouse 到底是个什么样的 APP,为什么这么火爆呢?

软件介绍

ClubHouse 首先是一个语音社交软件,这个软件的模式是采用手机号邀请制注册,只要注册的手机号被别人邀请到,就同样会有两个邀请名额。通过通讯录找到都注册了的朋友,然后就可以开个聊天室在里面聊天。每一个聊天室里面都会有一个主持人以及会邀请一些嘉宾,他们每个人都可以针对特定的主题进行分享,旁听的听众可以只旁听,也可以举手申请发言,只要被主持人同意就可以跟嘉宾一起交流。

看上去其实很普通的一个软件,为什么突然一下子火起来呢?阿粉主要觉得有这么几点,第一个是赶上了疫情,国外很多人在家没事做,打字聊天太慢,视频聊天太正式,而语音则刚刚好,不管自己是坐着还是躺着都可以。第二个是邀请制,就跟早期的知乎一样,如果一个软件的模式是邀请制,那么这个人群的质量就可以有保证,因为毕竟都是一个圈子的人才会互相邀请。第三个是名人效应做的好,刚开始内测的用户都是知名人士,特别是经过马克思在一次采访上面提到自己会开一个聊天室分享,这对于很多人来说能有一个跟大佬一起在一个虚拟房间聊天的机会是很可贵的。说不定举手发言被同意,还能直接跟大佬提问,这对于自己的成长绝对是“听君一席话胜读十年书”。

下载安装

阿粉经过一个下午的努力,成功的下载和注册体验了一下,总的来说整个体验还是不错的(就是好多外国人的聊天室进去听不懂),整个交互很简单,大大的创建聊天室的按钮,然后主页面就是一个个聊天室,随便点击就可以进去旁听,有的聊天室人多,有的聊天室人少。可以找到自己感兴趣的聊天室直接点击进去旁听,也可以申请发言直接交流。

最上面最左右是搜索功能,可以搜索好友或者聊天室,右边第一个邮件菜单就是邀请好友功能,每个成功被邀请注册的都有两个名额可以邀请别人(有朋友反馈在填写注册信息的时候要多选择几个自己喜欢的领域和关注一些人,不然没有邀请名额)。

上面简单说了一下软件的使用,但是在这之前我们需要先下载安装,目前 ClubHouse 这款软件只能在 iOS 上面运行,也就是只有苹果手机才能玩,另外这个软件在中国大陆的 App Store 是下载不了的,我们需要注册一个国外的 Apple Id 才能下载。所以我们要想体验这个软件,需要做如下几个事情。

  1. 注册国外的 Apple Id;
  2. 下载 ClubHouse 并注册;
  3. 找有邀请资格的朋友邀请(确保邀请的手机号和之前注册的手机号一致);

首先我们在苹果网站注册一个 Apple Id ,主要一个邮箱和手机号,然后地址记得不要选中国大陆,对于要填写的地址,邮编或电话直接在网上搜搜就可以了。

等到注册验证结束后,在手机设置里面媒体与购买项目菜单进行账号切换,切换到国外的账号,然后再到 App Store 里面去搜 ClubHouse 就可以搜索到了,然后认准下面的图标进行下载。

下载完过后通过手机号就可以进行注册,但是这个时候只能提供手机号和验证码,并不能进入软件里面,只能显示如下内容。进行到这里过后剩下的自己能做的就能到处找人邀请了。

总结

最后简单说下,阿粉在第一天使用的时候旁听了几个,感觉还是很有意思的。其中有一个聊天室标题叫做“我是美团骑手,我想跟美团 PM 聊聊” 在这个聊天室里面大家就如何帮忙残障人士点餐或者送外卖进行了讨论,虽然不一定有美团的产品经理能听到,但是感觉大家都想做点什么,还是挺有意思的。

阅读全文 »

阿粉来粉碎一下朋友圈谣言

发表于 2021-02-06 | 分类于 程序生活

这不过年了,有的朋友就和阿粉说,不敢吃辣,阿粉就有点儿懵了,咋了呀,为啥不敢吃辣嘞

阅读全文 »

未命名

发表于 2021-03-05
阅读全文 »

看完这篇文章,小白都会开启防火墙特定端口了

发表于 2021-02-06 | 分类于 运维

手把手教

阅读全文 »

一文带你看懂 Redis BitArray 如何实现高性能的位操作

发表于 2021-02-01 | 分类于 Java

Redis 作为当代互联网行业无可替代的 Key-Value 数据库,在我们日常的工作中占据主要的角色,对于常用的命令相信大家都很熟悉。今天给大家分享一个平时可能用到的少,但是也很重要的一个类型 BitArray。我们先通过简单的命令使用,了解该命令的用法,然后再给大家介绍一下底层的实现原理,帮助大家更好的了解。

简单使用

我们先看下什么是BitArray 位数组。Redis 使用字符串对象来存储位数组,一个 Byte 字节有 8 个 bit 位,通过控制每一个 bit 位为 0 或者 1来表示某个元素对应的值或者状态。通过使用 8 个 bit 位可以对复杂操作节省很多的空间。BitArray 相关的操作命令有 SETBIT,GETBIT,BITCOUNT,BITOP。下面我们依次看下命令的使用,最后再看下实现的原理。

首先我们在本地启动一个 Redis 实例,再启动一个客户端去链接如下图,

通过redis-cli 链接客户端,执行相应的命令,接下来使用一下 BitArray 相关的命令,

通过setbit test 2 1 命令我们创建了一个名为 test 的 bitarray 并将其第二位设置成 1,再使用getbit test 2 获取对应位的值。setbit命令功能是将对应的 key 指定 offset 的位置设置为 1 或 0,getbit 命令是获取指定 offset 位置的值。test 是一个位数组通过上面的命令值变成0000 0010 。

接下来我们再创建一个名为test2的位数组,并且通过多次使用 setbit 命令和 bitcount ,bitcount 命令的作用是用来统计位数组中 1 的个数,通过下面我们看到第一次使用 bitcount test2 命令时结果为 1,当使用了 setbit test2 1 1 命令后再次使用 bitcount 命令我们发现结果已经变成 2 了。其中 test2 的刚开始是0000 0100 后面变成0000 0101。

bitop 命令相信大家都能理解,都是一些与,或,异或,非的运算,就不赘述了,具体使用可以看上图。

原理

前面说到 Redis 是通过字符串对象来实现位数组的,所以字符串对象有的功能,在位数组上面都是有的,在Redis 底层位数组的存储结构也是基于 SDS (简单动态字符串)的,如下:

其中 len 字段表示包含的 buf 数组的个数,buf[i] 表示的是第i个字节数组里面具体的数值,buf[len] 是末尾的分隔符\0 。上图中的buf[0] 是一个字节,其中有 8 个 bit 位,在使用了 setbit 命令后初始值为0000 0000,buf[1] 中就是分隔符\0。

SETBIT

当我们执行setbit key offset value 命令时,我们分两步:

  1. 计算出创建多少个字节数组(offset / 8) + 1;
  2. 判断是否长度不够需要进行扩容;
  3. 计算出 offset 对应的字节位置 byte = offset / 8;
  4. 计算出 offset 对应的 bit 位,bit = (offset mod 8) + 1;
  5. 根据 offset 找到对应的位置将此处的值改成value 并返回旧值;

假设我们执行的命令时setbit test2 3 1,第一步先计算字节个数 (3 / 8) + 1 = 1,计算出来我们只需要一个字节;第二步跟原始 len 进行比较,发现不需要扩容;3. 根据 offset 计算存放的字节 3 / 8 = 0 则,存放的 buf[0] 中;第四部计算 bit,( 3 mod 8) + 1 = 4,表示的是第四个 bit 位。经过一轮 test2 就变成了 0000 1000。

setbit 命令执行的操作都是常数级别的,时间复杂度为 O(1)。

GETBIT

我们知道的setbit 命令是如何实现的,那么getbit 命令也就知道如何计算了,过程是类似的。

  1. 找到对应的字节数组 byte = offset / 8;
  2. 计算出对应的 bit 位bit = (offset mod 8) + 1;

经过上面的计算我们可以知道当执行命令 getbit test2 3 的时候,先算出 3 / 8 = 0 ,找到 buf[0],再使用(3 mod 8) + 1 = 4,找到 bit 位。

看到这里细心的小伙伴就会有疑问,会说不对啊,根据这个计算返回的值应该是 0 啊,因为上面 setbit命令执行完的结果是0000 1000 啊。

能发现这个问题的小伙伴说明很用心在看了,这里就要跟大家说下了,虽然 setbit 命令执行完结果是0000 1000 但是在 buf[0] 中存储的确实反过来的,即为0001 0000。采用的是逆序的方式来保存位数组的。

之所以采用逆序保存位数组是为了减少位数组的移动,提高性能,感兴趣的小伙伴可以自行研究一下。

BITCOUNT 命令

bitcount 命令是用来计算一个位数组中 1 的个数,说起来比较简单,但是实现起来却很有讲究。我们设想一下,统计一个位数组中 1 的个数有多少个,最简单的办法就是遍历,依次累加。但是当我们的位数组很大的时候,整个效率就会变得非常慢,因为遍历是跟长度正相关的,当存放 100MB 的位数组整个遍历需要八亿次。而当达到 500MB 时整个遍历就达到了四十亿次!

在 Redis 中采用的是查表和 variable-precision SWAR 算法,查表是指当位数组长度小于 128 时,直接根据预设的映射表找到对应 1 的个数,直接返回。而variable-precision SWAR 算法相对比较复杂,阿粉也还要再研究研究,今天就先不分享了。

BITOP 命令

bitop 命令相对简单一点,因为 Redis 底层是基于 C 语言实现的,C语言本身就支持相关的逻辑运算。因为本身就是二进制位数组,所以对应的逻辑运算会简单很多就不赘述了,相信大家都能理解。

参考资料

Redis 设计与实现(第二版)

阅读全文 »

一则道歉声明将某度推上风口浪尖

发表于 2021-01-24 | 分类于 Java

Hello 大家好,我是阿粉,相信最近大家都看到郑爽父亲的那个道歉视频,原本这件事情已经过去了,但是这则道歉视频里面的大大的某品牌 Logo 闪瞎了阿粉的狗眼,话不多说,见下图。

image-20210125231237658

说真的这种负面新闻正常的品牌应该都是退而避之,恨不得立马躲得远远的,像之前的任何娱乐圈的人出了事,各大代言的品牌都立马下架商品,而某度的这种“迎难而上”的做法,真的让人不能理解。

事情发酵的很快,随着道歉视频的出来,很多网友都发现了这个品牌的 Logo ,一时间各种批判的声音都出来了,而且据说这个事情在百度内部的高管群里都被讨论了。随后某度官微也出来道歉了,表示说诚恳的接受大家的批判,而且在这个视频中出现 Logo 不涉及任何经济行为,其中的细节作为局外人阿粉就不了解了,有没有经济行为大家自行脑补就行。

文中提到会诚恳接受大家的批评,对给网友带来的不好感受表示非常抱歉,并强调这个视频访谈不涉及任何经济行为,昨天第一时间在相关账号中下线了该内容。还表示:“孩子的话题背后公众表达的是同理心、同情心,人们希望的是事情得到最好的解决。关切越深期待越高,我们必将在未来的工作中加倍严谨、严肃,充分考虑每一位朋友的感受。“经过处理过后,部分网上的视频都做了打码处理,屏蔽了相关文字信息。

相关的道歉视频大家可以公众号后台回复【道歉】查看

我们都知道这么做是不对的,因为大家都知道品牌效应,一个品牌的 Logo 代表了一个品牌的价值观。为什么那些大牌在代言人出现负面新闻的时候都紧急下线商品,并且解约呢?这是因为如果不这样做就会影响到品牌的形象,而对于一个品牌来说,一旦品牌的形象受到负面影响那将会是重大损失,很有可能一去不复返。虽说当今的互联网是流量的时代,得流量者得天下,但是获取流量也不能通过蹭这种负面新闻的热度来获取,这种行为只会让人更加厌恶。

阅读全文 »

未命名

发表于 2021-03-05
阅读全文 »

看完这篇文章,别再说不会 Redis 的高级特性了

发表于 2021-02-22 | 分类于 Redis

Redis 作为后端工程师必备的技能,阿粉每次面试的时候都会被问到,阿粉特意把公号前面发过的 Redis 系列文章整理出来,自己学习同时也帮助大家一起学习。

Redis 的数据类型有哪些?

Redis 五种数据类型,每种数据类型都有相关的命令,几种类型分别如下:

  1. String(字符串)

  2. List(列表)

  3. Hash(字典)

  4. Set(集合)

  5. Sorted Set(有序集合)

Redis 有五种常见的数据类型,每种数据类型都有各自的使用场景,通用的字符串类型使用最为广泛,普通的 Key/Value 都是这种类型;列表类型使用的场景经常有粉丝列表,关注列表的场景;字典类型即哈希表结构,这个类型的使用场景也很广泛,在各种系统里面都会用到,可以用来存放用户或者设备的信息,类似于 HashMap 的结构;Redis set 提供的功能与列表类型类似也是一个列表的功能,区别是 Set 是去重的;有序集合功能与 Set 一样,只不过是有顺序的。

Redis 的内存回收与Key 的过期策略

Redis 内存过期策略

过期策略的配置

Redis 随着使用的时间越来越长,占用的内存会越来越大,那么当 Redis 内存不够的时候,我们要知道 Redis 是根据什么策略来淘汰数据的,在配置文件中我们使用 maxmemory-policy 来配置策略,如下图

image-20191113214158260

我们可以看到策略的值由如下几种:

  1. volatile-lru: 在所有带有过期时间的 key 中使用 LRU 算法淘汰数据;
  2. alkeys-lru: 在所有的 key 中使用最近最少被使用 LRU 算法淘汰数据,保证新加入的数据正常;
  3. volatile-random: 在所有带有过期时间的 key 中随机淘汰数据;
  4. allkeys-random: 在所有的 key 中随机淘汰数据;
  5. volatile-ttl: 在所有带有过期时间的 key 中,淘汰最早会过期的数据;
  6. noeviction: 不回收,当达到最大内存的时候,在增加新数据的时候会返回 error,不会清除旧数据,这是 Redis 的默认策略;

volatile-lru, volatile-random, volatile-ttl 这几种情况在 Redis 中没有带有过期 Key 的时候跟 noeviction 策略是一样的。淘汰策略是可以动态调整的,调整的时候是不需要重启的,原文是这样说的,我们可以根据自己 Redis 的模式来动态调整策略。 ”To pick the right eviction policy is important depending on the access pattern of your application, however you can reconfigure the policy at runtime while the application is running, and monitor the number of cache misses and hits using the Redis INFO output in order to tune your setup.“

策略的执行过程

  1. 客户端运行命令,添加数据申请内存;
  2. Redis 会检查内存的使用情况,如果已经超过的最大限制,就是根据配置的内存淘汰策略去淘汰相应的 key,从而保证新数据正常添加;
  3. 继续执行命令。

近似的 LRU 算法

Redis 中的 LRU 算法不是精确的 LRU 算法,而是一种经过采样的LRU,我们可以通过在配置文件中设置 maxmemory-samples 5 来设置采样的大小,默认值为 5,我们可以自行调整。官方提供的采用对比如下,我们可以看到当采用数设置为 10 的时候已经很接近真实的 LRU 算法了。

image-20191113231007725

在 Redis 3.x 以上的版本的中做过优化,目前的近似 LRU 算法以及提升了很大的效率,Redis 之所以不采样实际的 LRU 算法,是因为会耗费很多的内存,原文是这样说的

The reason why Redis does not use a true LRU implementation is because it costs more memory.

Key 的过期策略

设置带有过期时间的 key

前面介绍了 Redis 的内存回收策略,下面我们看看 Key 的过期策略,提到 Key 的过期策略,我们说的当然是带有 expire 时间的 key,如下

image-20191113233350118

通过 redis> set name ziyouu ex 100 命令我们在 Redis 中设置一个 key 为 name,值为 ziyouu 的数据,从上面的截图中我们可以看到右下角有个 TTL,并且每次刷新都是在减少的,说明我们设置带有过期时间的 key 成功了。

Redis 如何清除带有过期时间的 key

对于如何清除过期的 key 通常我们很自然的可以想到就是我们可以给每个 key 加一个定时器,这样当时间到达过期时间的时候就自动删除 key,这种策略我们叫定时策略。这种方式对内存是友好的,因为可以及时清理过期的可以,但是由于每个带有过期时间的 key 都需要一个定时器,所以这种方式对 CPU 是不友好的,会占用很多的 CPU,另外这种方式是一种主动的行为。

有主动也有被动,我们可以不用定时器,而是在每次访问一个 key 的时候再去判断这个 key 是否到达过期时间了,过期了就删除掉。这种方式我们叫做惰性策略,这种方式对 CPU 是友好的,但是对应的也有一个问题,就是如果这些过期的 key 我们再也不会访问,那么永远就不会删除了。

Redis 服务器在真正实现的时候上面的两种方式都会用到,这样就可以得到一种折中的方式。另外在定时策略中,从官网我们可以看到如下说明

Specifically this is what Redis does 10 times per second:

  1. Test 20 random keys from the set of keys with an associated expire.
  2. Delete all the keys found expired.
  3. If more than 25% of keys were expired, start again from step 1.

意思是说 Redis 会在有过期时间的 Key 集合中随机 20 个出来,删掉已经过期的 Key,如果比例超过 25%,再重新执行操作。每秒中会执行 10 个这样的操作。

Redis 的发布订阅功能你知道吗?

发布订阅系统在我们日常的工作中经常会使用到,这种场景大部分情况我们都是使用消息队列的,常用的消息队列有 Kafka,RocketMQ,RabbitMQ,每一种消息队列都有其特性。其实在很多时候我们可能不需要独立部署相应的消息队列,只是简单的使用,而且数据量也不会太大,这种情况下,我们就可以考虑使用 Redis 的 Pub/Sub 模型。

使用方式

发布与订阅

Redis 的发布订阅功能主要由 PUBLISH,SUBSCRIBE,PSUBSCRIBE 命令组成,一个或者多个客户端订阅某个或者多个频道,当其他客户端向该频道发送消息的时候,订阅了该频道的客户端都会收到对应的消息。

image-20191222092832322

上图中有四个客户端,Client 02,Client 03,Client 04 订阅了同一个Sport 频道(Channel),这时当 Client 01 向 Sport Channel 发送消息 “basketball” 的时候,02-04 这三个客户端都同时收到了这条消息。

整个过程的执行命令如下:

首先开四个 Redis 的客户端,然后在 Client 02,Client 03,Client 04 中输入subscribe sport 命令,表示订阅 sport 这个频道

image-20191222093131988

然后在 Client 01 的客户端中输入publish sport basketball 表示向 sport 频道发送消息 “basketball”

image-20191222093149658

这个时候我们在去看下Client 02-04 的客户端,可以看到已经收到了消息了,每个订阅了这个频道的客户端都是一样的。

image-20191222093412149

这里 Client 02-Client 04 三个客户端订阅了 Sport 频道,我们叫做订阅者(subscriber),Client 01 发布消息,我们叫做发布者(publisher),发送的消息就是 message。

模式订阅

前面我们看到的是一个客户端订阅了一个 Channel,事实上单个客户端也可以同时订阅多个 Channel,采用模式匹配的方式,一个客户端可以同时订阅多个 Channel。

image-20191222141017693

如上图 Client 05 通过命令subscribe run 订阅了 run 频道,Client 06 通过命令psubscribe run* 订阅了 run* 匹配的频道。当 Client 07 向 run 频道发送消息 666 的时候,05 和 06 两个客户端都收到消息了;接下来 Client 07 向 run1 和 run_sport 两个频道发送消息的时候,Client 06 依旧可以收到消息,而 Client 05 就收不到了消息了。

Client 05 订阅run 频道和接收到消息:

image-20191222141441686

Client 06 订阅run* 频道和接收到消息:

image-20191222141458065

Client 07 向多个频道发送消息:

image-20191222141514914

通过上面的案例,我们学会了一个客户端可以订阅单个或者多个频道,分别通过subscribe,psubscribe 命令,客户端可以通过 publish 发送相应的消息。

在命令行中我们可以用 Ctrl + C 来取消相关订阅,对应的命令时 unsubscribe channelName。

Pub/Sub 底层存储结构

订阅 Channel

在 Redis 的底层结构中,客户端和频道的订阅关系是通过一个字典加链表的结构保存的,形式如下:

image-20191222161405136

在 Redis 的底层结构中,Redis 服务器结构体中定义了一个 pubsub_channels 字典

1
2
3
4
struct redisServer {
	//用于保存所有频道的订阅关系
	dict *pubsub_channels;
}

在这个字典中,key 代表的是频道名称,value 是一个链表,这个链表里面存放的是所有订阅这个频道的客户端。

所以当有客户端执行订阅频道的动作的时候,服务器就会将客户端与被订阅的频道在 pubsub_channels 字典中进行关联。

这个时候有两种情况:

  • 该渠道是首次被订阅:首次被订阅说明在字典中并不存在该渠道的信息,那么程序首先要创建一个对应的 key,并且要赋值一个空链表,然后将对应的客户端加入到链表中。此时链表只有一个元素。
  • 该渠道已经被其他客户端订阅过:这个时候就直接将对应的客户端信息添加到链表的末尾就好了。

比如,如果有一个新的客户端 Client 08 要订阅 run 渠道,那么上图就会变成

image-20191222161526069

如果 Client 08 要订阅一个新的渠道 new_sport ,那么就会变成

image-20191222161558999

整个订阅的过程可以采用下面伪代码来实现

1
2
3
4
5
6
7
8
9
10
Map<String, List<Object>> pubsub_channels = new HashMap<>();
    public void subscribe(String[] subscribeList, Object client) {
        //遍历所有订阅的 channel,检查是否在 pubsub_channels 中,不在则创建新的 key 和空链表
        for (int i = 0; i < subscribeList.length; i++) {
            if (!pubsub_channels.containsKey(subscribeList[i])) {
                pubsub_channels.put(subscribeList[i], new ArrayList<>());
            }
            pubsub_channels.get(subscribeList[i]).add(client);
        }
    }

取消订阅

上面介绍的是单个 Channel 的订阅,相反的如果一个客户端要取消订阅相关 Channel,则无非是找到对应的 Channel 的链表,从中删除对应的客户端,如果该客户端已经是最后一个了,则将对应 Channel 也删除。

1
2
3
4
5
6
7
8
9
10
public void unSubscribe(String[] subscribeList, Object client) {
        //遍历所有订阅的 channel,依次删除
        for (int i = 0; i < subscribeList.length; i++) {
            pubsub_channels.get(subscribeList[i]).remove(client);
            //如果长度为 0 则清楚 channel
            if (pubsub_channels.get(subscribeList[i]).size() == 0) {
                remove(subscribeList[i]);
            }
        }
    }

模式订阅结构

模式渠道的订阅与单个渠道的订阅类似,不过服务器是将所有模式的订阅关系都保存在服务器状态的pubsub_patterns 属性里面。

1
2
3
4
struct redisServer{
	//保存所有模式订阅关系
	list *pubsub_patterns;
}

与订阅单个 Channel 不同的是,pubsub_patterns 属性是一个链表,不是字典。节点的结构如下:

1
2
3
4
5
6
struct pubsubPattern{
	//订阅模式的客户端
	redisClient *client;
	//被订阅的模式
	robj *pattern;
} pubsubPattern;

其实 client 属性是用来存放对应客户端信息,pattern 是用来存放客户端对应的匹配模式。

所以对应上面的 Client-06 模式匹配的结构存储如下

image-20191222174528367

在pubsub_patterns链表中有一个节点,对应的客户端是 Client-06,对应的匹配模式是run*。

订阅模式

当某个客户端通过命令psubscribe 订阅对应模式的 Channel 时候,服务器会创建一个节点,并将 Client 属性设置为对应的客户端,pattern 属性设置成对应的模式规则,然后添加到链表尾部。

对应的伪代码如下:

1
2
3
4
5
6
7
8
9
10
List<PubSubPattern> pubsub_patterns = new ArrayList<>();
    public void psubscribe(String[] subscribeList, Object client) {
        //遍历所有订阅的 channel,创建节点
        for (int i = 0; i < subscribeList.length; i++) {
            PubSubPattern pubSubPattern = new PubSubPattern();
            pubSubPattern.client = client;
            pubSubPattern.pattern = subscribeList[i];
            pubsub_patterns.add(pubSubPattern);
        }
    }
  1. 创建新节点;
  2. 给节点的属性赋值;
  3. 将节点添加到链表的尾部;

退订模式

退订模式的命令是punsubscribe,客户端使用这个命令来退订一个或者多个模式 Channel。服务器接收到该命令后,会遍历pubsub_patterns链表,将匹配到的 client 和 pattern 属性的节点给删掉。这里需要判断 client 属性和 pattern 属性都合法的时候再进行删除。

伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
public void punsubscribe(String[] subscribeList, Object client) {
        //遍历所有订阅的 channel 相同 client 和 pattern 属性的节点会删除
        for (int i = 0; i < subscribeList.length; i++) {
            for (int j = 0; j < pubsub_patterns.size(); j++) {
                if (pubsub_patterns.get(j).client == client
                && pubsub_patterns.get(j).pattern == subscribeList[i]) {
                    remove(pubsub_patterns);
                }
            }
        }
    }

遍历所有的节点,当匹配到相同 client 属性和 pattern 属性的时候就进行节点删除。

发布消息

发布消息比较好容易理解,当一个客户端执行了publish channelName message 命令的时候,服务器会从pubsub_channels和pubsub_patterns 两个结构中找到符合channelName 的所有 Channel,进行消息的发送。在 pubsub_channels 中只要找到对应的 Channel 的 key 然后向对应的 value 链表中的客户端发送消息就好。

Redis 的持久化你了解吗

持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。另外我们使用的 Redis 之所以快就是因为数据都存储在内存当中,为了保证在服务器出现异常过后还能恢复数据,所以就有了 Redis 的持久化,Redis 的持久化有两种方式,一种是快照形式 RDB,另一种是增量文件 AOF。

RDB

RDB 持久化方式是会在一个特定的时间间隔里面保存某个时间点的数据快照,我们拿到这个数据快照过后就可以根据这个快照完整的复制出数据。这种方式我们可以用来备份数据,把快照文件备份起来,传送到其他服务器就可以直接恢复数据。但是这只是某个时间点的全部数据,如果我们想要最新的数据,就只能定期的去生成快照文件。

RDB 的实现主要是通过创建一个子进程来实现 RDB 文件的快照生成,通过子进程来实现备份功能,不会影响主进程的性能。同时上面也提到 RDB 的快照文件是保存一定时间间隔的数据的,这就会导致如果时间间隔过长,服务器出现异常还没来得及生成快照的时候就会丢失这个间隔时间的所有数据;那有同学就会说,我们可以把时间间隔设置的短一点,适当的缩短是可以的,但是如果间隔时间段设置短一点频繁的生成快照对系统还是会有影响的,特别是在数据量大的情况下,高性能的环境下是不允许这种情况出现的。

我们可以在 redis.conf 进行 RDB 的相关配置,配置生成快照的策略,以及日志文件的路径和名称。还有定时备份规则,如下图所示,里面的注释写的很清楚,简单说就是在多少时间以内多少个 key 变化了就会触发快照。如save 300 10 表示在 5 分钟内如果有 10 个 key 发生了变化就会触发生产快照,其他的同理。

除了我们在配置文件中配置自动生成快照文件之外,Redis 本身提供了相关的命令可以让我们手动生成快照文件,分别是 SAVE 和 BGSAVE ,这两个命令功能相同但是方式和效果不一样,SAVE 命令执行完后阻塞服务器进程,阻塞过后服务器就不能处理任何请求,所以在生产上不能用,和SAVE 命令直接阻塞服务器进程的做法不同,BGSAVE 命令是生成一个子进程,通过子进程来创建 RDB 文件,主进程依旧可以处理接受到的命令,从而不会阻塞服务器,在生产上可以使用。

阿粉在这里测试一下自动生成快照,我们修改一下快照的生成策略为save 10 2,然后在本地启动Redis 服务,并用 redis-cli 链接进入,依次步骤如下

  1. 修改配置,如下

  2. 启动 Redis 服务,我们可以从启动日志中看到,默认是会先读取 RDB 文件进行恢复的

  3. 链接 Redis 服务,并在 10s 内设置 3 个 key

  4. 这个时候我们会看到 Redis 的日志里面会输出下面内容,因为触发了规则,所以开启子进程进行数据备份,同时在对应的文件路径下面,我们也看到了 rdb 文件。

从上面可以看出,我们配置的规则生效了,也成功的生成了 RDB 文件, 后续在服务器出现异常的情况,只要重新启动就会读取对应的 RDB 文件进行数据备份。

AOF

AOF 是一种追加执行命令的形式,它跟 RDB 的区别是,AOF 并不是把数据保存下来,而是保存执行的动作。在开启 AOF 功能的时候,客户端连接后执行的每一条命令都会被记录下来。这其实让阿粉想起来的 MySQL 的 binlog 日志,也是记录操作的命令,后续可以根据文件去恢复数据。

AOF 是追加命令格式的文件,同样的我们可以定义多长时间把数据同步一次,Redis 本身提供了三种策略来实现命令的同步,分别是不进行同步,每秒同步一次,以及当有查询的时候同步一次。默认的策略也是使用最多的策略就是每秒同步一次,这样我们可以知道,丢失的数据最多也就只有一秒钟的数据。有了这种机制,AOF 会比 RDB 可靠很多,但是因为文件里面存在的是执行的命令,所以AOF 的文件一般也会比 RDB 的文件大点。

Redis 的 AOF 功能,默认是没有开启的,我们可以通过在配置文件中配置appendonly yes 是功能开启,同时配置同步策略appendfsync everysec 开启每秒钟同步一次,我们拿到 AOF 文件过后,可以根据这个文件恢复数据。

同样的我们在redis.conf 中可以看到默认是没有开启 AOF 功能的,并且我们也可以指定对应的文件名称和路径。

接下来,我们测试一下开启 AOF 功能,先修改配置然后重启 Redis 的服务器,我们会发现已经没有读取 RDB 文件的日志了,并且在日志文件路径下面已经生成了一个 aof 文件。需要注意的是,因为我们重启的服务,并且开启了 AOF,所以现在 Redis 服务器里面并没有我们之前添加的数据(说明什么问题呢?)。

接下来我们使用客户端连接进入,设置如下值,接下来我们可以看看 aof 文件里面的内容

我们可以看到aof 文件里面的内容就是执行的命令,只不过是以一种固定的格式存储的,我们在备份的时候如果不需要哪些数据,可以手动删掉对应的命令就可以重新备份数据。

Redis 的有几种集群模式

虽然说单机 Redis 理论上可以达到 10 万并发而且也可以进行持久化,但是在生产环境中真正使用的时候,我相信没有哪个公司敢这样使用,当数据量达到一定的规模的时候肯定是要上 Redis 集群的。

Redis 的模式有主从复制模式,哨兵模式以及集群模式,这三种模式的涉及到篇幅内容会比较多,阿粉后面会单独写一篇文章来介绍,感兴趣的小伙伴可以先自己学习下。

阅读全文 »

从 LeetCode 的题目再看 MySQL Explain

发表于 2021-01-16 | 分类于 Java

Hello 大家好,我是阿粉,作为 Java 工程师,数据库用的最多的肯定是 MySQL,而对于 MySQL 公号前面也发过很多文章,感兴趣的可以去翻翻。今天阿粉主要是想通过 LeetCode 上面的一个题目来再带大家看看 MySQL 的变量使用以及通过 Explain 的解析看看SQL 的执行过程。虽然平时在工作中对于 MySQL 使用的很多,但是相对于 MySQL 的变量使用相对还是较少的,所以阿粉在刚看到的时候还是有点懵的,不过我相信大家肯定不会像阿粉一样,毕竟能关注我们公众号的读者都是优秀的。

阅读全文 »

再来“砍一刀”,拼多多天才黑客因为不做黑客业务疑被开除

发表于 2021-01-14 | 分类于 java

最近“拼多多”这是一直在风口浪尖上了,舆论的旋涡那是一层接着一层,员工猝死,员工跳楼自杀,员工发言开除员工,操纵用户手机删除本地保存的图片等一系列的事件,让“拼多多”一直保持在热搜的位置上。

阅读全文 »

心灵奇旅:对你来说,你的火花是什么?

发表于 2021-01-12 | 分类于 程序生活

阿粉元旦的时候去看了一部电影,心灵奇旅。

阅读全文 »

【非广告】半年时间 90% 的收益就问你慌不慌

发表于 2021-01-09 | 分类于 Java

先说明这篇文章不包含任何广告内容,也不提供任何投资理财建议,股市有风险,投资需谨慎!

都说牛市来了,今年的 A 股的行情确实很不错,从上面的截图中可以看到阿粉的一只基金已经收益 90% 了。90% 是什么概念,估计连股神巴菲特都没有过,所以这几天阿粉慌的一批,除了慌的很之外,另一个就是懊悔的很,当初应该多买点的,只能说人性是贪婪的。

阅读全文 »

面试官:既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?

发表于 2021-01-08 | 分类于 java

上一次的文章中,阿粉在面试官面前说了对启动流程不太理解,然后和他聊了一会,然后他又提出了你既然不是特别了解启动流程的话,那你对Tomcat的生命周期熟悉么?

阅读全文 »

团队里的妹子让阿粉跟她说说怎样写出好的代码

发表于 2021-01-05 | 分类于 编程

昨天团队里的妹子很突然地就让阿粉跟她说说怎么才能写出一手好的代码

阅读全文 »

唉!拼多多女孩猝死,996再上热搜!

发表于 2021-01-04 | 分类于 Java

Hello,大家好,我是阿粉~

『上班 996,下班 ICU!』这是 2019 年上半年的热门事件,那个时候整个互联网圈子都在抵制 996,抵制无良公司。

不过随着 2020 年疫情开始,外部环境变得很差, 越来越多人无奈接受了 996 ,这个话题开始慢慢淡出了视野。

不过,最近两天 996 话题再次引爆互联网,又一上了热搜了,而事情的真实起因说起来真的令人心痛。

1 月 3 号下午,网友在脉脉平台爆料,拼多多员工在凌晨一点半下班回家路上晕倒猝死。

据网上爆料信息,这位拼多多员工是 98 年,年仅 22 岁,19 届毕业,内部花名润肺,从事拼多多新疆买菜项目的招商相关岗位。

2020 年的12 月 29 日凌晨一点半,下班路上突然晕倒,经过抢救无效去世。

事情爆料出来之后,热度越来越高,一晚上的时间该话题达到了近千万的热度,知乎话题被顶到热门,而微博 996 ,拼多多等话题也被顶上了热搜。

随后脉脉上又有内部员工爆料,拼多多 HR 正在开始删帖。

这个套路是不是很熟悉?

撤热搜,降热度,删帖子,互联网大厂对待大众舆论一套组合拳。

如果事情就到此为此,也许就没么魔幻!

2021 年 1 月 4 日早上,疑似拼多多官方知乎账号发表回应,不过 1 分钟之后就被秒删。

不过互联网都是有记忆的,许多知乎网友都看到这个回答,截图传播。

仔细看下这个回答,这什么意思❓❓❓

这是想表达 猝死=以命换钱=努力吗❓❓❓

这真的是经过脑子吗❓❓❓

随后 2020 年 1 月 4 号下午拼多多官方回应:“我们心痛如绞,我们爱你,深深的想念你。”

然后又进行辟谣,称其从未发布过上面的截图。

本来事情也许就到此为止了,官方都发声明辟谣了,但是网上那些截图真的是伪造吗?

如果真的是假的,那么作为这张截图的源头知乎,起码也要负相关的责任。

拼多多这是要把黑锅甩给知乎啊,不过知乎没怂,选择了硬刚。

知乎小管家拿出了后台数据,时间精确到了秒,啪啪打了拼多多的脸,砍了拼多多一刀。

不得不说,知乎🐂🍺。

事情的最后,拼多多最终发布道歉声明,把锅甩给了一个合作供应商的员工。

这个套路有没有感觉让人很熟悉❓❓❓

好像每次看到热点新闻,都是临时工默默抗下所有!

现在开始回顾一下这件事,拼多多这波公关,怎么说呢,真的……负分。

先是谎称官方好回答是谣言,被辟谣之后又说是营销合作方的锅,是他们在乱搞。

最后还让一个员工手写新来澄清。

一个官方的号都不能让人相信的话,这个官方号还有啥用,还有公信力吗?

建议早点换个公关团队吧。

拼多多为什么这么忙?

去年十月,拼多多五周年的时候,黄峥在内部发表称拼多多全员都要「开启硬核奋斗模式」。

什么是硬核奋斗模式?

很多大厂开始大小周的上班方案,相比这个,拼多多更加狠,据网上爆料拼多多推出超级版的大小周方案,大周 7 天,小周 6 天。

这么计算下来,每个月就休息两天。

另外据说拼多多买菜业务全年无休,今年的春节假期很有可能也是不放假!!!

这真的很硬核!!!

可能很多人不了解拼多多买菜业务,简单解释一下,其实就是社区团购业务,最近非常火热。

京东、滴滴、美团、阿里叫的上名的互联网大厂都来参了一手。

拼多多将买菜业务列为重点项目,倾其所有资源投入,All in 买菜。

也许正因为竞争太激烈,所有人都想在这个赛道抢到头筹,争取跑的比竞争对手快,所以开始无止尽的加班,无止尽压榨底层员工。

最后

其实写到这里,阿粉觉得真的有点无奈,身处现在互联网圈子,感觉个体力量真的很渺小。我们只能被资本摆布,只能逼着去 996。

不过即使这样,阿粉还是要发声,让这件事能被更多的读者看到。

哎,真的很痛心!希望这次事件能成为大家反抗 996 的一次契机。

最后提醒大家一下,真的要注意一下自己的身体健康,平时有时间的话还是要适当运动一下,毕竟身体是我们自己的。

阅读全文 »

面试官:来说说Tomcat的启动过程是什么样子的

发表于 2021-01-02 | 分类于 java

阿粉最近在疯狂的研究各种用的工具里面的源码实现,之前给大家都专门的去扣了一下 JDK 里面自带的exe程序,这次阿粉开始更加无聊,直接开始搞Tomcat。

阅读全文 »

未命名

发表于 2021-03-05
阅读全文 »
1 2 … 27
Java Geek Tech

Java Geek Tech

一群热爱 Java 的技术人

530 日志
113 分类
24 作者
RSS
GitHub 知乎
Links
  • 纯洁的微笑
  • 沉默王二
  • 子悠
  • 江南一点雨
  • 炸鸡可乐
  • 郑璐璐
  • 程序通事
  • 懿
© 2019 - 2021 Java Geek Tech
由 Jekyll 强力驱动
主题 - NexT.Mist