Redis
本文最后更新于264 天前,其中的信息可能已经过时,如有错误请发送邮件到2067863254@qq.com

定义:redis是一个在内存中存储数据的中间件,用作缓存/支持分布式系统并具备良好的扩展性

数据结构:支持字符串/哈希/列表/集合/有序集合/流

对比mysql,mysql是通过表去进行存储的,是关系型数据库,redis是通过键值对去存储数据的(非关系型存储数据);键值对:key通常是字符串(string),value可以是上述各种结构

主打特点就是快

redis的特性(优点)ipep:

内存数据结构:数据主要存储在内存呢中,可以提供高速访问

可编程性:支持服务端脚本,特别是使用lua语言,除了交互式命令行操作,还可以通过lua脚本批量执行操作

可扩展性:提供api,允许开发者编写自定义扩展,扩展本质是动态链接库

持久化:默认数据存储在内存中,但支持数据持久化到磁盘,目的是避免防止进程退出或者是系统重启导致数据丢失,机制:通过aof(日志)以及rdb(快照)进行持久化

集群:支持分布式集群部署,通过哈希分片将数据分布在多个节点上

高可用性:支持主从复制,通过配置多个从节点去备份主节点数据

实时数据存储:把redis当作数据库,在大多数情况下,考虑数据持久化情况,优先考虑rdb,因为快

缓存:使用mysql+缓存(redis),采用二八原则,把热点数据存出来,存储在redis中,redis存的都是热数据,全量数据可以以mysql为主的存储,即使redis数据丢失了,也可以从mysql中恢复过来

消息队列:

session存储:

为什么redis快:

数据存储/操作逻辑/io模型/线程模型

1. 基础键值操作

import redis

# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)

# 设置键值对
r.set('name', 'Alice')  # 设置 name = Alice
r.set('age', 25)        # 设置 age = 25

# 获取值
print(r.get('name'))    # 输出: b'Alice' (b表示bytes类型)
print(r.get('age'))     # 输出: b'25'

# 设置过期时间(秒)
r.setex('temp_session', 30, 'session_data')  # 30秒后自动删除

# 检查键是否存在
print(r.exists('name'))  # 输出: 1 (存在)
print(r.exists('nonexistent'))  # 输出: 0 (不存在)

# 删除键
r.delete('age')
print(r.get('age'))      # 输出: None

2. 哈希(Hash)类型 – 适合存储对象

# 存储用户信息
r.hset('user:1001', 'name', 'Bob')
r.hset('user:1001', 'email', 'bob@example.com')
r.hset('user:1001', 'age', 30)

# 获取单个字段
print(r.hget('user:1001', 'name'))  # 输出: b'Bob'

# 获取所有字段
print(r.hgetall('user:1001'))  
# 输出: {b'name': b'Bob', b'email': b'bob@example.com', b'age': b'30'}

# 增加数字字段
r.hincrby('user:1001', 'age', 1)  # age增加1
print(r.hget('user:1001', 'age'))  # 输出: b'31'

3. 列表(List)类型 – 实现队列和栈

# 添加消息到队列
r.lpush('message_queue', 'msg1')
r.lpush('message_queue', 'msg2')
r.lpush('message_queue', 'msg3')

# 获取队列长度
print(r.llen('message_queue'))  # 输出: 3

# 从队列右侧取出消息(先进先出)
print(r.rpop('message_queue'))  # 输出: b'msg1' (最早的消息)
print(r.rpop('message_queue'))  # 输出: b'msg2'

# 作为栈使用(后进先出)
r.lpush('stack', 'item1')
r.lpush('stack', 'item2')
print(r.lpop('stack'))  # 输出: b'item2' (最后放入的先出)

4. 集合(Set)类型 – 去重和集合运算

# 添加元素到集合
r.sadd('tags', 'python', 'redis', 'database')
r.sadd('tags', 'python')  # 重复元素不会被添加

# 获取集合所有成员
print(r.smembers('tags'))  # 输出: {b'python', b'redis', b'database'}

# 集合运算
r.sadd('tags2', 'python', 'java', 'javascript')

# 交集
print(r.sinter('tags', 'tags2'))  # 输出: {b'python'}

# 并集
print(r.sunion('tags', 'tags2'))  # 输出: {b'python', b'redis', b'database', b'java', b'javascript'}

5. 有序集合(Sorted Set) – 排行榜实现

# 添加分数和成员
r.zadd('leaderboard', {'Alice': 100, 'Bob': 85, 'Charlie': 120})

# 获取成员排名(从高到低)
print(r.zrevrank('leaderboard', 'Alice'))  # 输出: 1 (第二名)

# 获取前3名
print(r.zrevrange('leaderboard', 0, 2, withscores=True))
# 输出: [(b'Charlie', 120.0), (b'Alice', 100.0), (b'Bob', 85.0)]

# 增加分数
r.zincrby('leaderboard', 20, 'Bob')  # Bob增加20分
print(r.zscore('leaderboard', 'Bob'))  # 输出: 105.0

6. 发布/订阅模式

import threading

# 订阅者
def subscriber():
    pubsub = r.pubsub()
    pubsub.subscribe('news')
    for message in pubsub.listen():
        if message['type'] == 'message':
            print(f"收到消息: {message['data'].decode('utf-8')}")

# 启动订阅线程
thread = threading.Thread(target=subscriber)
thread.start()

# 发布者
r.publish('news', '第一条消息')
r.publish('news', '第二条消息')

7. 实际应用示例 – 缓存网页内容

import requests

def get_page(url):
    # 检查缓存
    cache_key = f"page:{url}"
    cached_content = r.get(cache_key)
    
    if cached_content:
        print("从缓存获取")
        return cached_content.decode('utf-8')
    
    # 缓存中没有,从网络获取
    print("从网络获取")
    response = requests.get(url)
    content = response.text
    
    # 缓存1小时
    r.setex(cache_key, 3600, content)
    return content

# 使用示例
print(get_page('https://example.com'))
print(get_page('https://example.com'))  # 第二次会从缓存获取

8. 事务操作

# 开始事务
pipe = r.pipeline()

# 添加多个操作
pipe.set('counter', 0)
pipe.incr('counter')
pipe.incrby('counter', 4)

# 执行事务
pipe.execute()

# 获取结果
print(r.get('counter'))  # 输出: b'5'

9. Lua脚本示例 – 实现原子操作

# 实现原子性的"比较并设置"操作
lua_script = """
local current = redis.call('GET', KEYS[1])
if current == ARGV[1] then
    redis.call('SET', KEYS[1], ARGV[2])
    return 1
else
    return 0
end
"""

# 注册脚本
compare_set = r.register_script(lua_script)

# 使用脚本
r.set('status', 'active')
result = compare_set(keys=['status'], args=['active', 'inactive'])
print(result)  # 输出: 1 (修改成功)

10. 地理空间(Geo)操作 – 附近位置查询

# 添加地理位置
r.geoadd('stores', 
         (116.404, 39.915, 'store1'),  # 经度, 纬度, 名称
         (116.405, 39.916, 'store2'),
         (116.406, 39.917, 'store3'))

# 查询附近3公里内的商店
print(r.georadius('stores', 116.404, 39.915, 3, unit='km', withdist=True))
# 输出: [(b'store1', 0.0), (b'store2', 0.1419), (b'store3', 0.2838)]


Redis 基本全局命令详解

Redis 的全局命令是可以对所有数据类型使用的命令,下面我用通俗易懂的方式为你解释这些常用命令:

1. 键(Key)相关命令

KEYS pattern

  • 作用:查找所有符合给定模式的 key
  • 示例KEYS user:* (查找所有以”user:”开头的键)
  • 注意:生产环境慎用,数据量大时会阻塞服务器

EXISTS key

  • 作用:检查 key 是否存在
  • 示例EXISITS name (检查”name”键是否存在)
  • 返回:1(存在) 或 0(不存在)

DEL key [key ...]

  • 作用:删除一个或多个 key
  • 示例DEL name age (删除”name”和”age”两个键)
  • 返回:被删除 key 的数量

TYPE key

  • 作用:返回 key 所存储的值的类型
  • 示例TYPE user:1001
  • 可能返回:string, hash, list, set, zset 等

EXPIRE key seconds

  • 作用:为 key 设置过期时间(秒)
  • 示例EXPIRE temp_session 60 (60秒后自动删除)
  • 相关TTL key (查看剩余时间), PERSIST key (移除过期时间)

RENAME key newkey

  • 作用:重命名 key
  • 示例RENAME old_name new_name

2. 数据库相关命令

SELECT index

  • 作用:切换到指定的数据库(0-15)
  • 示例SELECT 1 (切换到1号数据库)

FLUSHDB

  • 作用:清空当前数据库
  • 注意:这个命令很危险,会删除当前数据库所有数据

FLUSHALL

  • 作用:清空所有数据库
  • 注意:极度危险,会删除Redis中所有数据

3. 服务器相关命令

DBSIZE

  • 作用:返回当前数据库的 key 数量
  • 示例DBSIZE (查看当前数据库有多少个key)

INFO [section]

  • 作用:获取 Redis 服务器的各种信息和统计数值
  • 示例INFO memory (查看内存相关信息)

CONFIG GET parameter

  • 作用:获取 Redis 配置参数
  • 示例CONFIG GET maxmemory (查看内存限制配置)

CONFIG SET parameter value

  • 作用:修改 Redis 配置(临时生效)
  • 示例CONFIG SET maxmemory 100mb (设置内存限制)

4. 连接相关命令

PING

  • 作用:测试连接是否正常
  • 返回PONG (表示连接正常)

ECHO message

  • 作用:打印给定的字符串
  • 示例ECHO "Hello Redis"

QUIT

  • 作用:关闭当前连接

5. 实用命令

RANDOMKEY

  • 作用:随机返回当前数据库的一个 key
  • 用途:可用于抽样检查数据

SCAN cursor [MATCH pattern] [COUNT count]

  • 作用:增量迭代数据库中的 key (比 KEYS 更安全)
  • 示例SCAN 0 MATCH user:* COUNT 10

MOVE key db

  • 作用:将当前数据库的 key 移动到另一个数据库
  • 示例MOVE temp_data 1 (移动到1号数据库)

通俗解释

可以把 Redis 想象成一个有很多抽屉(数据库)的大柜子,每个抽屉里放着各种盒子(key),盒子里装着不同类型的数据:

  1. 找东西KEYS 是打开抽屉大喊”谁的名字以A开头?”,SCAN 是慢慢翻找
  2. 检查盒子EXISTS 看盒子是否存在,TYPE 看盒子里装的是什么类型的东西
  3. 清理DEL 是扔掉盒子,EXPIRE 是设置定时自动扔掉
  4. 整理RENAME 是给盒子贴新标签,MOVE 是把盒子放到另一个抽屉
  5. 大扫除FLUSHDB 是清空一个抽屉,FLUSHALL 是把整个柜子清空

记住这些命令就像记住整理房间的工具,合理使用可以让你的 Redis “房间”保持整洁有序!

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇