npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sasdn-database

v1.0.14

Published

## 1. 简介

Downloads

34

Readme

SASDN-Database

1. 简介

SASDN-Database是基于Typeorm的封装,内部实现了分库分表的功能,对于开发者来说,只需要遵循一些规范即可像原来一样通过操作对象的方式来操作数据库。

2. 功能

2.1 ShardKey

若需要使用分表功能,首先要了解什么是ShardKeyShardKey是表中的一个字段,但是一定要保证唯一。插件读取此字段的值然后根据一致性hash算法去计算该条数据具体落在那一张分表上。用户只需在设计表时思考好今后使用哪一个字段并保证其唯一性即可。

该字段在设计表结构时需要定义,在代码编写运行时会用到,在设置及Entity代码定义中不需要使用。

2.2 分表

当用户指定完ShardKey后,可以通过装饰器ShardTable定义所需分表的数量,插件会自动进行分表操作,对用户来说是无感知的。一张需要进行分表的Entity类似下面的代码:

import { Entity, Column, PrimaryColumn } from 'typeorm';
import { BaseOrmEntity, ShardTable } from 'sasdn-database';

@Entity('shard_table') // 定义表名
@ShardTable(5)		   // 定义分表数量
export class ShardEntity extends BaseOrmEntity {  // 继承BaseOrmEntity
  @PrimaryColumn({ type: 'bigint', name: 'table_id' })
  tableId: number;

  @Column({ type: 'varchar', name: 'table_desc', length: 255})
  tableDesc: string;
}

2.3 分库

分库将根据用户给定的DatabaseOptions中的shardingStrategies字段读取用户希望那张表落于那个库上,若用户不指定则默认使用取余的方式将所有表散列到所有库上。自定义配置如下,有两种情况需要注意:

  1. 有分表需求,则需要在原来的表名后添加_${表号}
 shardingStrategies: [ 
    { 
      connctionName: 'test_shard_0', 
      entities: [ 
        'ShardEntity_0', 
        'ShardEntity_3', 
      ], 
    }, 
    { 
      connctionName: 'test_shard_1', 
      entities: [ 
        'ShardEntity_1', 
        'ShardEntity_4', 
      ], 
    }, 
    { 
      connctionName: 'test_shard_2', 
      entities: [ 
        'ShardEntity_2', 
      ], 
    }, 
  ], 
  1. 无分表需求,则只需给定具体那张表落在那个库上即可
shardingStrategies: [ 
    { 
      connctionName: 'test_shard_0', 
      entities: [ 
        'GameUser',  
      ], 
    }, 
    { 
      connctionName: 'test_shard_1', 
      entities: [ 
        'GameBind', 
        'GameGuid',
      ], 
    }, 
    { 
      connctionName: 'test_shard_2', 
      entities: [ 
        'GameInfo', 
      ], 
    }, 
  ], 

3. 规范定义

  • 所有Entity类均需要继承BaseOrmEntity
  • 分表需要使用ShardTable装饰器,并给定分表数量
  • 将所有Entity类统一放在一个entities文件夹中,并且在命名中不要使用_
  • 统一通过getEntity方法获得获得具体Entity
  • 使用DatabaseOptions对数据库链接进行声明,并调用initialize进行初始化

4. 具体使用

4.1 定义数据库文件

首先需要定义数据库文件的sql文件(若使用NOSQL则无需定义),然后根据定义好的sql文件写相应的Entity,一个简单的EntityClass如下:

import { Entity, Column, PrimaryColumn } from 'typeorm';
import { BaseOrmEntity, ShardTable } from 'sasdn-database';

@Entity('shard_table') // 定义表名
@ShardTable(5)		   // 定义分表数量
export class ShardEntity extends BaseOrmEntity {  // 继承BaseOrmEntity
  @PrimaryColumn({ type: 'bigint', name: 'guid' })
  tableid: number;

  @Column({ type: 'varchar', name: 'table_desc', length: 255})
  tableDesc: string;
}

4.2 定义DatabaseOptions

然后我们可以在通过sql文件创建完表之后编写数据库链接配置:

const databaseOptions: DatabaseOptions = {
  name: 'mysql',
  type: 'mysql',
  // 需要先在数据库上生成对应的表,不然会报错
  // 第一次使用可不指定,使用默认进行表分配
  shardingStrategies: [ 
    { 
      connctionName: 'test_shard_0', 
      entities: [ 
        'ShardEntity_0', 
        'ShardEntity_3', 
      ], 
    }, 
    { 
      connctionName: 'test_shard_1', 
      entities: [ 
        'ShardEntity_1', 
        'ShardEntity_4', 
      ], 
    }, 
    { 
      connctionName: 'test_shard_2', 
      entities: [ 
        'ShardEntity_2', 
      ], 
    }, 
  ], 
  connectionList: [
    {
      name: 'test_shard_0',
      type: 'mysql',
      host: '127.0.0.1',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test_shard_0',
      synchronize: false,
      // 默认采用*.js进行泛指
      entities: [LibPath.join(__dirname, 'entities/*.js')],
    },
    {
      name: 'test_shard_1',
      type: 'mysql',
      host: '127.0.0.1',
      port: 3307,
      username: 'root',
      password: 'root',
      database: 'test_shard_1',
      synchronize: false,
      entities: [LibPath.join(__dirname, 'entities/*.js')],
    },
    {
      name: 'test_shard_2',
      type: 'mysql',
      host: '127.0.0.1',
      port: 3308,
      username: 'root',
      password: 'root',
      database: 'test_shard_2',
      synchronize: false,
      entities: [LibPath.join(__dirname, 'entities/*.js')],
    },
  ],
};

4.3 初始化链接

然后我们就需要调用初始化函数:

// 第二个参数将在制定目录生成一份数据库链接对应具体Entity的Json文件,方便
// 后续进行维护和查询,若不指定可从console中查看具体输出
DatabaseFactory.instance.initialize(databaseOptions, __dirname);

4.4 编写业务代码

然后我们就可以编写对应的数据库操作:

\\ Write
const EntityModule = DatabaseFactory.instance.getEntity(ShardEntity.name, shardKey);
const entity = new EntityModule(shardKey);
entity.tableId = shardKey;
entity.tableDesc = shardKey.toString();
try {
  const result = await entity.save();
  console.log(`write[${success}] success result = ${result}`);
} catch (error) {
  console.log('on save caught error = ', error);
}

\\ Read
const EntityModule = DatabaseFactory.instance.getEntity(ShardEntity.name, shardKey);
try {
  let result = await EntityModule.findOne({ tableId: shardKey });
  console.log(`read[${success}] success result = ${result}`);
} catch (error) {
  console.log('on save caught error = ', error);
}

具体可以参考samples中的例子。例子中使用sqlite3进行一个简单的数据库操作,在目录下直接执行npm start即可。