成都网站建设设计

将想法与焦点和您一起共享

python学习之redis编程

redis简介

Redis(Remote Dictionary Server)远程字典数据服务的缩写,由意大利
人开发的是一款内存高速缓存数据库。使用ANSI C语言编写、支持网络、可基于内
存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API并提供多种语言
的 API的非关系型数据库。
python学习之redis编程
Redis和Memcache对比?
python学习之redis编程

成都创新互联主营琼结网站建设的网络公司,主营网站建设方案,成都App制作,琼结h5微信小程序搭建,琼结网站营销推广欢迎琼结等地区企业咨询

Redis的安装

  1. 首先上官网下载Redis 压缩包,地址 http://redis.io/download
  2. 压缩包执行解压操作并进行编译
    #tar xzf redis-x.x.x.tar.gz
    #cd redis-x.x.x/
    #make && make install
    #sh utils/install_server.sh
    Redis的部署
  3. 执行Redis-server 命令,启动Redis 服务
    redis-server
  4. 客户端redisClient
    redis-cli
    #登录redis

    set 'a' '123'

  5. 当添加键值后,发现在当前运行的目录下,创建了一个文件:dump.rdb,这个文
    件用于将数据持久化存储
    python学习之redis编程

    Redis内置数据类型

    • string 类型 是二进制安全的。可以包含任何数据(eg: jpg 图片或者序列化的对象)。
    从内部实现来看其实 string 可以看作 byte 数组,最大上限是 1G 字节。
    • hash类型 是一个 string 类型的 field 和 value 的映射表.它的添加、删除操作都是
    O(1)(平均)。
    • list类型 是一个 string 类型的双向链表。最大长度是(2 32 )。
    • set 类型 是 string 类型的通过 hash table 实现的无序集合。添加、删除和查找的复
    杂度都是 O(1)。最大长度是(2 32 )。
    Redis内置指令: http://doc.redisfans.com/
    python学习之redis编程 python学习之redis编程
    Redis应用场景
    python学习之redis编程

    Redis持久化

    Redis 是一个内存数据库,与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘
    中相比,内存数据库的读写效率比传统数据库要快的多(内存的读写效率远远大于硬盘的读写
    效率)。但是保存在内存中也随之带来了一个缺点,一旦断电或者宕机,那么内存数据库中的
    数据将会全部丢失。
    目标: 持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
    Redis 提供了两种持久化方式:RDB(默认) 和AOF
    Redis持久化: RDB
    RDB是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入
    磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时是将快
    照文件直接读到内存里。
    python学习之redis编程

    Redis持久化: RDB

    我们可以配置 redis在 n 秒内如果超过 m 个 key 被修改就自动做快照,下面是默认的快照保
    存配置:
    dbfilename dump.rdb
    save 900 1
    save 300 10
    #持久化存储文件名为 dump.rdb
    #900 秒内如果超过 1 个 key 被修改,则发起快照保存
    #300 秒内容如超过 10 个 key 被修改,则发起快照保

    save 60 10000 # 600 秒内容如超过 10000 个 key 被修改,则发起快照保存
    Redis持久化: AOF
    • RDB 持久化存是一定时间内做一次备份,如果
    redis意外down掉的话,就会丢失最后一次快照后
    的所有修改(数据有丢失)。
    • 工作原理: 当 redis 重启时会通过重新执行文件中
    保存的写命令来在内存中重建整个数据库的内容。python学习之redis编程

    Redis持久化: AOF

    通过配置文件告诉 redis 我们想要通过 fsync 函数强制 os 写入到磁盘的时机。有三
    种方式如下(默认是:每秒 fsync 一次), 通过BGREWRITEAOF指令压缩/优化命令
    //启用 aof 持久化方式
    appendonly yes
    //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
    #appendfsync always
    //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
    appendfsync everysec
    //完全依赖 os,性能最好,持久化没保证
    #appendfsync no
    配置:修改redis配置文件
    vim /etc/redis/6379.conf
    appendonly yes #修改appendonly为yes
    cd /var/lib/redis/6379/ #进入目录生成aof文件
    ls
    appendonly.aof dump.rdb
    python批量插入数据发现appendonly.aof文件大小发生变化

import  redis
redis_client = redis.StrictRedis(host='localhost',port=6379)
redis_client.mset({'name':'westos','age':10})
name = redis_client.get('name').decode('utf-8')
name_len = redis_client.strlen('name')
print('用户名称:',name,'用户名长度:',name_len)
age_add = redis_client.incr('age')
for i in range(1000):
    redis_client.incr('age')

Redis架构模式

单机版
特点:简单
问题:1、内存容量有限 2、处理能力有限 3、无法高可用。
python学习之redis编程
主从复制
python学习之redis编程
主从复制
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该
服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来
的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从
服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给
从服务器,从而一直保证主从服务器的数据相同。
特点:
1、master/slave 角色
2、master/slave 数据相同
3、降低 master 读压力在转交从库
问题:

  1. 无法保证高可用
  2. 没有解决 master 写的压力
    Python与Redis
    python学习之redis编程
    python学习之redis编程
    封装
    • 连接redis服务器部分是一致的
    • 将string类型的读写进行封装
    python学习之redis编程

python学习之redis编程
"""

01_Redis数据结构.py

import redis

redis_client = redis.StrictRedis(host='172.25.254.18', port=6379)

#对于字符串的操作
"""
get
mget
set 
mset
incr
incrby
decr 
decrby
strlen
"""
redis_client.mset({'name':'westos', 'age':10})
name = redis_client.get('name').decode('utf-8')
name_len = redis_client.strlen('name')
print("用户名称: ", name, "用户名称长度: ", name_len)
age_add = redis_client.incr('age')
print("当前年龄为: ", redis_client.get('age'))
for i in range(10000):
    redis_client.incr('age')

限制某段时间内的访问次数,就比如我们登录的功能可以用手机获取验证码登录,但是我们发送验证码使用的第三方,是多少钱多少条的,
肯定不能让他一直点,一直发短信,就算前端js做了校验,若有些人用fiddler拦截绕过前台就麻烦了,
这时候可以用redis的incr命令和expire结合起来做一个解决方案

  1. 用户请求了我们的发送短信验证码服务, 用户对应的key(电话号码)
  2. 如果缓存中存在了,就是已经请求过验证码了,比如我系统参数设置的至少60秒发送一次短信, 那就代表60之内再次请求了,返回False阻止
  3. 否则就是第一次请求短信验证码或者等了60再次请求的验证码, 发送验证码. 放入redis缓存并设置失效时间60秒
import time

def send_msg(phone):
    """模拟给手机发送验证码"""
    import string
    import random
    #['4', '1', '5', '9']
    nums_list = random.sample(string.digits, 4)
    nums_code = "".join(nums_list)
    print("%s验证码:%s[公司]" %(phone, nums_code))
    return  nums_code

def phone_code(phone):
    """
    电话验证码模拟, 3秒之后可以再次发送验证码
    :param phone:
    :return:
    """
    import redis
    client = redis.StrictRedis()
    #可以从缓存中查询验证码已经发送。
    if client.get(phone):
        print("验证码发送频繁, 请稍后再试")
        return  False
    else:
        code = send_msg(phone)
        client.set(phone, code, 3)
        print("发送验证码成功")

if __name__ == '__main__':
    print("第一次发送")
    phone_code('110')
    print("第二次发送")
    phone_code('110')
    time.sleep(4)
    print("第三次发送")
    phone_code('110')"""
IP限制频繁访问:
    如果你运行 HTTP 服务,并且希望限制 HTTP 的访问频率,那么你可以借助一些比较稳定的工具,
    例如: github.com/didip/tollbooth。不过如果你构建的应用比较简单,也可以自己来实现。
IP限制的规则:
    每分钟访问次数不能超过60次。
"""

def ip_limit(IP):
    """
    每分钟访问次数不能超过60次。
    key: value = IP:count
    :param IP:
    :return:
    """
    import redis
    client = redis.StrictRedis()
    #1). 判断是否访问过本服务器;
    if client.exists(IP):
        count = client.get(IP).decode('utf-8')
        if int(count) >= 60:
            print("%s访问频繁" %(IP))
        else:
            client.incr(IP)
            print("访问+1")
    else:
        client.set(IP, 1, 60)
        print("%s第一次访问" %(IP))

if __name__ == '__main__':
    ip_limit('127.0.0.1')
    for i in range(100):
        ip_limit('172.25.254.197')

"""

02_Redis数据结构列表.py

Redis: 内存缓存数据库, 消息队列(kafka、RabbitMQ)
#如何实现高并发场景下抢红包的设计。

import  queue

class RedisQueue(object):
    """左边为队头, 右边为队尾的消息队列"""
    def __init__(self, name, **conf):
        import redis
        self.__client = redis.Redis(**conf)
        self.key = name

    def qsize(self):
        return  self.__client.llen(self.key)

    def put(self, item):
        """入队操作"""
        self.__client.rpush(self.key, item)

    def get(self, timeout=5):
        """获取对头, 如果没有到, 等待时间为timeout"""
        item = self.__client.blpop(self.key, timeout=timeout)
        return  item

    def get_nowait(self):
        item = self.__client.blpop(self.key)
        return  item

if __name__ == '__main__':
    q = RedisQueue('scores', host='172.25.254.18', port=6380)
    for i in range(10):
        q.put(i)

    while True:
        result = q.get(timeout=100)
        print(result)
        if not result:
            break

06_集合与有序集合.py


项目实战: 分布式缓存服务实践: Redis实现排行榜功能
在网页和APP中常常需要用到榜单的功能,对某个key-value的列表进行降序显示。当操作和查询并发大的时候,
使用传统数据库就会遇到性能瓶颈,造成较大的时延。使用分布式缓存服务Redis,可以实现一个
商品热销排行榜的功能。它的优势在于:
    - 数据保存在缓存中,读写速度非常快。
    - 提供字符串(String)、链表(List)、集合(Set)、哈希(Hash)等多种数据结构类型的存储。

"""
import random

def productSalesRankDemo():
    import redis
    import uuid
    PRODUCT_KINDS = 30
    host = "127.0.0.1"
    port = 6379
    password = ''
    key = "商品热销排行榜"
    client = redis.StrictRedis(host=host, port=port, password=password)
    if not client.exists(key):
        products = {}
        for count in range(PRODUCT_KINDS):
            product_name = 'product-' + str(uuid.uuid4())
            product_sale = random.randint(1000, 20000)
            products[product_name] = product_sale
        client.zadd(key, products)

productSalesRankDemo()"""

07_管道pipeline优化程序.py

import redis

redis_client = redis.StrictRedis(host='172.25.254.18', port=6380)
pipe = redis_client.pipeline()
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.execute()
"""

08_发送邮件.py

#设置服务器,用户名、口令以及邮箱的后缀
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

smtp_server = "smtp.163.com"
from_username = '技术中心'
mail_user = "xc@163.com"
#是开启smtp的授权吗不是真实的密码。
mail_password = "westos123"
#邮件主题的前缀
mail_prefix = "[运维开发部]-"

def send_email(to_addrs, subject, msg):
    try:
        # 将要发送的文本信息做MIME封装
        msg = MIMEText(msg)
        #格式化发件人名称
        msg['From'] = formataddr([from_username, mail_user])
        msg['To'] = to_addrs
        msg['Subject'] = mail_prefix + subject

        #1. 实例化smtp对象
        server = smtplib.SMTP()
        #2. 连接邮件服务器
        server.connect(smtp_server)
        #3. 登录
        server.login(mail_user, mail_password)
        #4. 发送邮件内容
        server.sendmail(mail_user, to_addrs, msg.as_string())
        #5. 关闭连接
        server.quit()
    except Exception as  e:
        print(str(e))
        return False
    else:
        return True

if __name__ == '__main__':
    send_email('976131@qq.com','寒假作业', '请与3月2日之前提交')
    print("发送成功.....")

分享题目:python学习之redis编程
新闻来源:http://chengdu.cdxwcx.cn/article/gdpijo.html