您的位置:首页 > 数据库 > Memcache

Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

2018-03-17 19:46 381 查看

Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

 

Memcached

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

Memcached安装和基本使用

Memcached安装:

启动Memcached

Memcached命令

Python操作Memcached

安装API

1、第一次操作

Ps:debug = True 表示运行出现错误时,现实错误信息,上线后移除该参数。

2、天生支持集群

python-memcached模块原生支持集群操作,其原理是在内存维护一个主机列表,且集群中主机的权重值和主机在列表中重复出现的次数成正比

如果用户根据如果要在内存中创建一个键值对(如:k1 = "v1"),那么要执行一下步骤:

  • 根据算法将 k1 转换成一个数字
  • 将数字和主机列表长度求余数,得到一个值 N( 0 <= N < 列表长度 )
  • 在主机列表中根据 第2步得到的值为索引获取主机,例如:host_list
  • 连接 将第3步中获取的主机,将 k1 = "v1" 放置在该服务器的内存中

代码实现如下:

3、add
添加一条键值对,如果已经存在的 key,重复执行add操作异常

4、replace
replace 修改某个key的值,如果key不存在,则异常

5、set 和 set_multi

set            设置一个键值对,如果key不存在,则创建,如果key存在,则修改
set_multi   设置多个键值对,如果key不存在,则创建,如果key存在,则修改

6、delete 和 delete_multi

delete             在Memcached中删除指定的一个键值对
delete_multi    在Memcached中删除指定的多个键值对

7、get 和 get_multi

get            获取一个键值对
get_multi   获取多一个键值对

8、append 和 prepend

append    修改指定key的值,在该值 后面 追加内容
prepend   修改指定key的值,在该值 前面 插入内容

9、decr 和 incr  

incr  自增,将Memcached中的某一个值增加 N ( N默认为1 )
decr 自减,将Memcached中的某一个值减少 N ( N默认为1 )

10、gets 和 cas

如商城商品剩余个数,假设改值保存在memcache中,product_count = 900
A用户刷新页面从memcache中读取到product_count = 900
B用户刷新页面从memcache中读取到product_count = 900

如果A、B用户均购买商品

A用户修改商品剩余个数 product_count=899
B用户修改商品剩余个数 product_count=899

如此一来缓存内的数据便不在正确,两个用户购买商品后,商品剩余还是 899
如果使用python的set和get来操作以上过程,那么程序就会如上述所示情况!

如果想要避免此情况的发生,只要使用 gets 和 cas 即可,如:

Ps:本质上每次执行gets时,会从memcache中获取一个自增的数字,通过cas去修改gets的值时,会携带之前获取的自增值和memcache中的自增值进行比较,如果相等,则可以提交,如果不想等,那表示在gets和cas执行之间,又有其他人执行了gets(获取了缓冲的指定值), 如此一来有可能出现非正常数据,则不允许修改。

Memcached 真的过时了吗?

Redis

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

 View Code

一、Redis安装和基本使用

启动服务端

启动客户端

二、Python操作Redis

API使用

redis-py 的API的使用可以分类为:

  • 连接方式
  • 连接池
  • 操作 String 操作
  • Hash 操作
  • List 操作
  • Set 操作
  • Sort Set 操作
  • 管道
  • 发布订阅
  •  

    1、操作模式

    redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。

    2、连接池

    redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

    3、操作

    String操作,redis中的String在在内存中按照一个name对应一个value来存储。如图:

    set(name, value, ex=None, px=None, nx=False, xx=False)

    setnx(name, value)

    setex(name, value, time)

    psetex(name, time_ms, value)

    mset(*args, **kwargs)

    get(name)

    mget(keys, *args)

    getset(name, value)

    getrange(key, start, end)

    setrange(name, offset, value)

    setbit(name, offset, value)

    getbit(name, offset)

    bitcount(key, start=None, end=None)

    bitop(operation, dest, *keys)

    strlen(name)

    incr(self, name, amount=1)

    incrbyfloat(self, name, amount=1.0)

    decr(self, name, amount=1)

    append(key, value)

      

    Hash操作,redis中Hash在内存中的存储格式如下图:

    hset(name, key, value)

    hmset(name, mapping)

    hget(name,key)

    hmget(name, keys, *args)

    hgetall(name)

    hlen(name)

    hkeys(name)

    hvals(name)

    hexists(name, key)

    hdel(name,*keys)

    hincrby(name, key, amount=1)

    hincrbyfloat(name, key, amount=1.0)

    hscan(name, cursor=0, match=None, count=None)

    hscan_iter(name, match=None, count=None)

      

    List操作,redis中的List在在内存中按照一个name对应一个List来存储。如图:

    lpush(name,values)

    lpushx(name,value)

    llen(name)

    linsert(name, where, refvalue, value))

    r.lset(name, index, value)

    r.lrem(name, value, num)

    lpop(name)

    lindex(name, index)

    lrange(name, start, end)

    ltrim(name, start, end)

    rpoplpush(src, dst)

    blpop(keys, timeout)

    brpoplpush(src, dst, timeout=0)

    自定义增量迭代

    Set操作,Set集合就是不允许重复的列表

    sadd(name,values)

    scard(name)

    sdiff(keys, *args)

    sdiffstore(dest, keys, *args)

    sinter(keys, *args)

    sinterstore(dest, keys, *args)

    sismember(name, value)

    smembers(name)

    smove(src, dst, value)

    spop(name)

    srandmember(name, numbers)

    srem(name, values)

    sunion(keys, *args)

    sunionstore(dest,keys, *args)

    sscan(name, cursor=0, match=None, count=None)
    sscan_iter(name, match=None, count=None)

     

    有序集合,在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。

    zadd(name, *args, **kwargs)

    zcard(name)

    zcount(name, min, max)

    zincrby(name, value, amount)

    r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)

    zrank(name, value)

    zrangebylex(name, min, max, start=None, num=None)

    zrem(name, values)

    zremrangebyrank(name, min, max)

    zremrangebyscore(name, min, max)

    zremrangebylex(name, min, max)

    zscore(name, value)

    zinterstore(dest, keys, aggregate=None)

    zunionstore(dest, keys, aggregate=None)

    zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
    zscan_iter(name, match=None, count=None,score_cast_func=float)

      

    其他常用操作

    delete(*names)

    exists(name)

    keys(pattern='*')

    expire(name ,time)

    rename(src, dst)

    move(name, db))

    randomkey()

    type(name)

    scan(cursor=0, match=None, count=None)
    scan_iter(match=None, count=None)

     

    4、管道

    redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

    5、发布订阅

    发布者:服务器

    订阅者:Dashboad和数据处理

    Demo如下:

     RedisHelper

    订阅者:

    发布者:

    更多参见:https://github.com/andymccurdy/redis-py/

    http://doc.redisfans.com/

    RabbitMQ

    RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。

    MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

    RabbitMQ安装

    注意:service rabbitmq-server start/stop

    安装API

    使用API操作RabbitMQ

    基于Queue实现生产者消费者模型

     View Code

    对于RabbitMQ来说,生产和消费不再针对内存里的一个Queue对象,而是某台服务器上的RabbitMQ Server实现的消息队列。

    1、acknowledgment 消息不丢失

    no-ack = False,如果消费者遇到情况(its channel is closed, connection is closed, or TCP connection is lost)挂掉了,那么,RabbitMQ会重新将该任务添加到队列中。

     消费者

    2、durable   消息不丢失

     生产者  消费者

    3、消息获取顺序

    默认消息队列里的数据是按照顺序被消费者拿走,例如:消费者1 去队列中获取 奇数 序列的任务,消费者1去队列中获取 偶数 序列的任务。

    channel.basic_qos(prefetch_count=1) 表示谁来谁取,不再按照奇偶数排列

     消费者

    4、发布订阅

    发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。所以,RabbitMQ实现发布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。

     exchange type = fanout

     发布者  订阅者

    5、关键字发送

     exchange type = direct

    之前事例,发送消息时明确指定某个队列并向其中发送消息,RabbitMQ还支持根据关键字发送,即:队列绑定关键字,发送者将数据根据关键字发送到消息exchange,exchange根据 关键字 判定应该将数据发送至指定队列。

     消费者  生产者

    6、模糊匹配

     exchange type = topic

    在topic类型下,可以让队列绑定几个模糊的关键字,之后发送者将数据发送到exchange,exchange将传入”路由值“和 ”关键字“进行匹配,匹配成功,则将数据发送到指定队列。

    • # 表示可以匹配 0 个 或 多个 单词
    • *  表示只能匹配 一个 单词
     消费者  生产者

    注意:

     

     View Code

    SQLAlchemy

    SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

    Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

    步骤一:

    使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

     事务操作

    注:查看数据库连接:show status like 'Threads%';

    步骤二:

    使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。

     增删改查

    更多内容详见:

        http://www.jianshu.com/p/e6bba189fcbd

        http://docs.sqlalchemy.org/en/latest/core/expression_api.html

    注:SQLAlchemy无法修改表结构,如果需要可以使用SQLAlchemy开发者开源的另外一个软件Alembic来完成。

    步骤三:

    使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL。

    更多功能参见文档,猛击这里下载PDF

    posted @ 2018-03-17 19:46 田湾第一帅 阅读(...) 评论(...) 编辑 收藏
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: