Skip to content

Commit

Permalink
Add english document
Browse files Browse the repository at this point in the history
  • Loading branch information
adaex authored Aug 29, 2021
1 parent 1315325 commit 00b5ff7
Show file tree
Hide file tree
Showing 2 changed files with 318 additions and 79 deletions.
173 changes: 94 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,214 +5,229 @@
[![npm downloads](https://img.shields.io/npm/dm/coa-redis.svg?style=flat-square)](http://npm-stat.com/charts.html?package=coa-redis)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/coajs/coa-redis/pulls)

COA 核心 Redis 数据库组件,包含数据缓存、消息队列、定时任务、分布式锁等
English | [简体中文](README.zh-CN.md)

## 特点
Redis database components for coajs, including data cache, message queue, timing task, distributed lock, etc.

- **功能齐全** 基础数据连接基于 [ioredis](https://github.com/luin/ioredis) ,注重性能、功能齐全
- **简单轻量** 仅几百行代码,不依赖于其他第三方库
- **TypeScript** 全部使用 TypeScript 书写,类型约束、IDE 友好
## Feature

## 组件
- **Functional**: Basic data connection based on [ioredis](https://github.com/luin/ioredis). Pay attention to performance, full-featured
- **Lightweight**: Only hundreds of lines of code, do not rely on other third-party libraries
- **TypeScript**: All written in TypeScript, type constraint, IDE friendship

- 数据缓存 [RedisCache](#数据缓存) 用于 Key-Value 类型的数据缓存
- 消息队列 [RedisQueue](#消息队列) [RedisQueueWorker](#消息队列) 基于 Redis 实现轻量高效的消息队列
- 定时任务 [RedisCron](#定时任务) 通过 Cron 表达式和消息队列按时执行任务
- 分布式锁 [RedisLock](#分布式锁) 通过 Redis 实现基本的分布式锁机制
## Component

## 快速开始
- Data Cache [RedisCache](#Data-Cache): Data cache for Key-Value type
- Message Queue [RedisQueue](#Message-Queue) [RedisQueueWorker](#消息队列): Lightweight and efficient message queue based on Redis implementation
- Timing Task [RedisCron](#Timing-Task): Perform tasks on time through the cron expression and message queue
- Distributed Lock [RedisLock](#Distributed-Lock): Basic distributed lock mechanism by Redis

### 安装
## Quick Start

### Install

```shell
yarn add coa-redis
```

### 基础配置
### Basic configuration

```typescript
import { RedisBin } from 'coa-redis'

const redisConfig = {
// 服务器地址
// host address
host: '127.0.0.1',
// 端口
// port
port: 6379,
// 密码,若无填空字符串
// password, if not write an empty string
password: '123456',
// 数据库,默认为0
// database, default is 0
db: 0,
// 键前缀,可区分不同的项目
// Key prefix, distinguish between different project
prefix: 'pre_',
// 是否回显查询语句
// Whether to display a query statement
trace: false,
}

// 创建一个配置实例,后续所有的组件的使用均依赖此配置实例
// 一般一个数据库只需要使用一个实例,内部会管理连接池
// Create a configuration instance, follow-up all components depending on this configuration instance
// Generally a database only needs to use an instance, the internal management connection pool
const redisBin = new RedisBin(redisConfig)
```

### 组件使用
### Component usage

#### 数据缓存
#### Data Cache

基本使用
Basic usage

```typescript
// 创建一个缓存实例
// Create a cache instance
const redisCache = new RedisCache(redisBin)

// 注意:为了约束模块数据的隔离,缓存实例的所有操作均需要传递nsp参数且无法省略
// 一般可将模块名称当做nsp,每个nsp之间数据相互隔离
// Note: In order to constrain the isolation of module data, all operations of the cache instance need to pass nsp parameters and cannot be omitted.
// Generally, the module name can be used as nsp, and the data between each nsp is isolated from each other.

// 设置缓存数据
await redisCache.set('module1', 'id001', 'value001', 5 * 60 * 1000 /*5分钟*/) // 1
// Set cache data
await redisCache.set(
'module1',
'id001',
'value001',
5 * 60 * 1000 /*5 minutes*/
) // 1

// 读取缓存数据
// Read cache data
await redisCache.get('module1', 'id001') // value001

// 删除缓存数据(支持删除同一个nsp下的多条数据)
// Delete cache data (support to delete multiple data under the same nsp)
await redisCache.delete('module1', ['id001', 'id002']) // 2
```

批量操作
Batch operate

```typescript
// 批量设置缓存数据
await redisCache.mSet('module1', { id101: 'value101' }, 5 * 60 * 1000 /*5分钟*/) // 1
await redisCache.mSet('module2', { id201: 'value201', id202: { name: 'A2', title: 'a2' } }, 5 * 60 * 1000 /*5分钟*/) // 2

// 批量读取缓存数据
// Batch set cache data
await redisCache.mSet(
'module1',
{ id101: 'value101' },
5 * 60 * 1000 /*5 minutes*/
) // 1
await redisCache.mSet(
'module2',
{ id201: 'value201', id202: { name: 'A2', title: 'a2' } },
5 * 60 * 1000 /*5 minutes*/
) // 2

// Batch read cache data
await redisCache.mGet('module1', ['id101']) // 'value101'
await redisCache.mGet('module2', ['id201', 'id202']) // { id201: 'value201', id202: { name: 'A2', title: 'a2' }

// 批量删除缓存数据(支持删除不同nsp下的多条数据)
// Batch delete cache data (support to delete multiple data under different nsp)
await redisCache.mDelete([
['module1', ['id101']],
['module2', ['id201', 'id202']],
]) // 3
```

语法糖
Syntactic sugar

```typescript
// 获取缓存信息,如果不存在则按照方法读取并保存
// Get cache data, if there is no existence, follow the method to read and save
const resultWarp1 = await redisCache.warp(
'module1',
'id301',
() => {
// 这里做一些事情
return Math.random() // 返回结果
// Do something here
return Math.random() // return result
},
10 * 60 * 1000 /*10分钟*/
10 * 60 * 1000 /*10 minutes*/
)

resultWarp1 // 0.3745813097015189,10分钟内都返回 0.3745813097015189
resultWarp1 // return 0.3745813097015189 with in 10 minutes

// 这个语法糖等同于如下操作
// This Syntactic sugar is equivalent to the following
async function getAndSetCache(nsp: string, id: string) {
let result = await redisCache.get(nsp, id)
if (result === undefined) {
// 这里做一些事情
result = Math.random() // 得到结果
await redisCache.set(nsp, id, result, 10 * 60 * 1000 /*10分钟*/)
// Do something here
result = Math.random() // get result
await redisCache.set(nsp, id, result, 10 * 60 * 1000 /*10 minutes*/)
}
return result
}

// 批量获取缓存信息
// Batch get cache data
const resultWarp2 = await redisCache.mWarp(
'module1',
['id301', 'id302'],
(ids) => {
const result = {} as { [id: string]: number }
for (const id of ids) {
// 这里做一些事情
// Do something here
result[id] = Math.random()
}
return result // 返回结果,务必保证键值对形式
return result // Return the result, be sure to ensure the key value
},
10 * 60 * 1000 /*10分钟*/
10 * 60 * 1000 /*10 minutes*/
)

resultWarp2 // { id301: 0.32430600236596074, id302: 0.29829421673682566 }
```

#### 消息队列
#### Message Queue

```typescript
// 定义一个队列名称和消息类型名称
// Define a queue name and message type name
const QUEUE_NAME_1 = 'CHANNEL-1',
MESSAGE_NAME_1 = 'NORMAL-MESSAGE-1'

// 定义一个消息队列
// Define a message queue
const queue = new RedisQueue(redisBin, QUEUE_NAME_1)

// 定义该队列的消费者
// Define the consumer of the queue
const worker = new RedisQueueWorker(queue)
worker.on(MESSAGE_NAME_1, async (id, data) => {
console.log(`消息的ID是${id} 消息附带的数据${data}`)
console.log(`message id is ${id}, message included with ${data}`)
})

// 生产一个消息
// Produce a message
await queue.push(MESSAGE_NAME_1, 'message-id-001', { value: '001' }) // 1
```

#### 定时任务
#### Timing Task

```typescript
// 定时任务依赖于消息队列的消费者,同时要指定版本号避免版本升级瞬间任务冲突
// Timing task relies on the consumer of the message queue, and at the same time, you must specify the version number to avoid version upgrade instant task conflicts
const cron = new RedisCron(quque.worker, env.version)

// 每天10、16点执行
// Execute at 10:00 and 16:00 each day
cron.on('0 0 10,16 * * *', () => {
/**做一些事情**/
/**Do something**/
})

// 每天0:30执行
// Execute at 0:30 each day
cron.on('0 30 0 * * *', () => {
/**做一些事情**/
/**Do something**/
})

// 每10分钟执行
// Execute every 10 minutes
cron.on('0 */10 * * * *', () => {
/**做一些事情**/
/**Do something**/
})

// 每周一周三周五0点执行
// Execute at 0:00 on every Monday, Wednesday, Friday
cron.on('0 0 0 * * 1,3,5', () => {
/**做一些事情**/
/**Do something**/
})

// 每月1日、16日的0点执行
// Execute at 0:00 on every month of 1 day and 16
cron.on('0 0 0 1,16 * *', () => {
/**做一些事情**/
/**Do something**/
})
```

#### 分布式锁
#### Distributed Lock

```typescript
// 创建锁方法实例
// Create a lock method instance
const redisLock = new RedisLock(redisBin)

// 阻塞执行,如果重复调用,会一直等待上一次调用完成
// Blocking execution, if the call is repeated, will wait for the last call to complete
await redisLock.start('lock-for-user-register', () => {
// 做一些事情,这个事情不会并发执行
// Do something, this thing will not be executed concurrently
})

// 尝试执行,如果是重复调用,则会抛出 RedisLock.Running 错误
// Try to execute, if it is repeated call, it will throw the RedisLock.Running error
await redisLock.try('lock-for-user-register', () => {
// 做一些事情,这个事情不会并发执行
// Do something, this thing will not be executed concurrently
})

// 节流执行,1秒内只允许调用1次,重复调用会排队等待下一个1秒再执行
// The throttle is executed, only 1 second is allowed once, and the repeat call will be queued to wait for the next 1 second.
await redisLock.throttle(
'lock-for-user-register',
() => {
// 做一些事情,这个事情不会并发执行
// Do something, this thing will not be executed concurrently
},
1000 /*1秒钟*/
1000 /*1 second*/
)
```
Loading

0 comments on commit 00b5ff7

Please sign in to comment.