vapor-docs/docs/redis/overview.zh.md

170 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Redis
[Redis](https://redis.io/) 是一种最流行的内存数据结构存储,通常用作缓存或消息代理。
这个库是 Vapor 和 [**RediStack**](https://github.com/swift-server/RediStack) 的集成,它是与 Redis 通信的底层驱动程序。
!!! note "注意"
Redis 的大部分功能都是由 **RediStack** 提供的。我们强烈建议你熟悉其文档。
_链接稍后提供。_
## Package
使用 Redis 的第一步是将它作为依赖项添加到你的 Package.swift 文件中。
> 本示例针对已有项目,要了解如何构建新项目,请参阅[入门指南](../getting-started/hello-world.zh.md)。
```swift
dependencies: [
// ...
.package(url: "https://github.com/vapor/redis.git", from: "4.0.0")
]
// ...
targets: [
.target(name: "App", dependencies: [
// ...
.product(name: "Redis", package: "redis")
])
]
```
## 配置
Vapor 对 [`RedisConnection`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/redisconnection) 实例采用池化策略,并且有几个选项可以配置单个连接以及池本身。
配置 Redis 的最低要求是提供一个 URL 来连接:
```swift
let app = Application()
app.redis.configuration = try RedisConfiguration(hostname: "localhost")
```
### Redis 配置
> API 文档:[`RedisConfiguration`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration)
#### 服务器地址
如果你有多个 Redis 端点,比如一个 Redis 实例集群,你需要创建一个 [`[SocketAddress]`](https://swiftpackageindex.com/apple/swift-nio/main/documentation/niocore/socketaddress) 集合来传递给初始化器。
创建 `SocketAddress` 最常见的方法是使用 [`makeAddressResolvingHost(_:port:)`](https://swiftpackageindex.com/apple/swift-nio/main/documentation/niocore/socketaddress/makeaddressresolvinghost(_:port:)) 静态方法。
```swift
let serverAddresses: [SocketAddress] = [
try .makeAddressResolvingHost("localhost", port: RedisConnection.Configuration.defaultPort)
]
```
对于单个 Redis 端点,使用便利构造器初始化更容易,因为它将为你创建 `SocketAddress`
- [`.init(url:pool)`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/init(url:tlsconfiguration:pool:)-o9lf) (带 `String` 或 [`Foundation.URL`](https://developer.apple.com/documentation/foundation/url))
- [`.init(hostname:port:password:database:pool:)`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/init(hostname:port:password:tlsconfiguration:database:pool:))
#### 密码
如果你的 Redis 实例受密码保护,则需要将其作为 `password` 参数传递。
每个连接在创建时都将使用密码进行身份验证。
#### 数据库
这是你希望在创建每个连接时选择的数据库索引。
这使你不必自己将 `SELECT` 命令发送到 Redis。
!!! warning "警告"
未维护数据库选择。在自己发送 `SELECT` 命令时要小心。
### 连接池选项
> API 文档:[`RedisConfiguration.PoolOptions`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/pooloptions)
!!! note "注意"
这里只突出显示最常更改的选项。对于所有选项,请参考 API 文档。
#### 最小连接数
这是设置你希望每个池始终保持多少连接的值。
值为`0`时,如果连接因任何原因丢失,则池在需要之前不会重新创建它们。
这被称为`冷启动`连接,并且在维持最小连接数方面确实有一些开销。
#### 最大连接数
此选项确定如何维护最大连接数的行为。
!!! seealso "也可以看看"
请参阅 `RedisConnectionPoolSize` API 文档以熟悉更多可用选项。
## 发送命令
你可以使用 [`Application`](https://api.vapor.codes/vapor/documentation/vapor/application) 或 [`Request`](https://api.vapor.codes/vapor/documentation/vapor/request) 实例上的 `.redis` 属性发送命令,这使得你可以访问 [`RedisClient`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/redisclient)。
对于各别的 [Redis 命令](https://redis.io/commands)`RedisClient` 都有其对应的扩展。
```swift
let value = try app.redis.get("my_key", as: String.self).wait()
print(value)
// Optional("my_value")
// or
let value = try await app.redis.get("my_key", as: String.self)
print(value)
// Optional("my_value")
```
### 不支持的命令
如果 **RediStack** 不支持带有扩展方法的命令,你仍然可以手动发送它。
```swift
// command 后的每个值都是 Redis 期望的位置参数
try app.redis.send(command: "PING", with: ["hello"])
.map {
print($0)
}
.wait()
// "hello"
// or
let res = try await app.redis.send(command: "PING", with: ["hello"])
print(res)
// "hello"
```
## 发布/订阅 模式
Redis 支持进入[发布/订阅模式](https://redis.io/topics/pubsub),其中连接可以监听特定的`通道`,并在订阅的通道发布`消息`(一些数据值)时运行特定的闭包。
订阅的生命周期定义:
1. **subscribe**:订阅第一次开始时调用一次
1. **message**:在消息发布到订阅频道时调用 0+ 次
1. **unsubscribe**:订阅结束时调用一次,无论是通过请求还是连接丢失
创建订阅时,你必须至少提供一个 [`messageReceiver`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/redissubscriptionmessagereceiver) 来处理订阅频道发布的所有消息。
你可以选择为 `onSubscribe``onUnsubscribe` 提供一个 `RedisSubscriptionChangeHandler` 来处理它们各自的生命周期事件。
```swift
// 创建2个订阅每个给定频道一个订阅
app.redis.subscribe
to: "channel_1", "channel_2",
messageReceiver: { channel, message in
switch channel {
case "channel_1": // 处理消息
default: break
}
},
onUnsubscribe: { channel, subscriptionCount in
print("unsubscribed from \(channel)")
print("subscriptions remaining: \(subscriptionCount)")
}
```