180710-MySql插入唯一键冲突的三种可选方式

logo

MySql插入时唯一键冲突的几种处理方式

MySql插入一条记录,结果提示主键冲突,怎么办?

批量插入数据时,发现插入的这批数据中,有某些记录存在唯一键冲突,一个一个跳出来就比较麻烦了,有什么好的办法直接忽略掉冲突的记录么?

下面简单记录三种处理方式

170709-Java实现获取本机Ip工具类

logo

Java实现获取本机Ip的工具类

获取本机Ip算是比较常见的一个需求场景了,比如业务报警,可能就会带上出问题的机器IP,方便直接上去看日志定位问题,那么问题来了,如何获取机器IP呢?

180707-ssh远程免密登录配置

logo

通过ssh免密方式登录远程服务器, 配置比较简单,就是讲自己的rsa公钥放在远端服务器的授权文件中

1
vim ~/.ssh/authorized_keys

180706-BigDecimal除法的精度问题

BigDecimal除法的精度问题

在使用BigDecimal的除法时,遇到一个鬼畜的问题,本以为的精度计算,结果使用返回0,当然最终发现还是自己的使用姿势不对导致的,因此记录一下,避免后面重蹈覆辙

180705-一个简单的幂等工具类实现

一个简单的幂等工具类

在日常的工作中,业务的去重幂等场景属于比较常见的需求,一般来讲简单的幂等工具类可以基于内存或者基于redis进行,本篇简单介绍下,如何使用Guava的缓存来实现一个幂等工具类

180704-JDK常用监控参数

相关博文: jvm调优的工具介绍

小结一下用的几个调优参数,特别是自带的jvisualvm,比较好用,但是功能丰富完整方面比jprofile要欠缺一点,后面有时间补上jprofile的使用过程

180703-netstat常用命令学习小结

logo

平常工作中,经常会出现的一个case就是查询端口号占用情况,一般在linux下使用netstat,在mac下则使用lsof;本篇则记录下Linux之netstat命令的使用

最常用的一个查看端口号占用命令:

1
netstat -alnp | grep port

180702-QuickTask动态脚本支持框架整体介绍篇

logo

Quick-Task 动态脚本支持框架整体介绍篇

一个简单的动态脚本调度框架,支持运行时,实时增加,删除和修改动态脚本,可用于后端的进行接口验证、数据订正,执行定时任务或校验脚本

本项目主要涉及到的技术栈:

  • groovyEngine (groovy脚本加载执行)
  • commons-io (文件变动监听)

180701-计数时间窗口数据结构的设计

logo

相关博文:

维持计数时间窗口数据结构的设计

I. 背景

有这么一个场景,我需要维护每个商品在3min, 10mn, 1h, 6h, 24h这几个时间窗口内的贸易总额,那么可以怎么实现?

问题拆解:

  • 每个商品,对应多个时间窗口
  • 商品可能很多,因此时间窗口的量可能很大
  • 时间窗口的数据为总数,因此不需要记录每个订单的情况,只需要维护一个交易总额即可
  • 热点数据,可能每分钟都有很多的成交
  • 冷门数据,可能一天都没有几笔成交

180628-动态任务执行框架想法篇

数据订正带来的动态任务执行框架的想法

I. 背景

对于后端而言,数据订正可算是非常非常频繁且常见的事情了,常见的有DB、缓存、内存等数据源中的数据订正,对于非应用内存而言,其他有实体或者可以直接通过官方的提供的控制台连接进行修改的数据订正,相对比较简单,而对于应用内存,如果没有应用内通知并处理相关逻辑,多半就只能重启应用来实现刷新内存缓存了

当然我这里说的也不是内存数据更新,最近遇到的一个问题就是redis缓存中的数据有问题,需要订正,而并不是简单的把数据删了就行,需要根据某些数据,做一些计算,然后得出新的数据,并写回到缓存

这样看来好像也不太麻烦,如果没有第三方依赖,大不了写个python脚本或者php脚本,重新算一下,也没什么毛病

然而实际情况却并不是这样,问题有以下几点:

  • 数据经过ProtoBuf进行编码存入redis,反序列化是个问题
  • 数据计算有依赖外部服务,如只能通过rpc调用第三方接口,而rpc框架没有提供php或python的sdk

基于此,就想也米有办法,可以直接搞一个项目,可以执行Groovy脚本,在Groovy脚本中实现数据订正逻辑?需求如下

  • 支持Groovy脚本的动态更新(支持动态新增,删除和修改脚本)
  • Groovy脚本可友好的访问我们需要的外部资源

180626-Spring之借助Redis设计一个简单访问计数器

logo

Spring之借助Redis设计一个简单访问计数器

为什么要做一个访问计数?之前的个人博客用得是卜算子做站点访问计数,用起来挺好,但出现较多次的响应很慢,再其次就是个人博客实在是访问太少,数据不好看😢…

前面一篇博文简单介绍了Spring中的RedisTemplate的配置与使用,那么这篇算是一个简单的应用case了,主要基于Redis的计数器来实现统计

180625-关于时间窗口的想法

关于滑动时间窗口的想法

如何设计一个维护当前时间,当之前3min, 5min, 10min, 1h, 24h时间窗口内的访问计数的数据结构,简单来讲就是如何优雅的设计一个滑动时间窗口

180623-SpringBoot之logback配置文件

SpringBoot配置logback

项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?

阿里云服务器基本环境配置

阿里云服务器基本环境配置

I. RabbitMQ安装

1. 安装

1
2
3
yum install erlang
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.15/rabbitmq-server-3.6.15-1.el6.noarch.rpm
yum install rabbitmq-server-3.6.15-1.el6.noarch.rpm

180621-一个简单的时间窗口设计与实现

如何设计一个计数的时间窗口

时间窗口,通常对于一些实时信息展示中用得比较多,比如维持一个五分钟的交易明细时间窗口,就需要记录当前时间,到五分钟之前的所有交易明细,而五分钟之前的数据,则丢掉

一个简单的实现就是用一个队列来做,新的数据在对头添加;同时起一个线程,不断的询问队尾的数据是否过期,如果过期则丢掉

另外一中场景需要利用到这个时间窗口内的数据进行计算,如计算着五分钟交易中资金的流入流出总和,如果依然用上面的这种方式,会有什么问题?

  • 如果时间窗口大,需要存储大量的明细数据
  • 我们主要关心的只有资金流入流出;存这些明细数据得不偿失
  • 每次新增or删除过期数据时,实时计算流入流出消耗性能

针对这种特殊的场景,是否有什么取巧的实现方式呢?

180620-mysql之数据库导入导出

mysql之数据库导入导出

实际工作中,需要做一下数据库迁移,需要导入导出数据,记录一下mysqldump的简单用法

180619-Yaml文件语法及读写小结

Yaml文件小结

Yaml文件有自己独立的语法,常用作配置文件使用,相比较于xml和json而言,减少很多不必要的标签或者括号,阅读也更加清晰简单;本篇主要介绍下YAML文件的基本语法,以及如何在Java中实现读写逻辑

180615-精度计算BigDecimal

180615-精度计算BigDecimal

目前接触的业务中,对数据的精度要求比较高,因此不再使用基本的float,double,改为用BigDecimal进行存储和相关的计算,端午前的这一篇博文,则简单的介绍下BigDecimal的使用姿势,早点回家早点放假

180613-GuavaCache返回Null的注意事项

GuavaCache返回Null的注意事项

Guava在实际的Java后端项目中应用的场景还是比较多的,比如限流,缓存,容器操作之类的,有挺多实用的工具类,这里记录一下,在使用GuavaCache,返回null的一个问题

I. 常见使用姿势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void testGuava() {
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
if ("hello".equals(key)) {
return "word";
}
return null;
}
});

String word = cache.getUnchecked("hello");
System.out.println(word);

System.out.println(cache.getUnchecked("word"));
}

上面是一个非常简单的测试case,需要注意的是,cache.get("word") 的执行,并不如逾期的返回的是null,而是会抛一个异常出来

1
2
3
4
word
com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key word.
at com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2287)
...

从异常描述能看出,不允许返回null,这一块之前倒是没怎么注意,因此对于null的情况,要么定义一个标记表示不存在,要么在load()方法中主动抛一个异常出来,在使用的时候注意下,通过异常的使用方式,可以如下

1
2
3
4
5
6
7
8
9
10
public class NoVlaInGauvaException extends Exception {
public NoVlaInGauvaException(String msg) {
super(msg);
}

@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}

说明:为什么重写fillInStackTrace方法

  • 对于这种缓存未命中的情况下,一般而言是不需要关注完整的堆栈信息的,没有数据而已,可以节省一点点性能(当然除非是在高频率的抛出时,才会有表现症状)

其次就是getgetUnchecked的区别了

  • get要求显示处理exception状况
  • getUnchecked 一般是可确认不会有问题的场景,直接调用

II. 其他

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

QrCode

180612-Spring之Yml配置文件加载问题

Yml配置文件加载问题

在resource目录下有一个application.yml文件,希望是通过@PropertySource注解,将配置文件数据读取到Environment中,然而调试发现数据始终读取不到,google之后,记录下解决方法

在测试用例中,指定初始化方式 @ContextConfiguration(classes = RedisConf.class, initializers = ConfigFileApplicationContextInitializer.class)

1
2
3
4
5
6
7
8
9
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RedisConf.class, initializers = ConfigFileApplicationContextInitializer.class)
public class RedisTest {
@Test
public void testRedis() {
String ans = JedisClient.getStr("hello");
System.out.println(ans);
}
}

对应的配置类

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
@Configuration
@PropertySource(value = "classpath:application.yml")
public class RedisConf {

@Autowired
private Environment environment;

@Autowired
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);

DefaultStrSerializer serializer = new DefaultStrSerializer();
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.setKeySerializer(serializer);
redisTemplate.setHashKeySerializer(serializer);

redisTemplate.afterPropertiesSet();

JedisClient.register(redisTemplate);
return redisTemplate;
}

@Bean
public RedisConnectionFactory redisConnectionFactory() {
LettuceConnectionFactory fac = new LettuceConnectionFactory();
fac.getStandaloneConfiguration().setHostName(environment.getProperty("spring.redis.host"));
fac.getStandaloneConfiguration().setPort(Integer.parseInt(environment.getProperty("spring.redis.port")));
fac.getStandaloneConfiguration()
.setPassword(RedisPassword.of(environment.getProperty("spring.redis.password")));
fac.afterPropertiesSet();
return fac;
}
}

II. 其他

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

QrCode

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×