欢迎光临
我们一直在努力

04-redis进阶特性

第四章:Redis进阶特性

4.1 事务机制

事务特点

  • 保证原子性:事务中的命令要么全部执行,要么全部不执行
  • 不支持回滚:Redis事务不支持回滚操作
  • 隔离性:事务执行过程中不会被其他命令打断

基本命令

# 开启事务
MULTI

# 执行命令
SET key1 value1
SET key2 value2

# 提交事务
EXEC

# 取消事务
DISCARD

# 监视键
WATCH key

# 取消监视
UNWATCH

事务示例

1. 简单事务

# 开启事务
MULTI
OK

# 执行命令
SET key1 value1
QUEUED
SET key2 value2
QUEUED

# 提交事务
EXEC
1) OK
2) OK

2. 事务取消

# 开启事务
MULTI
OK

# 执行命令
SET key1 value1
QUEUED
SET key2 value2
QUEUED

# 取消事务
DISCARD
OK

3. WATCH机制

# 监视键
WATCH balance:1001
OK

# 开启事务
MULTI
OK

# 执行命令
DECRBY balance:1001 100
INCRBY balance:1002 100
QUEUED
QUEUED

# 提交事务(如果balance:1001未被修改)
EXEC
1) (integer) 900
2) (integer) 1100

# 如果balance:1001被其他客户端修改,事务会失败
EXEC
(nil)

事务应用场景

1. 转账

# 开启事务
MULTI

# 扣款
DECRBY balance:1001 100

# 收款
INCRBY balance:1002 100

# 提交事务
EXEC

2. 库存扣减

# 监视库存
WATCH product:1001:stock

# 检查库存
GET product:1001:stock

# 开启事务
MULTI

# 扣减库存
DECRBY product:1001:stock 1

# 提交事务
EXEC

4.2 发布订阅

发布订阅特点

  • 消息广播
  • 多个订阅者可以订阅同一个频道
  • 发布者不需要知道订阅者

基本命令

# 订阅频道
SUBSCRIBE channel1 channel2 ...

# 取消订阅
UNSUBSCRIBE [channel1 channel2 ...]

# 发布消息
PUBLISH channel message

# 按模式订阅
PSUBSCRIBE pattern1 pattern2 ...

# 按模式取消订阅
PUNSUBSCRIBE [pattern1 pattern2 ...]

发布订阅示例

1. 简单订阅

# 订阅者1
SUBSCRIBE channel:news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel:news"
3) (integer) 1

# 订阅者2
SUBSCRIBE channel:news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel:news"
3) (integer) 1

# 发布者
PUBLISH channel:news "今日头条:Redis 7.0发布"
(integer) 2

# 订阅者1和订阅者2都会收到消息
1) "message"
2) "channel:news"
3) "今日头条:Redis 7.0发布"

2. 模式订阅

# 订阅者
PSUBSCRIBE channel:*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel:*"
3) (integer) 1

# 发布者
PUBLISH channel:news "新闻"
PUBLISH channel:sports "体育"

# 订阅者会收到所有匹配的消息
1) "pmessage"
2) "channel:*"
3) "channel:news"
4) "新闻"

1) "pmessage"
2) "channel:*"
3) "channel:sports"
4) "体育"

发布订阅应用场景

1. 消息通知

# 订阅用户通知
SUBSCRIBE user:1001:notifications

# 发送通知
PUBLISH user:1001:notifications "您有新消息"
PUBLISH user:1001:notifications "您的订单已发货"

2. 系统广播

# 订阅系统消息
SUBSCRIBE system:announcements

# 发送系统公告
PUBLISH system:announcements "系统将于今晚22:00进行维护"

3. 实时聊天

# 订阅聊天室
SUBSCRIBE chat:room:1001

# 发送消息
PUBLISH chat:room:1001 "user1:大家好"

4.3 Lua脚本

Lua脚本特点

  • 原子性执行
  • 支持复杂逻辑
  • 减少网络开销
  • 复用脚本

基本命令

# 执行Lua脚本
EVAL script numkeys key1 key2 ... arg1 arg2 ...

# 计算脚本SHA1
SCRIPT LOAD script

# 执行缓存的脚本
EVALSHA sha1 numkeys key1 key2 ... arg1 arg2 ...

# 杀死正在执行的脚本
SCRIPT KILL

# 清空脚本缓存
SCRIPT FLUSH

# 查看脚本缓存
SCRIPT EXISTS sha1 sha2 ...

Lua脚本示例

1. 简单脚本

# 执行简单脚本
EVAL "return 'Hello Redis'" 0
"Hello Redis"

# 使用KEYS和ARGV
EVAL "return KEYS[1] .. ' ' .. ARGV[1]" 1 key1 value1
"key1 value1"

2. 复杂脚本

# 批量设置键值
EVAL "
for i=1,#KEYS do
redis.call('SET', KEYS[i], ARGV[i])
end
return #KEYS
"
3 key1 key2 key3 value1 value2 value3
(integer) 3

3. 条件操作

# 仅当key不存在时设置值
EVAL "
if redis.call('EXISTS', KEYS[1]) == 0 then
return redis.call('SET', KEYS[1], ARGV[1])
else
return 0
end
"
1 key1 value1

Lua脚本应用场景

1. 原子性操作

— 原子性转账
local from = KEYS[1]
local to = KEYS[2]
local amount = tonumber(ARGV[1])

local balance = tonumber(redis.call('GET', from))
if balance < amount then
return 0
end

redis.call('DECRBY', from, amount)
redis.call('INCRBY', to, amount)
return 1

2. 限流

— 限流脚本
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local expire = tonumber(ARGV[2])

local current = tonumber(redis.call('GET', key) or '0')
if current + 1 > limit then
return 0
else
redis.call('INCR', key)
if current == 0 then
redis.call('EXPIRE', key, expire)
end
return 1
end

3. 分布式锁

— 获取锁
local key = KEYS[1]
local value = ARGV[1]
local expire = tonumber(ARGV[2])

if redis.call('SETNX', key, value) == 1 then
redis.call('EXPIRE', key, expire)
return 1
else
return 0
end

— 释放锁
local key = KEYS[1]
local value = ARGV[1]

if redis.call('GET', key) == value then
return redis.call('DEL', key)
else
return 0
end

4.4 管道技术

管道技术特点

  • 批量执行命令
  • 减少网络往返
  • 提高性能
  • 不保证原子性

管道使用示例

1. 命令行使用

# 使用管道执行多个命令
(ECHO "SET key1 value1"; ECHO "SET key2 value2"; ECHO "GET key1") | redis-cli –pipe

2. Python示例

import redis

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

# 使用管道
pipe = r.pipeline()

# 批量执行命令
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.get('key1')

# 执行所有命令
results = pipe.execute()
print(results) # [True, True, b'value1']

3. 事务管道

import redis

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

# 使用事务管道
pipe = r.pipeline(transaction=True)

# 批量执行命令
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.get('key1')

# 执行所有命令
results = pipe.execute()
print(results) # [True, True, b'value1']

管道应用场景

1. 批量插入

import redis

r = redis.Redis(host='localhost', port=6379)

# 批量插入数据
pipe = r.pipeline()
for i in range(1000):
pipe.set(f'key:{i}', f'value:{i}')
pipe.execute()

2. 批量查询

import redis

r = redis.Redis(host='localhost', port=6379)

# 批量查询数据
pipe = r.pipeline()
for i in range(1000):
pipe.get(f'key:{i}')
results = pipe.execute()

4.5 慢查询日志

慢查询配置

# 慢查询阈值(微秒)
slowlog-log-slower-than 10000

# 慢查询日志最大长度
slowlog-max-len 128

慢查询命令

# 获取慢查询日志
SLOWLOG GET [n]

# 获取慢查询日志长度
SLOWLOG LEN

# 清空慢查询日志
SLOWLOG RESET

慢查询示例

# 查看慢查询
SLOWLOG GET 10

1) 1) (integer) 1
2) (integer) 15000
3) (integer) 1600000000
4) "GET user:1001"

# 解释:
# 1) 日志ID
# 2) 执行时间(微秒)
# 3) 时间戳
# 4) 执行的命令

慢查询分析

# 查看慢查询日志长度
SLOWLOG LEN
(integer) 10

# 清空慢查询日志
SLOWLOG RESET
OK

4.6 Redis模块

常用Redis模块

1. RedisJSON

# 安装RedisJSON
# https://oss.redislabs.com/redisjson/

# 设置JSON值
JSON.SET user:1001 $ '{"name":"张三","age":25}'

# 获取JSON值
JSON.GET user:1001

# 获取JSON字段
JSON.GET user:1001 $.name

# 更新JSON字段
JSON.SET user:1001 $.age 26

2. RedisSearch

# 安装RedisSearch
# https://oss.redislabs.com/redisearch/

# 创建索引
FT.CREATE user:idx ON JSON PREFIX 1 user: SCHEMA $.name AS name TEXT $.age AS age NUMERIC

# 搜索
FT.SEARCH user:idx "@name:(张三)"

# 聚合
FT.AGGREGATE user:idx "*" GROUPBY 0 REDUCE COUNT 0 AS total

3. RedisTimeSeries

# 安装RedisTimeSeries
# https://oss.redislabs.com/redistimeseries/

# 创建时间序列
TS.CREATE temperature:room1 RETENTION 0 LABELS room room1

# 添加数据点
TS.ADD temperature:room1 1600000000 25

# 查询数据
TS.RANGE temperature:room1 – + WITHLABELS

# 聚合查询
TS.MRANGE – + WITHLABELS AGGREGATION avg 60000 FILTER room=room1

赞(0)
未经允许不得转载:171主机测评 » 04-redis进阶特性
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址