30. Pytnon NoSQL简介 Redis服务搭建、连接池、管道

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:

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

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

  1. 性能NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
  2. 可扩展性同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
    关系型数据库的优势:
  3. 复杂查询可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
  4. 事务支持使得对于安全性能很高的数据访问要求得以实现。对于这两类数据库,对方的优势就是自己的弱势,反之亦然。但是近年来这两种数据库都在向着另外一个方向进化。
    例如: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



本文转自 听丶飞鸟说 51CTO博客,原文链接:http://blog.51cto.com/286577399/2044081

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
NoSQL Java 关系型数据库
mysql和redis连接池
mysql和redis连接池
25 0
|
4月前
|
存储 NoSQL 关系型数据库
什么是NoSQL?什么是redis?redis是做什么的?
什么是NoSQL?什么是redis?redis是做什么的?
37 1
|
4月前
|
关系型数据库 MySQL Java
mysql连接池和redis连接池的实现
mysql连接池和redis连接池的实现
46 0
|
2月前
|
弹性计算 NoSQL Redis
阿里云ECS使用docke搭建redis服务
阿里云ECS使用docke搭建redis服务
158 1
|
4月前
|
关系型数据库 MySQL Java
mysql连接池和redis连接池
mysql连接池和redis连接池
123 0
|
3月前
|
NoSQL Java 数据库连接
springboot整合Redis中连接池jedis与lettuce的对比和实现
springboot整合Redis中连接池jedis与lettuce的对比和实现
373 0
|
2天前
|
监控 NoSQL 关系型数据库
Redis 事务 与 管道
Redis 事务 与 管道
7 0
|
21天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
311 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
29天前
|
存储 缓存 NoSQL
Redis使用管道实现批量处理
Redis使用管道实现批量处理
39 0
|
2月前
|
存储 NoSQL 前端开发
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—实战篇)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—实战篇)
12 0