RediStack: Асинхронный Redis клиент для Swift (iOS/macOS)
RediStack — это современный, полностью асинхронный клиент для работы с Redis, написанный на Swift. Библиотека построена на основе фреймворка SwiftNIO, что обеспечивает высокую производительность и низкое потребление памяти. RediStack идеально подходит для iOS и macOS приложений, требующих быстрого кэширования, управления сессиями, очередей сообщений или Pub/Sub функциональности.
Основные возможности
- Полная асинхронность на базе Swift Concurrency (async/await) и Combine
- Поддержка всех основных типов данных Redis: строки, списки, множества, хеши, потоки
- Встроенная поддержка Pub/Sub с автоматическим переподключением
- Автоматическое пулингование соединений (Connection Pool)
- Поддержка Redis Cluster и Sentinel
- SSL/TLS шифрование для безопасного соединения
- Типобезопасные команды с автодополнением в Xcode
Установка с помощью Swift Package Manager
Добавьте RediStack в ваш Package.swift или через Xcode:
// Package.swift
dependencies: [
.package(url: "https://github.com/RediStack/RediStack.git", from: "1.6.0")
],
targets: [
.target(name: "YourApp", dependencies: ["RediStack"])
]
Быстрый старт: подключение к Redis
Для начала работы создайте пул соединений и выполните простые команды:
import RediStack
import NIO
// Создаем EventLoopGroup
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
// Настраиваем пул соединений
let pool = RedisConnectionPool(
configuration: .init(
initialServerConnectionAddresses: [try .init(hostname: "localhost", port: 6379)],
maximumConnectionCount: .maximumActiveConnections(5)
),
boundEventLoop: eventLoopGroup.next()
)
// Асинхронная работа с Redis
Task {
do {
// Установка и получение строки
try await pool.set("greeting", to: "Hello from Swift!")
let value = try await pool.get("greeting", as: String.self)
print("Получено: \(value ?? "nil")") // "Получено: Hello from Swift!"
// Работа со списками
try await pool.lpush(["apple", "banana", "cherry"], into: "fruits")
let fruits = try await pool.lrange(from: "fruits", firstIndex: 0, lastIndex: -1, as: [String].self)
print("Фрукты: \(fruits)") // ["cherry", "banana", "apple"]
} catch {
print("Ошибка Redis: \(error)")
}
}
Пример: Pub/Sub (издатель-подписчик)
RediStack поддерживает полноценный Pub/Sub с автоматическим восстановлением подписки:
import RediStack
import NIO
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2)
let pool = RedisConnectionPool(...)
// Подписчик
Task {
let subscriber = pool.makeSubscriber(eventLoop: eventLoopGroup.next())
// Подписка на канал
await subscriber.subscribe(to: "notifications") { channel, message in
print("Получено на канале \(channel): \(message.string ?? "")")
}
// Обработка ошибок подписки
subscriber.onError = { error in
print("Ошибка Pub/Sub: \(error)")
}
}
// Издатель (отправка сообщения)
Task {
try await pool.publish("Новое уведомление", to: "notifications")
}
Работа с хешами и транзакциями
Пример использования хешей и атомарных операций с помощью транзакций:
// Установка полей хеша
try await pool.hmset("user:1001", with: [
"name": "Иван Петров",
"email": "ivan@example.com",
"age": "30"
])
// Получение всех полей
let user = try await pool.hgetall(from: "user:1001")
print("Имя: \(user["name"]?.string ?? "")") // "Имя: Иван Петров"
// Транзакция (атомарное выполнение)
try await pool.transaction { transaction in
transaction.increment("counter") // INCR counter
transaction.set("last_update", to: Date().timeIntervalSince1970)
}
Обработка ошибок и переподключение
RediStack автоматически обрабатывает временные ошибки и переподключается к серверу:
// Настройка стратегии повторных попыток
let config = RedisConnectionPool.ConnectionPoolConfiguration(
initialServerConnectionAddresses: [try .init(hostname: "redis.example.com", port: 6379)],
maximumConnectionCount: .maximumActiveConnections(10),
retryStrategy: .exponentialBackoff(maxDelay: .seconds(30)),
connectionBackoffFactor: 2
)
// Обработка ошиб