Redis从入门到精通(13):python3操作redis实例详解

Redis很少有直接通过客户端去操作的,更多的是被程序的业务代码调用。这一节我们就以python3为例,演示一下对Redis的常规操作,最后简单实现下前面提到的视频网站限制用户观看视频数量的案例。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

环境准备

下面是我用来演示的环境:

  • 可被外界访问的Redis实例
  • Pycharm进行python代码编辑
  • Python3进行python代码解析
  • python环境和Redis实例之间网络通,Redis端口可正常访问

Redis实例可以直接按照前面的《Redis从入门到精通(1):centos7安装和启动redis》来启动;pycharm和python3环境可以按照另一篇博客《windows10安装anaconda 3和pycharm及常规使用详解》来安装和配置。

常规操作

连接Redis实例

首先需要安装两个第三方包:redis和redis-py,单单安装redis包无法连接。我安装的版本分别是:

  • redis - 3.2.100
  • redis-py - 3.4.1

之后就可以连接Redis实例了

import redis
r=redis.Redis(host='10.18.97.115',port=6379,db=0,password='xiaofu')

数据操作

虽说python对原来的Redis客户端命令都经过了封装,但是封装以后的命令和参数顺序和原先基本没有差别。下面对前面提到的五种类型的数据分别做简单的演示,为了清晰表示输入输出关系,下面的操作在ipython环境中完成。

  • string类型操作

赋值和取值操作:

In [11]: r.set('age',1)
Out[11]: True

In [12]: r.get('age')
Out[12]: b'1'

注意python3中所有返回的数据都是bytes类型,想要变为string类型用作后续处理,还需要经过decode操作,省略参数默认用utf-8解码。

In [13]: result=r.get('age')

In [14]: type(result)
Out[14]: bytes

In [15]: new_result=result.decode()

In [16]: type('new_result')
Out[16]: str

计数器操作:

In [18]: r.incrby('age',3)
Out[18]: 4

In [19]: r.incr('age')
Out[19]: 5

In [20]: r.decr('age',2)
Out[20]: 3

过期操作:

In [22]: r.setex('hobby',10,'basketball')
Out[22]: True

In [23]: r.ttl('hobby')
Out[23]: 3

In [24]: r.get('hobby')

In [25]: r.exists('hobby')
Out[25]: 0
  • hash操作

赋值和取值操作:
如果是批量操作,第二个参数是python的字典类型

In [28]: r.hmset('info',{'name':'xiaofu','age':100,'hobby':'basketball'})
Out[28]: True

In [31]: r.hset('info','location','SG')
Out[31]: 1

In [32]: r.hgetall('info')
Out[32]:
{b'name': b'xiaofu',
 b'age': b'100',
 b'hobby': b'basketball',
 b'location': b'SG'}

删除和计数操作:

In [34]: r.hincrby('info','age',-50)
Out[34]: 50

In [35]: r.hdel('info','location')
Out[35]: 1

In [36]: r.hgetall('info')
Out[36]: {b'name': b'xiaofu', b'age': b'50', b'hobby': b'basketball'}
  • list操作

赋值和取值操作:

In [40]: r.rpush('players','yaoming','james','davis','xiaofu')
Out[40]: 4

In [43]: r.lrange('players',0,-1)
Out[43]: [b'yaoming', b'james', b'davis', b'xiaofu']

In [44]: r.lpop('players')
Out[44]: b'yaoming'

In [45]: r.lrange('players',0,-1)
Out[45]: [b'james', b'davis', b'xiaofu']

In [47]: r.lindex('players',-1)
Out[47]: b'xiaofu'
  • set操作

赋值和取值操作:

In [49]: r.sadd('set1','a','b','c','d')
Out[49]: 4

In [50]: r.smembers('set1')
Out[50]: {b'a', b'b', b'c', b'd'}

In [51]: r.spop('set1')
Out[51]: b'd'

In [52]: r.scard('set1')
Out[52]: 3

In [53]: r.smembers('set1')
Out[53]: {b'a', b'b', b'c'}

集合操作:

In [55]: r.sadd('set2','b','c','d','e')
Out[55]: 4

In [56]: r.sinter('set1','set2')
Out[56]: {b'b', b'c'}

In [57]: r.sdiff('set1','set2')
Out[57]: {b'a'}

In [58]: r.sunion('set1','set2')
Out[58]: {b'a', b'b', b'c', b'd', b'e'}
  • sorted set操作

赋值和取值操作:

In [60]: r.zadd('score',{'xiaofu':100,'james':80,'davis':60})
Out[60]: 3

In [61]: r.zrange('score',0,-1,withscores=True)
Out[61]: [(b'davis', 60.0), (b'james', 80.0), (b'xiaofu', 100.0)]

In [62]: r.zrevrange('score',0,-1,withscores=True)
Out[62]: [(b'xiaofu', 100.0), (b'james', 80.0), (b'davis', 60.0)]

score操作:

In [63]: r.zrangebyscore('score',80,100,withscores=True)
Out[63]: [(b'james', 80.0), (b'xiaofu', 100.0)]

In [64]: r.zremrangebyrank('score',0,1)
Out[64]: 2

In [65]: r.zrange('score',0,-1,withscores=True)
Out[65]: [(b'xiaofu', 100.0)]

实际案例

模拟视频网站限制普通用户单日只能观看10个视频的场景。这里稍微简化一下,限制60秒内只能观看10个视频,操作次数提醒用户升级为VIP。且用户每隔1-5秒尝试观看一次视频,观看视频的行为用打印来简单代替。

先展示下最后效果:

You are watching video number 1. [refresh after 60 seconds]
You are watching video number 2. [refresh after 58 seconds]
You are watching video number 3. [refresh after 56 seconds]
You are watching video number 4. [refresh after 53 seconds]
You are watching video number 5. [refresh after 49 seconds]
You are watching video number 6. [refresh after 45 seconds]
You are watching video number 7. [refresh after 42 seconds]
You are watching video number 8. [refresh after 41 seconds]
You are watching video number 9. [refresh after 39 seconds]
You are watching video number 10. [refresh after 34 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 30 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 28 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 25 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 24 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 19 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 15 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 11 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 10 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 8 seconds]
You have watched 10 videos, please upgrade to VIP. [refresh after 2 seconds]
You are watching video number 1. [refresh after 60 seconds]
You are watching video number 2. [refresh after 59 seconds]

思路:以userid做为key创建一个计数器,过期时间为60秒。每观看一次视频加1,一直到10为止,不再增加,直到过期。

这里最主要是就是更新redis的操作,需要判断key是否存在,以及是否到10。创建一个函数,带入两个参数,分别是redis实例和userid,分三种情况来处理,返回一个tuple,两个元素分别为观看了的次数和剩余过期时间。如下:

def update_redis(r,userid):
    ttl = r.ttl(userid)
    if r.exists(userid) and r.get(userid).decode() == '10':  # remember to decode to string
        return (11,ttl)
    elif not r.exists(userid):
        r.setex(userid,60,1)
        return (1,60)  # can not use ttl here, will return -2
    else:
        watched_videos = r.incr(userid)  # this will return integer
        return (watched_videos,ttl)

然后针对用户观看视频的动作,用简单的打印来代替。首先更新下redis,根据返回的结果来决定用户是否能继续观看。如下:

def watch_video(r,userid):
    result=update_redis(r,userid)
    if result[0] == 11:
        print('You have watched 10 videos, please upgrade to VIP. [refresh after {} seconds]'.format(result[1]))
    else:
        print('You are watching video number {}. [refresh after {} seconds]'.format(result[0],result[1]))

完整的代码如下,利用暂停随机数来模拟用户的观看行为

#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
demo of non-VIP user limited to watch 10 videos within 100 seconds.

T型人小付 @ CSDN
"""


import redis
import random
import time


def conn_redis(address,port,password,db):
    r = redis.Redis(host=address, port=port, db=db, password=password)
    return r


def update_redis(r,userid):
    ttl = r.ttl(userid)
    if r.exists(userid) and r.get(userid).decode() == '10':  # remember to decode to string
        return (11,ttl)
    elif not r.exists(userid):
        r.setex(userid,60,1)
        return (1,60)  # can not use ttl here, will return -2
    else:
        watched_videos = r.incr(userid)  # this will return integer
        return (watched_videos,ttl)


def watch_video(r,userid):
    result=update_redis(r,userid)
    if result[0] == 11:
        print('You have watched 10 videos, please upgrade to VIP. [refresh after {} seconds]'.format(result[1]))
    else:
        print('You are watching video number {}. [refresh after {} seconds]'.format(result[0],result[1]))


if __name__ == '__main__':
    r=conn_redis('10.18.97.115',6379,'xiaofu',0)
    while True:
        watch_video(r,'userid:01')
        time.sleep(random.randint(1,5))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值