ES与MySQL的数据实时同步
其实不止电商系统需要用到ES,很多的项目也会经常使用ES来进行全文检索和特殊查询。那么如果我们想要将ES和MySQL的数据合理地同步,我总结了几个方式。
其一是双写,也是最简单的,在把数据写入数据库后再写入ES中,但这样会导致代码高度耦合,需要手动维护数据库和ES的数据关系,很麻烦。
其二则是使用MQ发送,在将数据写入数据库之后在服务端发送MQ到消费端执行向ES写入数据的逻辑,从而将写入数据库和写入ES的代码分离开,使程序员可以专注于自己的业务。但缺点是这样还是需要手动维护MQ的发送和接收逻辑,并且引入了MQ使项目更加复杂。
其三是使用Datax实现全量数据同步,该方法可以让代码完全分离开,并且不需要手动维护,对代码侵入性几乎为零。不过这是一种全量同步数据的方式,时效性较差。
其四则是使用Canal,与Datax有相同的功能,并且可以实时同步数据。
Canal的工作原理
首先需要了解数据库的主从复制主要流程为:主库(MySQL master)将数据的变更操作复制至二进制日志文件中(binary log),从库(MySQL slave)将主库的日志文件复制到中继日志(relay log)后重放操作从而实现复制数据。
Canal的工作原理则是将自己伪装为一个MySQL slave向MySQL master发送dump文件,MySQL master再将日志文件发送给Canal进行解析。
秒杀系统
秒杀系统主要面临的问题:高并发,锁机制,超卖,数据库压力
我这里仅仅是设计一个较为简单的秒杀系统:
针对高并发我们常用的策略就是限流,假如我们所要秒杀的库存只有10件,此时发送过来100个请求,那么就有90个请求是多余的。则可以设计一个计数器AutomicInteger(10),每个请求调用decreaseAndget方法,当计数器为0时不再接收请求,返回库存已空。然后再调用操作数据库的逻辑,当然要保证事务的原子性,全部成功后再提交并进入支付流程,否则返回购买失败信息。
对于锁问题,同时多个写入操作可能会引起锁的超时等待,可以提前将MySQL库存放到Redis中去,将写操作放到内存中,Redis不存在锁那么就不会存在等待。并且Redis的读写性能都高于MySQL,便解决了锁机制和性能问题。而对于超卖,可以通过MQ来解决,引入队列让写操作完全串行,这样就可以避免库存已尽的时候还有操作的情况。