分享知识

To strive, to seek, to find, and not to yield.

分享知识

  • 首页

  • 标签

  • 分类

  • 归档

Q46 把数字翻译成字符串

发表于 2020-06-09 | 更新于 2020-06-10 | 分类于 算法 , leetcode刷题

题目描述见:点击跳转

解析思路

  leetcode 中国中的一个中等难度面试题——把数字翻译成字符串,是一个较为简单的动态规划问题(虽然简单我也不会呀)。

咋一看这个题目描述是懵逼的,思考 10 分钟无果,果断看了解题思路,豁然开朗。

假设数字的长度为$n$,第$i$个数为$x_i$,长度为$n$的数字结果为$f(n)$

我们开始找规律:

阅读全文 »

手把手教你用redis实现一个简单的mq消息队列

发表于 2020-06-05 | 更新于 2020-06-09 | 分类于 java , 其他

众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。目前使用较多的消息队列有 ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ.

但是如果你不想为你的系统引入一个重量级(相对 redis 来说)的 mq,但是想要享受解耦、异步消息等特性,通过本文你就 get 到了,通过 redis 实现一个简单版的 mq。

为什么是 redis

  • redis 通常作为缓存服务引入,因此大部分系统都会有 redis
  • redis 本身的资源消耗是极小的,符合我们的轻量要求
  • redis 速度很快,几乎不会出现速度瓶颈
  • redis 有持久化方案,调整配置项可以在数据安全和速度间进行取舍(参考这篇)[https://segmentfault.com/a/1190000002906345]

如何实现

利用 redis 的队列结构来实现消息队列。redis 单个队列最多支持 2*32-1 条数据,对于大部分应用是完全够用的。

简单来说就是:

  • 每个 topic 对应一条队列
  • 从队列一段写入数据,从另一端读取数据
  • 消费失败,重新将消息放入队列

注意:代码仅供个人尝鲜使用,请勿用于真实生产环境

代码仅可在 springboot 环境中使用

首先定义注解和接口类

注解代码如下:

1
2
3
4
5
6
7
8
9
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface MqConsumer {
/**
* 队列主题
*/
String topic() default "default_es_topic";
}

被该注解修饰的类,将会接收 topic 下的消息。

接口代码如下:

1
2
3
4
5
6
7
8
9
10
11
public interface RedisConsumer {

/**
* 功能描述: 消费方法,消费者类必须继承此方法
*
* @param message 数据载体
* @author 123
* @date 2020/3/28 22:41
*/
void deal(String message);
}

本接口用于定于接受消息的处理方法。

扫描注解修饰类

本部分为核心代码,首先需要获取代码中被注解修饰的类,然后建立一个循环从 redis 队列中取数据,最后调用类对象的 deal 方法消费消息,如果 deal 方法抛出错误,认为消费失败,重新将该数据放入队列中。

  1. 扫描部分代码如下:
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
/**
* MqConfiguration.java
*/
@Override
public void run(ApplicationArguments args) {
Map<String, Object> map = context.getBeansWithAnnotation(MqConsumer.class);
map.values().forEach(item -> {
if (!(item instanceof RedisConsumer)) {
log.warn("注意检测到被@EsConsumer注解的类{}未实现RedisConsumer接口", item.getClass().getCanonicalName());
return;
}
MqConsumer[] annotations = item.getClass().getAnnotationsByType(MqConsumer.class);
MqConsumer annotation = annotations[0];
String topic = annotation.topic();
if (topicMap.containsKey(topic)) {
log.error("多个消费者{},消费同一个消息:{},已忽略", item.getClass().getCanonicalName(), topic);
} else {
topicMap.put(topic, (RedisConsumer) item);
}

});
log.info("redis订阅信息汇总完毕!!!!!!");
//由一个线程始终循环获取es队列数据
threadPoolExecutor.execute(loop());
}

run 方法在 spring 扫描完毕后调用,通过实现ApplicationRunner接口实现,通过 spring 的方法来获取所有被MqConsumer接口注解的类(否则需要自己写类加载器)。数据汇总完毕后使用一个线程来进行无线循环从 redis 队列中取数据。

  1. 执行线程部分代码如下:
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
private Runnable loop() {
return () -> {
while (true) {
AtomicInteger count = new AtomicInteger(0);
topicMap.forEach((k, v) -> {
try {
String message = mqUtil.getRedisTemplate().opsForList().rightPop(k);
if (message == null) {
count.getAndIncrement();
} else {
pushTask(v, message, k);
}
} catch (RedisConnectionFailureException connException) {
log.error("redis无法连接,10s后重试", connException);
sleep(10);
} catch (Exception e) {
log.error("redis消息队列异常", e);
}
});
if (count.get() == topicMap.keySet().size()) {
//当所有的队列都为空时休眠1s
sleep(1);
}
}
};
}
private void pushTask(RedisConsumer item, String value, String key) {
threadPoolExecutor.execute(() -> {
try {
item.deal(value);
} catch (Exception e) {
log.error("执行消费任务出错", e);
//非广播消息进行数据回补
mqUtil.getRedisTemplate().opsForList().rightPush(key, value);
}
});
}

loop 方法无限循环根据 topic 从 redis 中取数据,如果取到数据,调用 pushTask 方法执行,如果执行报错将会进行数据回补。

完整代码见本文结尾

测试

运行项目后调用,MainController中的接口即可测试。

完整代码:github

本文原创发布于:手把手教你用 redis 实现一个简单的 mq 消息队列

node搭建拼音转换服务器

发表于 2020-03-15 | 更新于 2020-06-09 | 分类于 node , 项目

npm设置代理

发表于 2019-10-10 | 更新于 2019-11-30 | 分类于 node , node开发配置

背景

通常情况下当 npm 无法下载依赖时,我们使用 cnpm 就够了。但是总是存在特殊情况的:

  1. 公司内网,无法访问 npm,但是有一个代理可以访问外网
  2. 网络质量很差,连 cnpm 都无法正常使用(比如长城坑带,跨市就出现大量的丢包)

那就需要给 npm 设置代理了

设置代理

http 代理

npm 原生支持 http 代理,直接设置即可

1
2
3
4
5
6
7
# 假设本地代理端口为8080
npm config set proxy "http://localhost:8080"
npm config set https-proxy "http://localhost:8080"

# 有用户密码的代理
npm config set proxy "http://username:password@localhost:8080"
npm confit set https-proxy "http://username:password@localhost:8080"

socks5 代理

npm 不支持 socks 代理,但是我们可以用一个工具将 http 代理转成 socks 代理,然后将 npm 代理地址设置到这个工具的地址。

1
2
3
4
5
6
7
8
# 假设本地socks5代理端口为8081
# 首先安装转换工具
npm install -g http-proxy-to-socks
# 然后使用这个工具监听8080端口,支持http代理,然后所有8080的http代理数据都将转换成socks的代理数据发送到8081上
hpts -s localhost:8081 -p 8080
# 最后设置npm代理为8080
npm config set proxy "http://localhost:8080"
npm config set https-proxy "http://localhost:8080"

相当于又加了一个中间层,将 http 转成 socks。

删除代理

1
2
npm config delete proxy
npm config delete https-proxy

本文原创发布于tapme.top/blog/detail/20191010

主流排序算法全面解析

发表于 2019-08-06 | 更新于 2019-11-30 | 分类于 算法 , 排序算法

以下如无特殊说明都是按照升序进行排序。
源码见最下方

比较类排序

交换排序

冒泡排序

定义

是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端–维基百科。

思想

冒泡排序很简单,顾名思义每轮循环中将一个最大/最小的数通过交换一路冒到数组顶部。

阅读全文 »

springboot整合elasticsearch(基于es7.2和官方high level client)

发表于 2019-07-29 | 更新于 2019-11-30 | 分类于 java , spring boot学习

前言

最近写的一个个人项目(传送门:全终端云书签)中需要用到全文检索功能,目前 mysql,es 都可以做全文检索,mysql 胜在配置方便很快就能搞定上线(参考这里),不考虑上手难度,es 在全文检索方面是完胜 mysql 的。

最后决定使用 es。使用最新的 7.2 版本。java 客户端使用 es 官方的 high level client(官方文档),为什么用这个有以下几点原因:

  • jest 毕竟不是官方的,更新速度较慢
  • transportClient,速度太慢,连官方都嫌弃它了。在 7.x 中已经被弃用,8.x 中将完全删除
  • high level client 的官方文档写的很清楚明了,虽然目前相关的中文资料还很少,也能够上手用起来

本文主要内容如下:

  • docker 部署 es(支持 ik 中文分词)
  • 在 springboot 中进行增删改查
阅读全文 »

从零开始react实战:云书签2-登录、注册、重置密码功能前后端实现

发表于 2019-06-28 | 更新于 2019-11-30 | 分类于 前端 , react

总集篇:react 实战之多人聊天室

上一篇搭建了 reat 的环境,本篇正式开始编码了。先实现以下三个通用功能:

  • 注册
  • 登录
  • 重置密码

鉴于本人设计水平有限(抠脚),所以这三个页面的风格将参考简书网页版。

模板编写

打开简书的注册页和登录页发现结构都是一样的,背景加上中间的输入框,如下图所示:

简书登录页

观察登录、注册两个页面的结构可以发现真正变化的部分只有中间的表单,所以我们可以将表单外的其他部分作为一个公共布局给这些页面来复用。

阅读全文 »

从零开始react实战:云书签1- react环境搭建

发表于 2019-06-26 | 更新于 2019-11-30 | 分类于 前端 , react

总览篇:react 实战之云书签

本篇是实战系列的第一篇,主要是搭建 react 开发环境,在create-react-app的基础上加上如下功能:

  • antd 组件库按需引入 ,支持主题定制
  • 支持 less 语法,并使用 css-module
  • 配置路由
  • 支持 http 请求
  • 配置 redux

注意:需要 node 版本大于 8.0.

创建 create-react-app

  1. 安装
1
npm install -g create-react-app
  1. 创建 react 应用
1
create-react-app bookmark-world
阅读全文 »

从零开始react实战:云书签(总览)

发表于 2019-06-25 | 更新于 2019-11-30 | 分类于 前端 , react

一个合格的全栈开发怎么能不会 react 呢?所以从现在开始系统的学习 react 开发。目标:完成完成一个云书签,包含前后台。

基于create-react-app进行开发,选择这个框架有以下两个原因:

  • 从头开始配置 webpack 太复杂,不用了解的这么细致。
  • 也不使用antd pro,umi.js这类开箱即用的,隐藏了太多细节,也不考虑。
阅读全文 »

antd组件中table设置单行显示

发表于 2019-06-21 | 更新于 2019-11-30 | 分类于 前端 , react

今天在开发中遇到了这样一个问题,antd 的 table 组件,在内容太多时会折行显示,如何才能让它不折行并且用省略号显示超出内容呢?

可以同给给单元格设置这样的 css 来达到效果:

1
2
3
4
5
6
7
8
/* 设置最大宽度,不能用width */
max-width: 133px;
/* 不折行 */
white-space: nowrap;
/* 超出部分隐藏 */
overflow: hidden;
/* 显示... */
text-overflow: ellipsis;
12…8

fleyX

To strive, to seek, to find, and not to yield.

72 日志
35 分类
152 标签
GitHub E-Mail
© 2018 – 2021 fleyX
由 Hexo 强力驱动 v3.8.0
|
主题 – NexT.Gemini v7.0.0
湘ICP备17016434号-1