其实有了那篇服务开发总结,这篇看起来没什么必要了,不过作为纯技术的总结还是发出来吧。
在前几篇中说到了es的jdbc工具,这个工具确实挺好,可以满足一些不想要开发量的小公司的要求。
但从我们使用的过程中也看出了这个工具的一些缺陷:
1.方案强依赖于数据库表的时间戳。
不靠谱,你不能要求你的业务RD或者老的遗留系统能够满足你的这些规范方面的要求(刚从dc出来的时候感觉很多规范方面的事情是应该做的,但根据工作经历来看,设计技术方案最好还是要考虑到最坏的情况)。
2.这个工具每一个脚本只能执行一条sql语句。
这是一个比较重大的缺陷,因为工具本身是java写的,这就意味着每个脚本都是在独立的jvm里跑。而jvm,你懂的。基本一台64GB的机器跑个七八个脚本,再加上es本身,内存就快要爆掉了。而实际上这件事情本身不应该需要这么大的硬件成本。
3.读写分离问题导致的数据延迟问题。
这条其实是1衍生出来的,同样考虑最坏的情况,主从延迟如果到了一定程度,那么在脚本运行期间内会导致时间戳前进之后,有旧数据入到从库。那么脚本的逻辑就会产生数据丢失。
前几天在公司做了一次分享,其实是类似于工作汇报的东西。。。顺便记了一些东西,整理一下吧:
这个服务完成了的事情
1).独立的es集群
目前线上正在运行的版本是1.7.3
三台机器,总数据量大概在100G左右(算上分片的冗余)
集群上安装有head、bigdesk、ik分词器等插件
存在的问题:
es版本其实已经有点老了。。官方在2.1和2.2又加入了一些新特性,这些特性在老版本里我们享受不到,当然现在的接入功能也比较简单,也不一定用得到。但不升级自然就享受不到官方版本升级带来的红利:新功能,新bug
2).在es之前封装了一层web服务
用golang的web框架gin
> https://github.com/
在上次的一致性哈希讲解中,提到了虚拟结点的生成算法。说得不怎么明白,本文将会对常用的两种虚拟结点生成算法进行一些简单的解析。
我们以Google的groupcache和经典应用memcached来做例子进行说明。
首先是groupcache,在groupcache中生成虚拟结点的算法代码如下:
func (m *Map) Add(keys ...string) {
for _, key := range keys {
for i := 0; i < m.replicas; i++ {
hash := int(m.hash([]byte(strconv.Itoa(i) + key)
很多事情真是说起来容易做起来难,就比如说起来很简单的:
> 把mysql的数据同步到elasticsearch里
听着很简单吧,我们有各种现成的工具,之前调研了半天,选择了elasticsearch
jdbc这种类似river的工具,根据数据表里的update_time来做数据同步。将lastexecutionstart作为时间参数传到sql里,构成了下面这样的sql
select *, id as _id from [业务表] where update_time > ?
? = lastexecutionstart
看着是不是挺天衣无缝的?
如果真的这么顺利就好了。。。。
实际操作的时候发现了很多问题:
首先,我们的代码里没有在创建数据条目的时候填update_time,我&$@#$$(@#)*$。
而这种”显然我就不遵守既定的常识“的事情在我现在参与的这个系统里尤其的多。这种我觉得还是规范的问题,
本文是官方Transactions小节的文档翻译,因为之前对redis的事务一直比较疑惑,这里做一次记录:
MULTI,EXEC,DISCARD和WATCH是redis里构成事务的4个基础命令。通过redis的事务,可以做到一次执行一组命令,关于事务redis有两方面的保证:
1. 在一个事务中的所有命令会被串行化并且是按照顺序依次执行。在事务执行期间一定不会被插入其它客户端传入的命令。这一点保证了这些命令是一个独立的执行体(独立性)。
2. 所有的命令要么全部被执行,要么没有一条被执行,所以一个redis的事务同样也具有原子性。EXEC这个命令会触发事务中所有的命令开始执行,所以在客户端在执行了MULTI命令之后(
官方这里写的是之前,但是我觉得不对
)的事务上下文中丢生了和服务器的连接,那么任何一条命令都不会被执行,但如果EXEC已经开始执行了的话,所有的命令都会被执行完。当使用append-only
文件作为Redis的持久化方式时,Redis会确保用write的系统调用来将事务写到磁盘上。然而如果Redis服务器在保存过程中崩