AI观察与大数据

不忘初心,砥砺前行!

先分享一篇文章,这是我在几年前阅读过的文章,原文在elthain.com网站上。后被网友在v2ex网站上分享。大概的故事是这样的:

一行代码引发的惨案

2011 年,Google 推出「 Panda 」机制动摇了很多老的 SEO 手段,digg 流量被腰斩。推出 DiggV4 作战计划。经过紧张的开发发布,不过访客页面没问题,已登录用户打不开 MyNews 页面。开发不得不用临时手段把登录用户的默认页面改成 TopNews。MyNews 只能通过不断重启进程才能短暂修复。初期以为是 cassandra 的缓存击穿了 memcache,后来加紧用 redis 重写了,还是得每4个小时重启一次进程。

(折腾了一个月之后)

阅读全文 »

在我们的系统中部署了很多套MongoDB的集群,但是有的时候会发现MongoDB启动不起来,或者启动之后一会儿MongoDB实例就挂了,也不知道是什么原因。我们按照如下方式进行了排查:

  1. 检查所在宿主OS中MongoDB的存储磁盘空间是否足够
  2. 检查所在宿主OS中的空闲内存是否足够
    使用命令free -h或者用命令top也可以
  3. 检查MongoDB的运行日志
  4. 通过top -p pid命令跟踪进程的内存占用 发现进程突然被kill掉。怀疑这时是因为进程的内存增长过快导致[2]
阅读全文 »

在很多系统中都有打标签的需求,比如图片、书籍、电影、博客、评论等,并且打标签的对象往往是海量数据。这就给系统的设计提出了挑战:

  • 要求可以根据标签进行分组、过滤、协同查询(比如标签的并集、交集、差集等等)
  • 要求查询的效率很高
  • 要求整个标签系统的扩展性很强
阅读全文 »

建模原则

  1. 数据库字段小写,下划线连接;每个字段都需要由COMMENT,说明其业务含义。

  2. 使用id作为主键,建议类型为bigint(20), 其对应的java类型为Long。

    • Mybatis Plus框架自动生成主键插入(雪花算法)
    • 也可以使用数据库自增,当只有1个服务,数据量较小的时候建议选择,提升插入性能。
  3. update_time、create_time
    使用timestamp或者datetime作为时间类型的首选。Mybatis-Plus框架生成的相应Java类型都是LocalDateTime。大部分场景下2种类型可以互相替换,不过在时间范围和时区支持上有差异。
    使用MySQL的自动初始化和自动更新功能。 字段变化之后,update_time数据库自动更新,如下:

1
2
3
4
create_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_by varchar(36) DEFAULT NULL COMMENT '创建人',
update_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
update_by varchar(36) DEFAULT NULL COMMENT '更新人',
  1. 布尔型字段使用tinyint(1)即可。
  2. 参考《阿里巴巴Java开发手册(华山版).pdf》。

雪花算法实现

阅读全文 »

Snapshots和release仓库

二者区别是什么

Snapshot[2],快照,是一种特殊的版本,指定了某个当前的开发进度的副本。不同于常规的版本,Maven 每次构建都会在远程仓库中检查新的快照。比如发布了一个app-1.0-SNAPSHOT版本,那么maven构件的时候,每次都会去仓库检查是否有最新的版本已经被发布。如果有,则替换。如果是release仓库,那么除非版本升级,否则maven构件的时候不会去检查最新的jar包,即便是在nexus仓库中已经更新了。

maven中的仓库分为两种[3],snapshot快照仓库和release发布仓库。snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本。

定义一个组件/模块为快照版本,只需要在pom文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写),如下:

1
2
3
4
5
6
7
8
9
<groupId>com.schdri</groupId>
<artifactId>bimgis</artifactId>
<version>3.10.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<packaging>pom</packaging>
<organization>
<name>pig4cloud</name>
<url>https://www.pig4cloud.com</url>
</organization>
阅读全文 »

MongoDB无疑是当前在各个领域中NoSQL优选的文档数据库之一。原因在于部署简单,可扩展性强,原生支持javascript脚本编程。对于使用Spring全家桶的团队来说,是一个很好的选择,可以快速的搭建一个服务出来。如果是用JS或者Typescript语言的话,使用mongoose的ORM框架结合到express框架,生产力会提高一大截。

稍显不足的是,MongoDB对于中文索引支持的力度不够,对于某些要求强事务的领域应用(比如金融、财务等)略显不足,至少还没有看到有成熟应用的案例。如果有,请告诉我。另外一个就是,在搭建MongoDB集群的时候,相对来说是比较复杂的。水平扩展虽然很简单,但是做Sharding的时候也需要仔细的考量。

本文简单介绍一下如何在Spring Boot/Spring Cloud程序中使用MongoDB数据库。

Java Config

第一种方式就是采用Java Config的方式,直接上代码,如下:

阅读全文 »

建模原则:

  1. 数据库名字、Collection名字、属性字段均小写,并使用下划线连接。
    但是对应的Java DAO对象的属性字段需要按照驼峰命名法书写,并且每个字段都需要加上@Field注解,即使数据库字段和名字是完全一样的。

  2. 对于大规模数据,字段存储的时候使用缩写。

  3. 如果嵌套的Document数量会不断的增长或者频繁发生变化,那么可以考虑单独存Collection

    The maximum BSON document size is 16 megabytes.

  4. 如果从逻辑上对象是从属并且是1:1的关系,直接使用嵌套对象。

    但是如果多个地方使用了同一个对象,比如A包含了B, C也包含了B,那么可以考虑将B单独建集合,然后通过DBRefs(对于Spring Data Mongo来说就是注解@DBRef)来引用。

建索引原则:

  1. 复合索引不在Java POJO对象上加注解完成。而是手工创建。

  2. 对于复合索引,要将能够快速缩小数据范围(命中率更高)的字段放在复合索引前面并排序。

  3. 稀疏索引,如果某字段对于大部分数据都可能不存在,或者为null, 要指定该索引为稀疏索引

参考文档:

https://docs.mongodb.com/manual/core/document/

Nacos遇到MySQL 8版本连接会报错,并且MySQL多次连接报错之后会拒绝连接。遇到这种情况之后登陆到mysql,然后flush hosts。

在Nacos 1.2.0版本中解决了连接MySQL 8报错的问题[1].

1. 下载对应版本的connector

比如mysql-connector-java-8.0.17.jar[2]。注意这里加载的jar包对应的版本必须要和MySQL版本完全一致。否则可能出现报错。

2. 配置nacos的mysql插件

在nacos目录下新建 plugins/mysql/mysql-connector-java-8.0.17.jar

3. 配置连接数据库,然后启动nacos


  1. 1.https://github.com/alibaba/nacos/issues/2042
  2. 2.https://downloads.mysql.com/archives/c-j/

DOM是什么?

Document Object Model[0],简称DOM, 文档对象模型, 是一套抽象的、单一的、具有一致性的API。这一套API是与具体实现和具体语言无关的。在WHATAG CORE 3 Living Standard[1]上通过Web IDL定义给出。

HTML和定义良好的XML都是结构化,里面的内容、表现、属性都可以通过节点和对象的方式来表示,形成一棵树形结构(或者是森林)。而DOM所定义的API就是用来访问、操作、修改里面的数据。

阅读全文 »

1. 星形拓扑的通信模型

星形的意思是说,有一个消息接收和转发中心,应用两两之间并不直接通信。所有的应用层消息都通过Kafka集群进行中转。但是对Kafka来说,消息的机制是推拉机制。如果需要接收消息,需要应用层连接到集群,订阅感兴趣的topic,然后poll消息。

为了实现这种模型,
1. 我们利用Kafka本身的ACL控制机制来对topic权限进行控制

  • 对每一个应用分配唯一的Consumer Group。
  • 对每一个接入的应用分配唯一的账户和密码。
  • 对每一个接入的应用分配SSL证书
  • 对每一个topic按照应用进行配置读写权限。
  • 对每一个接入的应用分配一个唯一的秘钥(该秘钥通过安全方式传递)。

2. 同时我们在应用包装一层API进行消息分派机制

  • 应用层的消息需要进行加密。
  • 应用层需要校验消息的来源和完整性。
  • 判断该消息是否应该被处理,比如消息的接收方是否包含了自己。
  • 应用层需要按照消息的业务ID(或者其他机制)分派合适的处理函数。
阅读全文 »
0%