当前位置: 首页 > news >正文

Redis基础

一、Redis操作

1.1 redis

下载redis:https://github.com/tporadowski/redis/releases
启动redeis:redis-server.exe redis.windows.conf
启动redis客户端:redis-cli
Redis默认端口6379
redis特性:

  • 速度快
  • 持久化
  • 多种数据结构
  • 支持多种编程语言
  • 主从复制
  • 高可用、分布式
    Redis提供的数据类型主要分为5种自有类型和一种自定义类型,这5种自有类型包括:String类型、哈希类型、列表类型、集合类型和顺序集合类型。
    redis={
    “name”:“yuan”,
    “age”:“23”,
    “scors”:[78,79,98,],
    “info”:{“gender”:“male”,“tel”:“110”},
    “set”:{1,2,3},
    “zset”:{1,2,3,}
    }
    Redis 的应用场景包括:
    缓存系统(“热点”数据:高频读、低频写):缓存用户信息,优惠券过期时间,验证码过期时间、session、token等

计数器:帖子的浏览数,视频播放次数,评论次数、点赞次数等

消息队列,秒杀系统

社交网络:粉丝、共同好友(可能认识的人),兴趣爱好(推荐商品)

排行榜(有序集合)

发布订阅:粉丝关注、消息通知

Setnx(分布式锁)不允许重复赋值
Setex设置有效期 setex key time value 查看剩余时间 ttl key
mset key1 value1 key2 value2 …
字符串拼接:set title “我的” append title “redis” append title “学习之路”
set id 1 incr id(自增) # 相当于id+1
decr goods_id_1 # 相当于 id-1

1.2 键操作

Keys * 查看所有key
del key删除键
exists key判断键是否存在
expire key 10(10秒过期)
在这里插入图片描述

1.3 Redis 操作列表:

lpush rpush llen names(获取列表长度)
创建列表:Rpush names zhangsan lisi wangwu
增:linsert names after “zhangsan” lihua
改:lset key index value(按索引修改列表值)
删:lpop key删除第一个 或者rpop key删除最后一个。lrem names 0 zhangsan(0全部删除,2删除前两个,-2删除后两个)
查: lrange names 0 -1 lrange(切片)

1.4 Redis 操作hash:

创建&修改hash: hset info name tom age 22
查:hget info name ,hgetall info(获取所有),hmget info name age(获取多个), hkeys info hvals info
删除:hdel info age hdel info
自增:hincrby info age 1

1.5 Redis 操作集合(无序):

增:sadd authors zhangsan lisi wangwu
查: smembers authors
删:spop authors(随机删) srem authors zhangsan
sinter交集 sdiff差集 sunion并集

1.6 Redis 操作有序集合:

增:zadd scores 61 xiaoming 62 xiaobai 78 xiaohei 87 xiaohui 99 xiaolan
查:zrangebyscore scores 70 100 zrevrangebyscore scores 100 70
Zrange scores 0 -1(递增) zrange scores -2 -1(递增) zrevrange scores 0 1(递减)
改:zincrby scores 10 xiaohui(加10)
删:zrem scores xiaohui zpopmin scores 2(删除前两个,从最低分开始删) zpopmax scores 2
获取长度:zcard scores 获取指定区间人数:zcount scores 70 100
获取指定成员的权重值Zscore scores xiaohui
获取指定成员在集合中的排名 zrank socres xiaohui zrevrank socres xiaohui(从大到小)

二 Python操作redis

2.1 Python实现对redis的连接

import redis
#方式一 直接创建链接
r=redis.Redis(host=‘127.0.0.1’,port=6379)
r.set(‘for’,‘bar’)
#方式二 使用连接池
pool = redis.ConnectionPool(host=‘127.0.0.1’, port=6379)
r = redis.Redis(connection_pool=pool)
r.set(‘bar’,‘foo’)
print(r.get(‘bar’))

2.2 Python实现对redis的数据类型操作

import redis
pool=redis.ConnectionPool(host='127.0.0.1',port='6379')
r=redis.Redis(connection_pool=pool)
# (1)字符串操作:不允许对已经存在的键设置值
ret = r.setnx("name", "yuan")
print(ret)  # 已存在返回False
# (2)字符串操作:设置键有效期
r.setex("good_1001", 10, "2") #10秒有效期
# (3)字符串操作:自增自减
r.set("age", 20)
r.incrby("age", 2)
print(r.get("age"))  # b'22'
# (4)hash操作:设置hash
r.hset("info", "name", "rain")
print(r.hget("info", "name"))  # b'rain'
r.hmset("info", {"gedner":"male", "age":23})
print(r.hgetall("info"))  # {b'name': b'rain', b'gender': b'male', b'age': b'23'}
# (5)list操作:设置list
r.rpush("scores", "100", "90", "80")
r.rpush("scores", "70")
r.lpush("scores", "120")
print(r.lrange("scores", 0, -1))  # ['120', '100', '90', '80', '70']
r.linsert("scores", "AFTER", "100", 95)
print(r.lrange("scores", 0, -1))  # ['120', '100', '95', '90', '80', '70']
print(r.lpop("scores"))  # 120
print(r.rpop("scores"))  # 70
print(r.lindex("scores", 1)) # '95'
# (6)集合操作
# key对应的集合中添加元素
r.sadd("name_set", "zhangsan", "lisi", "wangwu")
# 获取key对应的集合的所有成员
print(r.smembers("name_set"))  # {'lisi', 'zhangsan', 'wangwu'}
# 从key对应的集合中随机获取 numbers 个元素
print(r.srandmember("name_set", 2))
r.srem("name_set", "lisi")
print(r.smembers("name_set"))  # {'wangwu', 'zhangsan'}
# (7)有序集合操作
# 在key对应的有序集合中添加元素
r.zadd("jifenbang", {"yuan": 78, "rain": 20, "alvin": 89, "eric": 45})
# 按照索引范围获取key对应的有序集合的元素
# zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
print(r.zrange("jifenbang", 0, -1))  # ['rain', 'eric', 'yuan', 'alvin']
print(r.zrange("jifenbang", 0, -1, withscores=True))  # ['rain', 'eric', 'yuan', 'alvin']
print(r.zrevrange("jifenbang", 0, -1, withscores=True))  # ['rain', 'eric', 'yuan', 'alvin']

print(r.zrangebyscore("jifenbang", 0, 100))
print(r.zrangebyscore("jifenbang", 0, 100, start=0, num=1)) #这个范围内的从下标0开始,取一个

# 删除key对应的有序集合中值是values的成员
print(r.zrem("jifenbang", "yuan"))  # 删除成功返回1
print(r.zrange("jifenbang", 0, -1))  # ['rain', 'eric', 'alvin']
# (8)键操作
r.delete("scores")
print(r.exists("scores"))
print(r.keys("*"))
r.expire("name",10)

2.3 分布式锁

假设某电商网站的某商品做秒杀活动,key可以设置为key_resource_id,value设置任意值,伪代码如下:

方案1
import redis

pool = redis.ConnectionPool(host='127.0.0.1')
r = redis.Redis(connection_pool=pool)
ret = r.setnx("key_resource_id", "ok")
if ret:
    r.expire("key_resource_id", 5)  # 设置过期时间
    print("抢购成功!")
    r.delete("key_resource_id")  # 释放资源
else:
    print("抢购失败!")

但是这个方案中,setnxexpire两个命令分开了,「不是原子操作」。如果执行完setnx加锁,正要执行expire设置过期时间时,进程crash或者要重启维护了,那么这个锁就“长生不老”了,「别的线程永远获取不到锁啦」

方案三

在这里插入图片描述

2.4 延迟队列:

延时队列可以通过Redis的zset(有序列表)来实现。我们将消息序列化为一个字符串作为zset的值。这个消息的到期时间处理时间作为score,然后用多个线程轮询zset获取到期的任务进行处理,多线程时为了保障可用性,万一挂了一个线程还有其他线程可以继续处理。因为有多个线程,所有需要考虑并发争抢任务,确保任务不能被多次执行。

import time
import uuid

import redis

pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)


def delay_task(task_name, delay_time):
    # 保证value唯一
    task_id = task_name + str(uuid.uuid4())

    retry_ts = time.time() + delay_time
    r.zadd("delay-queue", {task_id: retry_ts})


def loop():
    print("循环监听中...")
    while True:
        # 最多取1条
        task_list = r.zrangebyscore("delay-queue", 0, time.time(), start=0, num=1)
        if not task_list:
            # 延时队列空的,休息1s
            print("cost 1秒钟")
            time.sleep(1)
            continue
        task_id = task_list[0]
        success = r.zrem("delay-queue", task_id)
        if success:
            # 处理消息逻辑函数
            handle_msg(task_id)
def handle_msg(msg):
    """消息处理逻辑"""
    print(f"消息{msg}已经被处理完成!")

import threading

t = threading.Thread(target=loop)
t.start()

delay_task("任务1延迟5", 5)
delay_task("任务2延迟2", 2)
delay_task("任务3延迟3", 3)
delay_task("任务4延迟10", 10)

2.5 发布订阅:

在这里插入图片描述

2.6 基于redis的发布订阅聊天室案例

import threading
import redis
r = redis.Redis(host='127.0.0.1')
def recv_msg():
    pub = r.pubsub()
    pub.subscribe("room_1001")
    pub.parse_response()
    while 1:
        res_msg = pub.parse_response()
        print(res_msg)

def send_msg():
    msg = input(">>>")
    r.publish("room_1001", msg)
t = threading.Thread(target=send_msg)
t.start()
recv_msg()

相关文章:

  • 字符串算法深入
  • 【python】OpenCV—Hough Circle Transform
  • 动态调试环境配置(Android Studio + IDA Pro)
  • 【Spring】Spring是如何解决循环依赖问题的
  • [C语言]内存函数的使用和模拟实现
  • 分类操作-01.新增分类
  • canal集群部署
  • 求出e的值(信息学奥赛一本通-1092)
  • ctfshow做题笔记—栈溢出—pwn69~pwn72
  • HybridCLR Generate All 报错UnityLinker.exe
  • Ubuntu-配置apt国内源
  • SpringBoot 实现接口数据脱敏
  • 【自学笔记】MoonBit语言基础知识点总览-持续更新
  • GOF设计模式在 Spring 框架中的核心应用分析
  • golang算法快慢指针
  • 19个判定学术写作内容有AI生成痕迹的例子
  • (Lauterbach调试器学习笔记)一、首次连接TriCore开发板调试
  • AutoGen学习笔记系列(十三)Advanced - Logging
  • 第75期 Doxygen是干嘛的,Windows版本,如何安装,学习
  • 函数题 01-复杂度3 二分查找【PAT】
  • 俄外长与美国务卿通电话,讨论俄美接触等问题
  • 杨建全已任天津市委副秘书长、市委市政府信访办主任
  • 美国务卿鲁比奥抵达会场,将参加俄乌会谈
  • 艺术稀缺性和价值坚守如何构筑品牌差异化壁垒?从“心邸”看CINDY CHAO的破局之道
  • 龚正市长调研闵行区,更加奋发有为地稳增长促转型,久久为功增强发展后劲
  • 俄方代表团抵达土耳其,俄乌直接谈判有望于当地时间上午重启