通过mysql批量操作不生效问题聊聊java里mysql的batch
众所周知,对于mysql,使用批量操作,可以大幅度提升大数据量下操作的性能。不过,在java中使用mysql时,有些细节务必注意,否则就会导致batch操作不生效,也就享受不到批量操作的性能了。 前阵子,发现一条sql的性能明细不正常,几千条数据批量insert,耗时居然到了秒级。排除了服务器性能、网络的问题后,开始怀疑是代码的问题,导致batch操作没有真正生效,感觉只有一条一条去跟数据库交互的话才会出现这种性能。 调了一下代码,翻到了mysql-connector里,关键的代码是这么一块: 12345678910111213if (!this.batchHasPlainStatements && this.connection.getRewriteBatchedStatements()) { if (canRewriteAsMultiValueInsertAtSqlLevel()) { return executeBatchedInserts(batch...
【实践经验】单元测试怎么写
之前一段时间,在尝试完善项目的单元测试,做起来才发现,其实自己对于单元测试该怎么写一直没有特别清晰的认识,因此查了一些资料, 查的过程中发现,其实每个人的看法都不尽相同。每阅读一篇文章,都是对自己认知的一次更新。本文就是结合前人的看法,和自己的实践经验,总结出一些我自己当前认知状态下认为正确的东西,分享给大家。估计也不会是最正确的,也欢迎大家留言讨论。 先说一下我们写单元测试的目的,这个是下边所有讨论的基础。单元测试的意义应当在于保障修改代码的时候,保障存量代码的正确性。也就是说,修改代码后,执行一遍已有的测试用例,能执行的话就代表之前的逻辑依然是可用的。 下面就具体列一下个人认为写单元测试应当遵守的准侧。 避免对环境的依赖单元测试不应当依赖于环境,包括对网络、db、io、数据、外部接口等的依赖。这一点应该争议不大,因为单元测试会有很多的执行场景,比如开发人员手动触发、提交代码时自动触发、打包时自动触发等,如果单元测试不能解除对环境的依赖,它的执行场景就会大大受限。 实现这一点,需要借助很多工具,例如内存数据库、redis的内嵌server, mock等待,势必会给写单元测试这...
关于rocketmq的readQueue和writeQueue
解释一下rocketMq里的messageQueue为什么要拆分成writeQueue和readQueue. 首先,简单介绍一下rocketmq的queue是什么,从网上找了一个rocketMq的架构图。我们知道,使用rocketMq时,我们都是针对一个topic区进行生产或者消费。而messageQueue就是topic的一部分,类似于kafka中分区的概念。queue是consumer消费时的最小单元,也就是说,consumer的数量无法高于queue的数量。 rocketMq中有很特殊的一点是分了writeQueue和readQueue。其实,在绝大对数情况下,这两件事是无法分开的,如果readQueue和writeQueue的数量不一致,会产生非常严重的问题。例如,writeQueue的数量高于readQueue, 就说明有些queue只有写没有读,也就是说会有一部分消息永远都不会消费掉。readQueue多于writeQueue的话,就说明有一部分consumer处在空跑的状态,不可能接收到消息。 那么,rocketMq这么设计的意义在哪里呢。其实,拆分readQu...
数据分析的利器-clickhouse介绍
Clickhouse是Yandex开源的一个用于实时数据分析的数据库,一开始就用在yandex内部的多个数据分析业务上。要介绍clickhouse,还是需要先介绍一下yandex。Clickhouse为什么会出现,其实和yandex的业务关系非常大。Yandex是俄罗斯最大的搜索引擎,会有很多数据分析的业务,其中数据量最大的业务,就是Yandex.Metrica,这是一个和百度统计类似的网站数据分析服务,数据量也仅次于google analysis。自从Clickhouse开源后,在国内外的很多公司的线上业务都已经开始使用。 因此,写这篇clickhouse教程,对clickhouse做一个基础的介绍。 概述Clickhouse是极其适合OLAP(联机分析处理)问题的一个数据库。这类问题有如下一些特点: 请求以读为主,数据添加、更新一般以批量的形式进行; 表可以很宽,但是实际查询时只会用到有限的几列; 列值较小,一般是数字或者短字符串; 查询结果集的大小显著小于源数据; 事务处理需求较弱 根据clickhouse提供的性能测试结果,clickhouse的性能要大大领先于所...
通过位运算转换大小写
位运算是计算机科学领域用的非常广泛的一种计算方式。再合理的使用方式下,会大大提升运算效率,今天就介绍一下位运算的一个巧妙应用:转换大小写字母。 针对这个问题,我们可以首先观察一下大小写字母的ascii码特点。 可以看到每一对大小写字母的ascii码值都是差32,对应到二进制上,就是只有第六位相反,其他的值都一样。 因此,用一个字母的值与 0010 0000 (32)作亦或,就可以得到它对应的大写或小写字母了。 原文地址:https://lichuanyang.top/posts/9193/
activemq多线程消费的不同处理方式
之前在另一篇文章里介绍过使用activemq时,client端的基本语法。 值得注意的是消费者, 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 public void consume() throws JMSException { ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(); cf.setBrokerURL("tcp://localhost:61616"); Connection connection = cf.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Que...
高并发下作余额扣减的一些经验
前一段时间参加了优化一个老的计费系统,学习了一些高并发下做余额扣减的常用手段,也做了一些尝试,因此在这里总结记录一下, 在高并发下对。 问题描述对于一个计费系统来说,并发问题事实上分为两类,一类是应用并发高,也就是纯粹的用户量大,访问量多,这类问题和一般的高并发问题没有区别,用分布式等手段就可以解决;另外一类问题则是一般分布式手段无法解决的用户高并发问题,也是本文要着重说的。这类问题源自对某些高频账号,大量的并发访问,会导致瓶颈首先出现在某些数据库记录上,大量操作由于无法竞争到数据库的行锁而导致等待,这些等待中的操作又会占用其他资源,最终导致系统不可用。针对这类问题,下边介绍一些常用的处理办法。 不设置余额字段由于对于一个稳定的计费来说,一定是会记录计费流水明细的,所以完全可以不设置余额字段,而采用根据流水明细计算的方式来获取余额。不过这种方法不是万能的,比如拿广告业务的计费系统来说,频率非常高,而每次的金额很小,这时候想通过计算求和去算余额,显然是不现实的。 合并与拆分这是两种方式,因为有一些相似之处,都是要降低对单条数据库记录的访问压力,所以也就放到一起说了。合并,就是对...
java细节:三目运算符和自动拆箱
问题引入今天用findbugs扫代码时遇到一个很有意思的问题,有关三目运算符的,在这儿记录一下。 就是类似这么一行代码: 12boolean b = true; Long a = b ? 0l : Long.valueOf(2); Findbugs给出了”Boxed value is unboxed and then immediately reboxed”的提示,意思就是有装箱的对象做了拆箱,然后又马上做了装箱。这个问题其实很常见,一开始也没注意,只是习惯性的把Long.valueOf 改成了Long.parseLong, 确实把这个警告消掉了,不过之后才意识到不对:明明valueOf返回的是Long类型,parseLong返回的是long类型,而需要的正是Long类型,为什么反而用valueOf的时候有问题呢。 其实思考一下大概也能想明白,主要就在三元运算符的另一个分支,因为另一个分支返回的是一个未装箱的0,所以这个三元运算符的返回值就成了long,所以原本的Long类型就要经过一次拆箱才会被返回。要优化这个部分的话,保持两个分支的返回类型一致就可以了。 然后把相...
设计一个开源的北京地铁路线规划小工具 java版本
概述最近在找房子,因为想找一个去几个地方都相对方便的位置,自己去地图上看还挺麻烦的,所以想做个小工具,用来对北京地铁的路线做规划,本文就简单介绍一下实现过程。目前的功能还比较简单,主体方法就是根据一个输入的始发站,列出其他所有站点到这个地方的站数最少路线。 数据获取从网上找了高德地图的接口数据: http://map.amap.com/service/subway?_1469083453978&srhdata=1100_drw_beijing.json . 对拿到的json串进行解析,其中包含每条地铁线路的信息,并依次列出线路上的每个站点。 通过解析数据,要得到的主要就是各个站点的信息,站点定义的数据结构如下: 123456private String id;private String name;private Set<String> lines = new HashSet<String>(); //所在线路private String position;private String pinyin;private Set<String&...
redis cluster的数据迁移
在之前的一篇文章通过实际操作理解redis cluster原理中,我们简单介绍过redis cluster的设计原理。redis cluster中的数据是根据一定规则分配到16384个slot中,这些slot又根据配置对应到不同的节点上。我们知道,在集群稳定运行后,仍然可以以slot为单位转移数据,不过对于具体的转移过程,包括转移过程中集群的可用性等问题,一直不是太确定,所以这次详细了解了一下。 整体流程redis官方文档中提供的数据迁移办法是借助redis-trib脚本,其实严格来说,这个redis-trib并不是redis本体的一部分,它只是官方按照redis设计规范实现的一套脚本集合,帮助用户更方便的使用redis-cluster。 实际上,我们完全可以脱离这个脚本来使用cluster, 或者用其他方式实现这套逻辑,比如搜狐tv的redis运维工具cachecloud里,就用java实现了整套逻辑。 我们可以参考redis-trip或者cachecloud的代码来了解cluster数据迁移的流程,主要分为如下几部: 设定迁移中的节点状态,比如要把slot x的数据从节...