Chinaunix首页 | 论坛 | 博客
  • 博客访问: 230712
  • 博文数量: 57
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 557
  • 用 户 组: 普通用户
  • 注册时间: 2015-10-01 18:05
文章分类

全部博文(57)

文章存档

2017年(57)

我的朋友

分类: Python/Ruby

2017-11-24 15:29:15

Python操作nosql数据库

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

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

 

非关系型数据库和关系型数据库的差别:

 

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

redis
的概念:


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

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了JavaC/C++C#PHPJavaScriptPerlObject-CPythonRubyErlang等客户端,使用很方便。

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

 

Redis的安装

Redis一般都是安装在linux系统中,具体安装步骤如下:

#cd /usr/local/src

#wget

#tar xzf redis-3.0.1.tar.gz

#cd redis-3.0.1

#make

#./redis-server ../redis.conf

检查redis是否正常启动

ps –ef |grep redis

netstat –lnp |grep 6379

windows 安装redis的客户端
命令行下运行:pip install redis


简单操作:

redis是以key-value的形式存储的,所以我们在操作的时候。首先我们将redis所在主机的ip和发布端口作为参数实例化了一个对象r,然后执行set('address','Shanghai'),这样我们就在内存中存储了一个keyaddress,值为‘Shanghai’的项。我们可以理解为{('address','Shanghai'},当我们要读取的之后,keys()就是获得key值。


点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # Author :Alvin.xie
  4. # @Time :2017-11-24 14:51
  5. # @file :redisconn.py

  6. import redis
  7. r = redis.Redis(host="10.89.1.10", port=6379)
  8. r.set("address", "Shaihai")
  9. print(r.get("address"))
  10. print(r.keys())
  11. #print(dir(r))
执行结果
Shaihai
['address']

连接池

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

点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # Author :Alvin.xie
  4. # @Time :2017-11-24 15:21
  5. # @file :redispool.py

  6. import redis

  7. pool = redis.ConnectionPool(host="10.89.1.10")
  8. r = redis.Redis(connection_pool=pool)
  9. r.set("name", "kate")
  10. print(r.get("name"))
执行结果:
kate

管道

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

redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。
实现代码如下:

点击(此处)折叠或打开

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # Author :Alvin.xie
  4. # @Time :2017-11-24 15:23
  5. # @file :guandao.py

  6. import datetime
  7. import redis


  8. def withpipe(r):
  9.     pipe = r.pipeline(transaction=True)
  10.     for i in xrange(1, 1000):
  11.         key = "test1" +str(i)
  12.         value = "test1" + str(i)
  13.         pipe.set(key, value)
  14.     pipe.execute()


  15. def withoutpipe(r):
  16.     # pipe = r.pipeline(transaction=True)
  17.     for i in xrange(1, 1000):
  18.         key = "test1" + str(i)
  19.         value = "test1" + str(i)
  20.         r.set(key, value)

  21. if __name__ == "__main__":
  22.     pool = redis.ConnectionPool(host="10.89.1.10", port=6379, db=0)
  23.     r1 = redis.Redis(connection_pool=pool)
  24.     r2 = redis.Redis(connection_pool=pool)
  25.     start = datetime.datetime.now()
  26.     # print(start)
  27.     withpipe(r1)
  28.     end = datetime.datetime.now()
  29.     # print((end-start).microseconds)
  30.     # print(end-start)
  31.     t_time = (end - start).microseconds
  32.     print("withpipe time is : {0}".format(t_time))

  33.     start = datetime.datetime.now()
  34.     withoutpipe(r2)
  35.     end = datetime.datetime.now()
  36.     t_time = (end - start).microseconds
  37.     print("withoutpipe time is : {0}".format(t_time))
执行结果:
withpipe time is : 26000
withoutpipe time is : 845000
























 

阅读(1589) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~