• 缓存



     
    一、memcached(value只能是str):
    • 关键字:
      • 旁路代理:
        • 缓存中若无数据,app自行从db获取,至于获取后是否更新缓存,由代码自行决定
      • 分布式:
        • 各个节点彼此无视,分布式功能完全依赖于app或调度器实现(haproxy)
      • 缓存清理:
        • memcache不会主动清理过期数据,只会在系统给memcache分配的存储空间使用完毕后,根据LUR算法,数据更新时对不活跃数据进行覆盖
      • 集群实现:
        • 通过app自身,搞笑,雪崩了谁背锅
        • 通过haproxy,正解!只有haproxy调度器有一致性hash算法
    • 安装:
      • server:
        • 1、yum install memcached ;
        • 2、memadmin.tar.gz 管理控制台,php实现的web版本
      • client:
        • 1、安装API:python-memcache  # --trusted-host=pypi.douban.com
    • 使用:
      • 连接:
        • import memcache
        • server = memcache.Client( [('1.1.1.1:11211', 1), ('1.1.1.2:11211', 2)] )
        • 解释:
          • 该API模块支持权重,即其内部维护一个主机列表,权重为几,则该节点在列表中出现几次
          • 如上则:1.1.1.1  1.1.1.2  1.1.1.2 
          • 插入数据时,将Key先进行hash取数值,再将数值与列表长度取模,余数为几则数据存储到第几个个节点
      • add/replace:
          • server.add('key1', value1) # 添加一条键值对,若key已经存在,则操作异常
          • server.replace('key1', '11111') # 修改某个key的值,若key不存在,则异常
      • set/set_nulti
        • server.set('key1', 'value1') # 设置一个键值对,key不存在则创建;key存在则修改
        • server.set_nulti( {'key1':'value1', 'key2':'value2'} ) # 设置多个键值对,key不存在则创建,key存在则修改
      • delete/delete_nulti
        • server.delet('key1') # 删除一个键值对
        • server.delete_nulti(['key1', 'key2']) # 删除多个键值对
      • get/get_nulti
        • ret = server.get( 'key1' ) # 获取一个键值对
        • ret_dic = server.get_multi( ['key1', 'key2'] )  # 获取多个键值对
      • append/prepend
        • server.append('key', 'after')  # 在指定key值后,追加内容
        • server.prepend('key', 'before')  # 在指定key值前,插入内容
      • incr/decr
        • server.incr('key1')  # 将某一个值自增N ,N默认为1, key的值自增了1
        • server.incr('key1', 10 ) # 将某一个值自减N, N默认为1, key的值自增了10
        • server.decr('key1') # key的值自减1
        • server.decr('key1', 10) # key的值自减10
      • gets/cas
        • 场景:若商品剩余数为100,A B 同时购买1个,则本应为98,但是,A和B均会在本地运算得到99 ,再写入memcahce中
        • ret = server.gets('product_count') # 每个 client 通过 gets 获取数据的同时,会获取该key的一个自增的数字,
        • server.cas('product_count', 99)  # 修改数据前,对比之前获取的数字是否相同,不同则表示有人也获取了数据,可能已经被别人在本地修改,即抛出异常

     
    二、redis:
     
    1、概述
    • 安装:
      • server: yum install redis ; sed -i 's/127.0.0.1/0.0.0.0/g' /etc/redis.conf
      • client:安装API :redis # --trusted-host=pypi.douban.com

    • import redis
      • redis-py 提供了两个类:Redis, StrictRedis 用于实现redis的命令,
        • StrictRedis用于实现大部分官方的语法和命令,
        • Redis 是strictredis的子类,用于向前兼容旧版本的redis-py
    • 连接方式:
      • 直接连接:conn = redis.Redis(host='1.1.1.1', port=6379)
      • 连接池:
    pool = redis.ConnectionPool(host='1.1.1.1', port=6379)
    conn = redis.Redis(connection_pool=pool)
    conn.set('key1', 'value1')

    2、基本数据类型
    • string 操作 (name -- key 一一对应):
      • set/mset
    set( name, value, ex=None, px=None, nx=False, xx=False )
    ex 过期时间,秒
    px 过期时间,毫秒
    nx 若为True,则表示只有该key不存在,才执行set
    xx 若为True,则表示只有该key存在,才执行set

    setns(name, value)   # 当name不存在时,创建一个键值对
    setex(name, value, time) # 创建一个键值对,并指定过期时间
    mset(* args, **kwargs) # 批量设置,比如 mset( k1='v1', k2='v2' )
      • get(name) / mget(keys, *args)
    get('key1')
    mget('key1', 'key2') # 批量获取
      • 自增、自减、追加
    incr(self, name, amount=1) # 当name不存在,则创建name=amount,否则其值自增1
    infcbyfloat(self, name, amount=1.0) # 同上,只不过自增可浮点数
    decr(self, name, amount=1) # 自减name对应的值,当name不存在则创建name=amount
    append(key, value) # 在指定key后面追加内容
      • 其他:
    getset(name, value) # 设置一个新值,并获取原先的值
    getrange(name, start, end) # 切片,获取指定key的值,并进行切片
    strlen(name) # 获取指定key的字节长度 
    • hash 操作(一个name对应一个字典)
      • 创建
    hset(name, key, value) # 为指定name关联一个键值对,不存在则创建;存在则修改
    hmset(name, mapping) # 批量设置键值对,mapping为字典,比如dic1 , dic2
      • 获取指定字典中指定key值
    hget(name, key) # 在name对应的dict中获取指定key
    hmget(name, keys, lst) # 在name对应的hash中获取多个key值,lst中为各key名称
      • 获取指定字典中所有key值
    hgetall(name) # 获取name对应的所有键值
    hlen(name) # 获取name对应的所有键值个数
      • 获取指定字典中所有key,或value
    hkeys(name) # 获取name对应的hash中所有的key名称
    hvals(name) # 获取name对应的hash中所有的value的值
      • 判断:
    hexists(name, key) # 检测name对应的hash中是否存在指定key
      • 删除:
    hdel(name, *keys) # 将name对应的hash中指定key键值对删除, *keys可为列表或元组
      • 自增、自减:
    hincrby(name, key, amount=1) # 自增指定name中的指定key值,不存在,则创建key=amount
    hincrbyfloat(name, key, amount=1.0) # 同上,只不过可以浮点

      • 迭代获取:
    --------------- hscan
    hscan(name, cursor=0, match=None, coiunt=None) # 迭代式获取键值对
    cursor1, data = server.hscan(name, cursor=0, match=None, count=None)
    cursor2, data = server.hscan(name, cursor=cursor1, match=None, count=None)
    # cursor表示游标指针,当cusor为0,则表示已经获取完成
    -------------- hscan_iter
    # 利用yield封装hscan创建生成器,实现分批获取数据
    for item in server.hscan_iter(name)
    print(item)
    • list 操作(每个name对应一个lst)
      • 添加:
    lpush(name, value) # 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
    server.lpush('name1', 11,22,33)  # 保存顺序为33,22,11
      • 列表长度:
    llen(name) # 返回对应list的元素个数
      • 插入:
    linsert(name, where, refvalue, value) # 在指定值前后插入数据
    name: 名称
    where: BEFORE 或 AFTER
    refvalue: 标杆值,即在该值前后插入数据
    value: 要插入的数据
      • 删除:
    lrem(name, value, num) # 在name对应的list中删除指定的值
    name::列表名称
    value:要删除的值
    num:正数,从前到后删N个,负数,从后到前删N个
      • pop弹出:
    lpop(name) # 从列表左侧弹出一个元素并移除,
    rpop(name) # 从右侧弹出
      • 切片、索引:
    lset(name, index,value) # 在索引处重新赋值
    lindex(name , index) # 在列表中根据索引获取列表元素
    lrange(name, start, end) # 切片获取数据
    ltrim(name, start, end) # 切片移除
      • 迭代:
    redis的列表没有提供迭代功能,因此需要自定义增量迭代
    # 定义迭代器
    def list_iter(name):
    list_count = server.llen(name)
    for index in range(list_count):
    yield server.lindex(name, index)
    # 使用
    for item in list_iter('name'):
    print(item)
      • 集合、有序集合
    3、管道:
      • redis-py 默认在执行每次请求时,都会创建(连接池获取链接)和断开(释放链接),
      • 若想在一次请求中完成多个指令,则可以使用pipline,默认情况下,一次pipline是个原子操作

    import redis
    pool = redis.ConnectionPool(host='1.1.1.1', port=6379)
    server = redis.Redis(connection_pool=pool)

    pipe = server.pipline(transaction=True) # 下面的指令会缓存到cmd buffer中
    server.set('name', 'qiao')
    server.set('role', 'kk')
    pipe.execute() # 发送并执行cmd buffer中指令
    4、发布订阅:
      • 自定义公共类
    import redis

    class RedisHelper:
    def __init__(self):
    self.__conn = redis.Redis(host='61.129.46.111', port=6379)
    self.chan_sub = 'xxx'

    def public(self, msg):  # 发布消息
    self.__conn.publish(self.chan_sub, msg)
    return True

    def subscribe(self):
    pub = self.__conn.pubsub() # 返回一个发布订阅对象
    pub.subscribe(self.chan_sub) # 订阅一个频道
    pub.parse_response() # 订阅频道的时候也会有响应,需要解析
    return pub # 返回该订阅了频道的“发布/订阅”对象
      • client端(订阅者)
    obj = RedisHelper() # 实例化一个自定义类
    redis_sub = obj.subscribe()  # 获取一个已经订阅了频道的“发布/订阅”对象

    while True:
    msg = redis_sub.parse_response()  # 响应为列表结构,且元素为字节,[b'message', b'xxx', b'test1'] <class 'list'>
    data = msg[2].decode()
    print(msg, type(msg), data, type(data))
      • server 端(发布者)
    obj = RedisHelper() # 实例化一个自定义类
    obj.public('test1') # 发布消息








  • 相关阅读:
    mac下完全卸载程序的方法
    Mac下检测NSTableView的滑动事件的方法
    一行代码起动全屏
    Unsupported compiler '4.0' selected for architecture 'i386'类错误解决办法
    编译错误“The run destination My Mac 64bit is not valid for Running the scheme '***',解决办法
    ios项目中导入百度地图SDK出错的问题
    Unable to resolve target 'android9'解决办法
    ios保存录制好的视频到相簿的方法
    NSTableView系列之代码创建(不用nib)
    谈内链优化不是每个站点都能做的
  • 原文地址:https://www.cnblogs.com/qiaogy/p/5875443.html
Copyright © 2020-2023  润新知