day25-python操做redis一

1.     Python操做nosql数据库

   

NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了不少难以克服的问题,而非关系型的数据库则因为其自己的特色获得了很是迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤为是大数据应用难题。python

虽然NoSQL的流行与火起来才短短几年的时间,可是不能否认,如今已经开始了第二代运动。尽管早期的堆栈代码只能算是一种实验,然而如今的系统已经更加的成熟、稳定。不过如今也面临着一个严酷的事实:技术愈来愈成熟——以致于原来很好的NoSQL数据存储不得不进行重写,也有少数人认为这就是所谓的2.0版本。该工具能够为大数据创建快速、可扩展的存储库。linux

 

非关系型数据库和关系型数据库的差异:web

 

非关系型数据库的优点:1. 性能NOSQL是基于键值对的,能够想象成表中的主键和值的对应关系,并且不须要通过SQL层的解析,因此性能很是高。2. 可扩展性一样也是由于基于键值对,数据之间没有耦合性,因此很是容易水平扩展。关系型数据库的优点:1. 复杂查询能够用SQL语句方便的在一个表以及多个表之间作很是复杂的数据查询。2. 事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优点就是本身的弱势,反之亦然。可是近年来这两种数据库都在向着另一个方向进化。例如:NOSQL数据库慢慢开始具有SQL数据库的一些复杂查询功能的雏形,好比Couchbase的index以及MONGO的复杂查询。对于事务的支持也能够用一些系统级的原子操做来实现例如乐观锁之类的方法来曲线救国。SQL数据库也开始慢慢进化,好比HandlerSocker技术的实现,能够在MYSQL上实现对于SQL层的穿透,用NOSQL的方式访问数据库,性能能够上能够达到甚至超越NOSQL数据库。可扩展性上例如Percona Server,能够实现无中心化的集群。虽然这两极都由于各自的弱势而开始进化出另外一极的一些特性,可是这些特性的增长也会消弱其原本具有的优点,好比Couchbase上的index的增长会逐步下降数据库的读写性能。因此怎样构建系统的短时间和长期存储策略,用好他们各自的强项是架构师须要好好考虑的重要问题。redis

2.     python操做redis

redis的概念:sql

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

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合能够对关系数据库起到很好的补充做用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。缓存

Redis支持主从同步。数据能够从主服务器向任意数量的从服务器上同步,从服务器能够是关联其余从服务器的主服务器。这使得Redis可执行单层树复制。存盘能够有意无心的对数据进行写操做。因为彻底实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操做的可扩展性和数据冗余颇有帮助。安全

 

Redis的安装

Redis通常都是安装在linux系统中,具体安装步骤以下:

#cd /usr/local/src

#wget http://download.redis.io/releases/redis-3.0.1.tar.gz

#tar xzf redis-3.0.1.tar.gz

#cd redis-3.0.1

#make

#src/redis-server &

检查redis是否正常启动

ps –ef |grep redis

Netstat –lnp |grep 6379

 

安装redis的客户端

pip install redis
python操做redis
例子
import redis

r = redis.Redis(host='192.168.1.5', port=6379)
r.set("wxp","I love you")
print(r.get("wxp"))
print(r.keys())
#print(dir(r))

输出结果

I love you
['wxp']

3.链接池

redis-py使用connection pool来管理对一个redis server的全部链接,避免每次创建、释放链接的开销。默认,每一个Redis实例都会维护一个本身的链接池。能够直接创建一个链接池,而后做为参数Redis,这样就能够实现多个Redis实例共享一个链接池服务器

import redis

pool = redis.ConnectionPool(host="192.168.1.5")
r = redis.Redis(connection_pool=pool)
r.set("name","wxp")
print(r.get("name"))

结果:
wxp

4.管道

redis-py默认在执行每次请求都会建立(链接池申请链接)和断开(归还链接池)一次链接操做,若是想要在一次请求中指定多个命令,则可使用pipline实现一次请求指定多个命令,而且默认状况下一次pipline 是原子性操做。减小功耗网络

redis是一个cs模式的tcp server,使用和http相似的请求响应协议。一个client能够经过一个socket链接发起多个请求命令。每一个请求命令发出后client一般会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果经过响应报文返回给client。基本的通讯过程以下:

Client: INCR X

Server: 1

Client: INCR X

Server: 2

Client: INCR X

Server: 3

Client: INCR X

Server: 4

基本上四个命令须要8个tcp报文才能完成。因为通讯会有网络延迟,假如从client和server之间的包传输时间须要0.125秒。那么上面的四个命令8个报文至少会须要1秒才能完成。这样即便redis每秒能处理100个命令,而咱们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了能够利用mget,mset 之类的单条命令处理多个key的命令外咱们还能够利用pipeline的方式从client打包多条命令一块儿发出,不须要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一块儿返回给客户端。通讯过程以下:

Client: INCR X

Client: INCR X

Client: INCR X

Client: INCR X

Server: 1

Server: 2

Server: 3

Server: 4

假设不会由于tcp报文过长而被拆分。可能两个tcp报文就能完成四条命令,client能够将四个命令放到一个tcp报文一块儿发送,server则能够将四条命令的处理结果放到一个tcp报文返回。经过pipeline方式当有大批量的操做时候。咱们能够节省不少原来浪费在网络延迟的时间。须要注意到是用 pipeline方式打包命令发送,redis必须在处理完全部命令前先缓存起全部命令的处理结果。打包的命令越多,缓存消耗内存也越多。因此并是否是打包的命令越多越好。具体多少合适须要根据具体状况测试

 

import datetime
import redis

def withpipe(r):
    pipe = r.pipeline(transaction=True)
    for i in xrange(1,1000):
        key = "wxp" + str(i)
        value = "wxp1" +str(i)
        pipe.set(key,value)
    pipe.execute()
def withoutpipe(r):
    for i in xrange(1,1000):
        key = "wxp" + str(i)
        value = "wxp1" +str(i)
        r.set(key,value)

if __name__ == "__main__":
    pool = redis.ConnectionPool(host="192.168.1.5",port = 6379,db=0)
    r1 = redis.Redis(connection_pool=pool)
    r2 = redis.Redis(connection_pool=pool)
    start = datetime.datetime.now()
    withpipe(r1)
    end = datetime.datetime.now()
    t_time = (end-start).microseconds
    print("withpipe time is:{0}".format(t_time))

    start = datetime.datetime.now()
    withoutpipe(r2)
    end = datetime.datetime.now()
    t_time = (end - start).microseconds
    print("withoutpipe time is : {0}".format(t_time))

结果:
withpipe time is:34000
withoutpipe time is : 969000
相关文章
相关标签/搜索