跳到主要内容
版本:4.0.0 🚧

Redis

这里介绍如何快速在 Midway 中使用 Redis。

相关信息:

描述
可用于标准项目
可用于 Serverless
可用于一体化
包含独立主框架
包含独立日志

安装依赖

@midwayjs/redis 是主要的功能包。

$ npm i @midwayjs/redis@3 --save

或者在 package.json 中增加如下依赖后,重新安装。

{
"dependencies": {
"@midwayjs/redis": "^3.0.0",
// ...
}
}

引入组件

首先,引入组件,在 src/configuration.ts 中导入:

import { Configuration } from '@midwayjs/core';
import * as redis from '@midwayjs/redis';
import { join } from 'path';

@Configuration({
imports: [
// ...
redis // 导入 redis 组件
],
importConfigs: [
join(__dirname, 'config')
],
})
export class MainConfiguration {
}

配置 Redis

单客户端配置

// src/config/config.default.ts
export default {
// ...
redis: {
client: {
port: 6379, // Redis port
host: "127.0.0.1", // Redis host
password: "auth",
db: 0,
},
},
}

Sentinel 配置

// src/config/config.default.ts
export default {
// ...
redis: {
client: {
sentinels: [{ // Sentinel instances
port: 26379, // Sentinel port
host: '127.0.0.1', // Sentinel host
}],
name: 'mymaster', // Master name
password: 'auth',
db: 0
},
},
}

Cluster 模式配置,需要配置多个

// src/config/config.default.ts
export default {
// ...
redis: {
// Cluster Redis
client: {
cluster: true,
nodes: [{
host: 'host',
port: 'port',
},{
host: 'host',
port: 'port',
}],
redisOptions: {
family: '',
password: 'xxxx',
db: 'xxx'
}
}
},
}

多个客户端配置,需要配置多个

// src/config/config.default.ts
export default {
// ...
redis: {
// Multi Redis
clients: {
instance1: {
host: 'host',
port: 'port',
password: 'password',
db: 'db',
},
instance2: {
host: 'host',
port: 'port',
password: 'password',
db: 'db',
},
},
},
}

更多参数可以查看 ioredis 文档

使用 Redis 服务

我们可以在任意的代码中注入使用。

import { Provide, Controller, Inject, Get } from '@midwayjs/core';
import { RedisService } from '@midwayjs/redis';

@Provide()
export class UserService {

@Inject()
redisService: RedisService;

async invoke() {

// 简单设置
await this.redisService.set('foo', 'bar');

// 设置过期时间,单位秒
await this.redisService.set('foo', 'bar', 'EX', 10);

// 获取数据
const result = await this.redisService.get('foo');

// result => bar
}
}

可以使用 RedisServiceFactory 获取不同的实例。

import { RedisServiceFactory } from '@midwayjs/redis';
import { join } from 'path';

@Provide()
export class UserService {

@Inject()
redisServiceFactory: RedisServiceFactory;

async save() {
const redis1 = this.redisServiceFactory.get('instance1');
const redis2 = this.redisServiceFactory.get('instance3');

//...

}
}

也可以通过装饰器获取。

import { RedisServiceFactory, RedisService } from '@midwayjs/redis';
import { InjectClient } from '@midwayjs/core';

@Provide()
export class UserService {

@InjectClient(RedisServiceFactory, 'instance1')
redis1: RedisService;

@InjectClient(RedisServiceFactory, 'instance3')
redis2: RedisService;

async save() {
//...
}
}

服务发现

提供基于统一抽象的服务发现能力,虽然 Redis 一般不作为服务发现的注册中心,但是其拥有 pub/sub 能力可以变相提供功能,我们仍实现了 Redis 将作为服务发现的客户端能力。

服务发现包括 注册服务获取服务 两部分。

配置服务发现

你需要先配置一个客户端;若存在多个客户端,可通过 serviceDiscoveryClient 指定用于服务发现的客户端。

通过 serviceDiscovery 配置服务发现选项:

// src/config/config.default.ts
export default {
redis: {
clients: {
default: {
host: '127.0.0.1',
port: 6379
}
},
serviceDiscovery: {
prefix: 'services:',
ttl: 30,
scanCount: 100
}
}
}

注册服务发现

服务启动后,将当前服务注册到 Redis:

import { Configuration, Inject } from '@midwayjs/core';
import { RedisServiceDiscovery } from '@midwayjs/redis';

@Configuration({})
export class MainConfiguration {
@Inject()
redisDiscovery: RedisServiceDiscovery;

async onServerReady() {
const client = this.redisDiscovery.createClient();

await client.register({
serviceName: 'order',
id: client.defaultMeta.id,
host: client.defaultMeta.host,
port: 7001,
ttl: 30,
meta: { version: '1.0.0' }
});
// 注册默认上线,无需显式 online
}
}

说明:上线时写入实例键并设置 TTL,客户端会定时刷新 TTL 保持存活;下线删除实例键并清理刷新;注销发布变更消息以便 Listener 全量刷新。

获取可用服务

在任意位置获取可用实例或按负载均衡选择一个实例:

@Provide()
export class OrderService {
@Inject()
redisDiscovery: RedisServiceDiscovery;

async getService() {
const instances = await this.redisDiscovery.getInstances('order');
const one = await this.redisDiscovery.getInstance('order');
return { instances, one };
}
}

返回的实例为注册时写入的对象,通常包含 serviceName/id/host/port/ttl/meta/tags/status 等字段。