设为首页 收藏本站
查看: 1027|回复: 0

[经验分享] 30. Pytnon NoSQL简介 Redis服务搭建、连接池、管道

[复制链接]

尚未签到

发表于 2018-11-3 09:35:56 | 显示全部楼层 |阅读模式
  1.NoSQL简介
  NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
  虽然NoSQL的流行与火起来才短短几年的时间,但是不可否认,现在已经开始了第二代运动。尽管早期的堆栈代码只能算是一种实验,然而现在的系统已经更加的成熟、稳定。不过现在也面临着一个严酷的事实:技术越来越成熟——以至于原来很好的NoSQL数据存储不得不进行重写,也有少数人认为这就是所谓的2.0版本。该工具可以为大数据建立快速、可扩展的存储库。
  非关系型数据库和关系型数据库的差别:
  非关系型数据库的优势:


  • 性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
  • 可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。  关系型数据库的优势:

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

  2.redis服务搭建
  redis的概念:
  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  

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

# -*- coding:utf-8 -*-  
import redis
  
redis_config = {
  
"host":"192.168.48.128",
  
"port":6379
  
}
  
r = redis.Redis(**redis_config)
  

  
r.set("shang", "I love you!")
  
# set 操作 第一参数是key,第二个参数是value
  
print(r.get("shang"))
  
# r.key 就是获取到所有的key
  
print(r.keys())
  
# r.get 就是获取到key的值
  

  结果:
  I love you!
  ['shang', 'ajing']
  3.redis连接池
  连接池
  redis-py使用connection pool(连接池)来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。
  默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
  

#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
import redis
  
redis_config = {
  
"host":"192.168.48.128",
  
"port":6379
  
}
  

  
pool = redis.ConnectionPool(**redis_config)
  
r = redis.Redis(connection_pool=pool)
  

  
r.set("name", "lingxiangxiang")
  
print(r.get("name"))
  

  

  结果:
  Lingxiangxiang
  创建一个连接池函数,每次使用时候调用就行了:
  

import redis  
def get_redis_connect():
  redis_config = {
  "host":"192.168.48.128",
  "port":6379
  
}
  pool = redis.ConnectionPool(**redis_config)
  r = redis.Redis(connection_pool=pool)
  return r
  

  
If __name__ == "__main__":
  r = get_redis_connect()    #每次调用连接直接用这个就行
  r.set("name", "lingxiangxiang")
  print (r.get("name"))
  

  4.redis管道
  管道
  Redis的管道可以打包一次执行多条redis命令,比如将1000条命令一起发给server端,server端处理将数据放在内存中,当把1000条命令都处理完成后,server端将所有获得的数据都返回给客户端(client)
  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必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多,所以并是不是打包的命令越多越好,具体多少合适需要根据具体情况测试。
  

#!/usr/bin/env python  
# -*- coding:utf-8 -*-
  
import datetime
  
import redis
  

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

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

  
if __name__ == "__main__":
  pool = redis.ConnectionPool(host="192.168.48.131", port=6379, db=0)
  r1 = redis.Redis(connection_pool=pool)
  r2 = redis.Redis(connection_pool=pool)
  start = datetime.datetime.now()
  # print(start)
  withpipe(r1)
  end = datetime.datetime.now()
  # print((end-start).microseconds)
  # print(end-start)
  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 : 28000
  withoutpipe time is : 253000



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-630099-1-1.html 上篇帖子: 开发人员学Linux(12):CentOS7安装配置Memcached和Redis 下篇帖子: 学习Redis必须了解的N个常识
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表