Mac 本地搭建 Redis 指南
Mac 本地搭建 Redis 指南
一、安装 Redis
方式一:Homebrew 安装(推荐)
# 安装
brew install redis
# 验证安装
redis-server --version
方式二:Docker 安装
docker run -d --name redis -p 6379:6379 redis:latest
方式三:源码编译
curl -O http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make install
二、启动与停止
# 前台启动
redis-server
# 后台服务方式启动(开机自启)
brew services start redis
# 停止服务
brew services stop redis
# 重启服务
brew services restart redis
# 查看服务状态
brew services info redis
三、验证连接
# 连接本地 Redis
redis-cli
# 测试连通性
redis-cli ping
# 返回 PONG 表示正常
四、项目配置
测试脚本和本项目均通过环境变量读取 Redis 配置,在 .env 文件中添加或通过命令行导出:
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=
REDIS_TIMEOUT=5
如果本地 Redis 未设置密码,
REDIS_PASSWORD留空即可。
五、常用 redis-cli 命令
| 命令 | 说明 |
|---|---|
redis-cli |
连接本地 Redis |
redis-cli -h <host> -p <port> |
连接指定地址 |
redis-cli -a <password> |
带密码连接 |
redis-cli info |
查看 Redis 信息 |
redis-cli dbsize |
查看当前库 key 数量 |
redis-cli flushdb |
清空当前库 |
redis-cli shutdown |
关闭 Redis 服务 |
六、常用配置修改
Homebrew 安装的配置文件路径:
- Apple Silicon:
/opt/homebrew/etc/redis.conf - Intel Mac:
/usr/local/etc/redis.conf
常见修改项:
# 设置密码
requirepass your_password
# 允许远程访问(默认只允许本地)
bind 0.0.0.0
# 修改端口
port 6379
# 设置最大内存
maxmemory 256mb
# 内存淘汰策略
maxmemory-policy allkeys-lru
修改后重启 Redis 生效:
brew services restart redis
七、运行测试程序
测试脚本为独立文件,不依赖本项目代码,唯一依赖:
pip install redis
确保 Redis 已启动后,直接运行:
python examples/test_local_redis.py
也可通过环境变量指定连接参数(默认连接 127.0.0.1:6379,无密码):
REDIS_HOST=127.0.0.1 REDIS_PORT=6379 python examples/test_local_redis.py
该脚本会依次测试连接、字符串读写、哈希、列表、集合、过期机制、Keys 模式匹配,最终输出通过/失败汇总。
点击查看代码
"""
本地 Redis 连接独立测试程序(无项目依赖)
仅依赖第三方库:redis (>=4.2,含 redis.asyncio)
安装:pip install redis
使用方式:
1. 确保本地 Redis 已启动: redis-cli ping
2. 直接运行: python test_local_redis.py
3. 可通过环境变量覆盖默认配置:
REDIS_HOST / REDIS_PORT / REDIS_DB / REDIS_PASSWORD / REDIS_TIMEOUT
"""
import os
import asyncio
import redis.asyncio as aioredis
# ───────── 配置(可通过环境变量覆盖)─────────
REDIS_HOST = os.getenv("REDIS_HOST", "127.0.0.1")
REDIS_PORT = int(os.getenv("REDIS_PORT", "6379"))
REDIS_DB = int(os.getenv("REDIS_DB", "0"))
REDIS_PASSWORD = os.getenv("REDIS_PASSWORD") or None
REDIS_TIMEOUT = int(os.getenv("REDIS_TIMEOUT", "5"))
# ───────── 测试统计 ─────────
passed = 0
failed = 0
def report(name: str, ok: bool, detail: str = ""):
"""打印一条测试结果"""
global passed, failed
status = "PASS" if ok else "FAIL"
if ok:
passed += 1
else:
failed += 1
msg = f" [{status}] {name}"
if detail:
msg += f" ({detail})"
print(msg)
# ───────── 连接管理 ─────────
async def create_client() -> aioredis.Redis:
"""创建一个本地 Redis 异步客户端"""
pool = aioredis.ConnectionPool(
host=REDIS_HOST,
port=REDIS_PORT,
db=REDIS_DB,
password=REDIS_PASSWORD,
decode_responses=True,
socket_timeout=REDIS_TIMEOUT,
socket_connect_timeout=REDIS_TIMEOUT,
max_connections=10,
)
return aioredis.Redis(connection_pool=pool)
# ───────── 测试用例 ─────────
async def test_connection(client: aioredis.Redis) -> bool:
"""测试 1:连接与 Ping"""
print("\n--- 测试 1:连接与 Ping ---")
try:
pong = await client.ping()
report("Redis 连接", bool(pong), f"{REDIS_HOST}:{REDIS_PORT}")
return bool(pong)
except Exception as e:
report("Redis 连接", False, str(e))
return False
async def test_string_ops(client: aioredis.Redis):
"""测试 2:字符串读写"""
print("\n--- 测试 2:字符串读写 ---")
key = "test:string:hello"
try:
ok = await client.set(key, "world", ex=60)
report("SET", bool(ok))
val = await client.get(key)
report("GET", val == "world", f"value={val}")
exists = await client.exists(key)
report("EXISTS", exists > 0)
await client.delete(key)
exists_after = await client.exists(key)
report("DELETE", exists_after == 0)
except Exception as e:
report("字符串操作", False, str(e))
async def test_hash_ops(client: aioredis.Redis):
"""测试 3:哈希操作"""
print("\n--- 测试 3:哈希操作 ---")
key = "test:hash:user"
try:
await client.hset(key, "name", "test_user")
await client.hset(key, "role", "developer")
await client.expire(key, 60)
name = await client.hget(key, "name")
report("HSET / HGET", name == "test_user", f"name={name}")
all_fields = await client.hgetall(key)
report("HGETALL", len(all_fields) == 2, f"fields={all_fields}")
await client.delete(key)
except Exception as e:
report("哈希操作", False, str(e))
async def test_list_ops(client: aioredis.Redis):
"""测试 4:列表操作"""
print("\n--- 测试 4:列表操作 ---")
key = "test:list:queue"
try:
await client.delete(key)
await client.lpush(key, "a", "b", "c")
await client.expire(key, 60)
val = await client.rpop(key)
report("LPUSH / RPOP", val == "a", f"popped={val}")
await client.delete(key)
except Exception as e:
report("列表操作", False, str(e))
async def test_set_ops(client: aioredis.Redis):
"""测试 5:集合操作"""
print("\n--- 测试 5:集合操作 ---")
key = "test:set:tags"
try:
await client.delete(key)
await client.sadd(key, "python", "redis", "mac")
await client.expire(key, 60)
members = await client.smembers(key)
report("SADD / SMEMBERS", len(members) == 3, f"members={members}")
await client.srem(key, "mac")
members2 = await client.smembers(key)
report("SREM", len(members2) == 2, f"after_remove={members2}")
await client.delete(key)
except Exception as e:
report("集合操作", False, str(e))
async def test_expire(client: aioredis.Redis):
"""测试 6:过期机制"""
print("\n--- 测试 6:过期机制 ---")
key = "test:expire:tmp"
try:
await client.set(key, "will_expire", ex=2)
val1 = await client.get(key)
report("写入带过期的 key", val1 == "will_expire")
print(" 等待 3 秒让 key 过期...")
await asyncio.sleep(3)
val2 = await client.get(key)
report("过期后 GET 为空", val2 is None, f"value={val2}")
except Exception as e:
report("过期机制", False, str(e))
async def test_keys_pattern(client: aioredis.Redis):
"""测试 7:Keys 模式匹配"""
print("\n--- 测试 7:Keys 模式匹配 ---")
try:
await client.set("test:pattern:a", "1", ex=60)
await client.set("test:pattern:b", "2", ex=60)
keys = await client.keys("test:pattern:*")
report("KEYS 模式匹配", len(keys) >= 2, f"found={len(keys)} keys")
await client.delete("test:pattern:a", "test:pattern:b")
except Exception as e:
report("Keys 模式匹配", False, str(e))
# ───────── 主入口 ─────────
async def main():
print("=" * 50)
print(" Mac 本地 Redis 连接测试(独立版)")
print("=" * 50)
print(f"\n目标地址: {REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}")
print(f"密码: {'(已设置)' if REDIS_PASSWORD else '(无密码)'}")
client = await create_client()
try:
connected = await test_connection(client)
if not connected:
print("\n连接失败,终止后续测试。请检查:")
print(" 1. Redis 是否已启动: redis-cli ping")
print(" 2. 主机/端口/密码是否正确(可通过 REDIS_HOST 等环境变量覆盖)")
return
await test_string_ops(client)
await test_hash_ops(client)
await test_list_ops(client)
await test_set_ops(client)
await test_expire(client)
await test_keys_pattern(client)
finally:
try:
await client.aclose()
except Exception:
pass
# 汇总
print("\n" + "=" * 50)
total = passed + failed
print(f" 测试结果: {passed}/{total} 通过, {failed} 失败")
if failed == 0:
print(" 本地 Redis 一切正常!")
else:
print(" 存在失败项,请检查日志排查问题。")
print("=" * 50)
if __name__ == "__main__":
asyncio.run(main())
执行 python examples/test_local_redis.py 效果如下:
==================================================
Mac 本地 Redis 连接测试(独立版)
==================================================
目标地址: 127.0.0.1:6379/0
密码: (无密码)
--- 测试 1:连接与 Ping ---
[PASS] Redis 连接 (127.0.0.1:6379)
--- 测试 2:字符串读写 ---
[PASS] SET
[PASS] GET (value=world)
[PASS] EXISTS
[PASS] DELETE
--- 测试 3:哈希操作 ---
[PASS] HSET / HGET (name=test_user)
[PASS] HGETALL (fields={'name': 'test_user', 'role': 'developer'})
--- 测试 4:列表操作 ---
[PASS] LPUSH / RPOP (popped=a)
--- 测试 5:集合操作 ---
[PASS] SADD / SMEMBERS (members={'redis', 'python', 'mac'})
[PASS] SREM (after_remove={'redis', 'python'})
--- 测试 6:过期机制 ---
[PASS] 写入带过期的 key
等待 3 秒让 key 过期...
[PASS] 过期后 GET 为空 (value=None)
--- 测试 7:Keys 模式匹配 ---
[PASS] KEYS 模式匹配 (found=2 keys)
==================================================
测试结果: 13/13 通过, 0 失败
本地 Redis 一切正常!
==================================================
浙公网安备 33010602011771号