zoukankan      html  css  js  c++  java
  • Python- redis缓存 可达到瞬间并发量10W+

    redis是什么?

    mysql是一个软件,帮助开发者对一台机器的硬盘进行操作。
    redis是一个软件,帮助开发者对一台机器的内存进行操作。

    redis缓存 可达到瞬间并发量10W+

    高并发架构系列:Redis为什么是单线程、及高并发快的3大原因详解

    http://m.sohu.com/a/282430394_99994950?qq-pf-to=pcqq.group

    https://www.cnblogs.com/liuqingzheng/p/9833534.html


    特点
    - 可以做持久化:
    - AOF
    - RDB
    - 单进程单线程
    - 相当于是大字典,5大数据类型

    redis={
    k1:'123', 字符串
    k2:[1,2,3,4,4,2,1], 列表
    k3:{1,2,3,4}, 集合
    k4:{name:123,age:666}, 字典
    k5:{('alex',60),('eva-j',80),('rt',70),},有序集合
    }
    使用字典:
    - 基本操作
    - 慎重使用hgetall, 优先使用 hscan_iter
    - 计数器

    注意事项:redis操作时,只有第一层value支持:list,dict ....

    关键字:缓存

    缓存,优先去redis中获取,如果没有就是数据库。

    redis的应用场景


    1. top 列表
    产品运营总会让你展示最近、最热、点击率最高、活跃度最高等等条件的top list。很多更新较频繁的列表如果使用MC+MySQL维护的话缓存失效的可能性会比较大,鉴于占用内存较小的情况,使用Redis做存储也是相当不错的。

    2.最后的访问

    用户最近访问记录也是redis list的很好应用场景,lpush lpop自动过期老的登陆记录,对于开发来说还是非常友好的

    3.手机验证码的,有效时间

    4.限制用户登录的次数,比如一天错误登录次数10次。

    5.投票系统 ,投票结果排序。 排行榜等等

    6.存储社交信息,set的并集和交集。比较两个用户的共同粉丝

    7.各种计数:商品维度计数(点赞数,评论数,浏览数)

    8.发布订阅,聊天室等

    安装

    - redis软件
    - yum install redis
    redis-server /etc/redis.conf
    -
    wget http://download.redis.io/releases/redis-3.0.6.tar.gz
    tar xzf redis-3.0.6.tar.gz
    cd redis-3.0.6
    make

    /src/redis-server redis.conf


    默认端口:6379

    配置文件:
    bind 0.0.0.0
    port 6379
    requirepass dskjfsdf


    - python连接redis的模块

    pip3 install redis

    Redis Pttl 命令 - 以毫秒为单位返回 key 的剩余的过期时间

    基本使用

    a.
    import redis
    # 创建连接
    # conn = redis.Redis(host='47.94.172.250',port=6379,password='luffy1234')
    # conn.set('x1','wanghuaqiang',ex=5)
    # val = conn.get('x1')
    # print(val)
    b.
    # 连接池
    # import redis
    #
    # pool = redis.ConnectionPool(host='10.211.55.4', port=6379,password='luffy1234',max_connections=1000)
    # conn = redis.Redis(connection_pool=pool)
    #
    # conn.set('foo', 'Bar')

    连接池注意:连接池只创建一次
    wupeiqi/articles/5132791.html

    使用字典
    基本操作
    慎用hgetall,优先使用hscan_iter
    计数器

    注意事项:redis操作时,只有第一次value支持:list,dict...
    session就是通过数据库,序列化到缓存里的和反序列化拿来用

     

    redis字符串操作总结:

    set(name, value, ex=None, px=None, nx=False, xx=False)
    在Redis中设置值,默认,不存在则创建,存在则修改
    参数:
    ex,过期时间(秒)
    px,过期时间(毫秒)
    nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
    xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会 
    设置新值

    get(name)
    获取值

    mget(keys, *args)
    批量获取
    如:
    mget('k1', 'k2')

    r.mget(['k3', 'k4'])

    getset(name, value)
    设置新值并获取原来的值

    getrange(key, start, end)
    # 获取子序列(根据字节获取,非字符)
    # 参数:
    # name,Redis 的 name
    # start,起始位置(字节)
    # end,结束位置(字节)
    # 如: "刘清政" ,0-3表示 "刘"

    setrange(name, offset, value)
    # 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
    # 参数:
    # offset,字符串的索引,字节(一个汉字三个字节)
    # value,要设置的值


    strlen(name)
    # 返回name对应值的字节长度(一个汉字3个字节)

    incr(self, name, amount=1) #如点赞,提高性能
    # 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
    # 参数:
    # name,Redis的name
    # amount,自增数(必须是整数)
    # 注:同incrby

    append(key, value)
    # 在redis name对应的值后面追加内容
    # 参数:
    key, redis的name
    value, 要追加的字符串

    # 字符串操作
    # conn.set('yyy', 'egon', nx=True)
    # conn.set('ttt', 'egon', xx=True)
    # import datetime
    # v=datetime.timedelta(weeks=2)
    # ctime=datetime.datetime.now()
    # ctime+v
    # conn.setex('ttt', 5,'xxx')

    # conn.mset({"k1": 'v1', "k2": 'v12', "k3": 'v3'})
    # value=conn.mget('name','k1','k2')
    # value=conn.mget(['name','k1','k2'])
    # print(value)
    # print(conn.getset('name','xxxxxx'))
    # conn.setrange('name', 1, 'eerrrrrrrrrrrrrrrr')

    # print(conn.strlen('name'))
    # conn.set('age',"19")
    # 文章阅读数
    # conn.incr('age',-4)
    # conn.append('name','0000000')

    redis字典操作总结:

    hscan_iter(name, match=None, count=None)
    # 利用yield封装hscan创建生成器,实现分批去redis中获取数据

    # 参数:
    # match,匹配指定key,默认None 表示所有的key
    # count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数

    # 如:
    # for item in r.hscan_iter('xx'):
    # print item

    # 字典操作

    # conn.hset('person','age','18')
    # conn.hset('person','name','lqz')
    # conn.hset('person','height','180')
    # conn.hmset('person2',{'age':'19','name':'egon','xx':'xx'})
    # print(conn.hget('person','name'))
    # print(conn.hmget('person','age','name','height'))
    # print(conn.hmget('person',['age','name','height']))
    # 以后用这个要慎用
    # print(conn.hgetall('person'))
    # print(conn.hlen('person'))
    # print(conn.hkeys('person'))

    # print(conn.hexists('person','nameee'))
    # conn.hdel('person2','name','age')

    # conn.hincrby('person','age')
    # for i in range(1000000):
    # conn.hmset('person2',{'eeeeee%s'%i:i})
    # 如果数据量不大,自动全取出来
    # cour, data = conn.hscan('person2', cursor=0, match=None, count=3000)
    # cour2, data2 = conn.hscan('person2', cursor=cour, match=None, count=3000)
    #
    # print(cour)
    # print(len(data))
    #
    # print('-------')
    # print(cour2)
    # print(len(data2))

    # cour2 = 0
    # count = 1
    # while True:
    # cour2, data2 = conn.hscan('person2', cursor=cour2, match=None, count=3000)
    # count += len(data2)
    # if cour2 == 0:
    # break
    #
    # print(count)
    # 不用getall的方式取,用这种方式取,也能把所有数据取出来,但是不会吧内存撑爆
    # data=conn.hscan_iter('person2', match=None, count=100)
    # # 内部有915371条数据
    # # 先去取100条
    # # 做成了生成器
    # # 取值的时候,100以内,没有再去查,用的是生成器
    # # 当超过一百,再去取100条.做成了生成器
    # for i in data:
    # print(i)

    redis列表操作总结:

    # 列表操作

    # conn.lpush('list','2')
    # conn.rpush('list','3')
    # conn.lpushx('list2','3')
    # print(conn.llen('list'))

    # conn.linsert('list', 'after', "3", '444444')
    # conn.linsert('list', 'before', "3", '5555555')
    # 从0开始
    # conn.lset('list',4,'66666666')
    # conn.lrem('list',0,"3")
    # print(conn.lpop('list'))
    # print(conn.rpop('list'))
    # 按索引取值,支持负索引
    # print(conn.lindex('list',-2))

    # 简单的分布式爬虫
    # print(conn.blpop('list'))
    # 取出列表的所有值

    # conn.lpush('list',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68])
    # print(conn.lrange('list',0,-1))
    # 自定义列表的增量迭代
    # def scan_list(name,count=2):
    # index=0
    # while True:
    # data_list=conn.lrange(name,index,count+index-1)
    # if not data_list:
    # return
    # index+=count
    # for item in data_list:
    # yield item
    # # print(conn.lrange('test',0,100))
    # for item in scan_list('list',5):
    # print('---')
    # print(item)

    # 其它操作

    # 事务(不支持事务,但是通过管道模拟)
    # conn=redis.Redis(host='127.0.0.1', port=6379)
    # # 拿到一个管道,transaction=True表示管道内部都是原子性
    # pi=conn.pipeline(transaction=True)
    # # 说明是批量命令
    # pi.multi()
    #
    #
    # pi.set('xx','xxx')
    # pi.set('yy','yyy')
    #
    # pi.execute()

    # 其它操作
    # conn.delete('name1')
    # 用的比较多
    # print(conn.keys('k*'))

    # print(conn.type('person'))
    # django中使用redis

     

     redis 管道(模拟事务)

    import redis
     
    pool = redis.ConnectionPool(host='10.211.55.4', port=6379)
     
    r = redis.Redis(connection_pool=pool)
     
    # pipe = r.pipeline(transaction=False)
    pipe = r.pipeline(transaction=True)
    pipe.multi()
    pipe.set('name', 'alex')
    pipe.set('role', 'sb')
     
    pipe.execute()
    

      

    应用(django):

    方式一:

    utils文件夹下,建立redis_pool.py

    import redis
    POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,password='1234',max_connections=1000)

    视图函数中使用:

    复制代码
    import redis
    from django.shortcuts import render,HttpResponse
    from utils.redis_pool import POOL
    
    def index(request):
        conn = redis.Redis(connection_pool=POOL)
        conn.hset('kkk','age',18)
    
        return HttpResponse('设置成功')
    def order(request):
        conn = redis.Redis(connection_pool=POOL)
        conn.hget('kkk','age')
    
        return HttpResponse('获取成功')
    复制代码

    方式二:

    安装django-redis模块

    pip3 install django-redis

    setting里配置:

    复制代码
    # redis配置
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                # "PASSWORD": "123",
            }
        }
    }
    复制代码

    视图函数:

    from django_redis import get_redis_connection
    conn = get_redis_connection('default')
    print(conn.hgetall('xxx'))

    高级使用: (memachach 不能做持久化)
    1. 全站缓存(通过中间件)
    wupeiqi/articles/5246483.html

    2. 单视图

    3. 局部页面

  • 相关阅读:
    springmvc文件上传 并读取excel文件基本写法 多文件时参数为 @RequestParam MultipartFile[] myfiles 单文件时直接传File
    谷歌浏览器 js调试方法
    jxl实现文件导入页面例子
    angularjs实现上传文件动态显示文件列表
    文件上传 多个文件上传与单个文件上传
    angularjs实现动态表格的删除与增加
    2017songyunxin
    百万数据导出
    OutProductController
    DownloadUtil
  • 原文地址:https://www.cnblogs.com/du-jun/p/10408576.html
Copyright © 2011-2022 走看看