python访问redis

首先看个案例
无论是电商网站还是支付系统,都离不开数据的存储和增删改查,在这种情况下,每一次登录、访问等都会访问,这样会给数据库造成很大的压力,当数据库无法支撑过高的访问量,轻则影响用户体验,重则导致数据库宕机,网站无法访问。
如何解决数据库压力过大的问题呢?

  1. 优化应用程序,减少数据库的连接数,尽量使用数据库连接池。
  2. 使用消息队列,常见的有RabbitMQ,ActiveMQ,Kafka,RocketMQ等。
  3. 通过使用redis等缓存数据,分担数据库读压力,同时直接从内存读数据速度更快。

下面主要针对redis等nosql数据库进行介绍。

nosql介绍

特征

对于NoSQL并没有一个明确的范围和定义,但是他们都普遍存在下面一些共同特征:

  1. 不需要预定义模式:不需要事先定义数据模式,预定义表结构。数据中的每条记录都可能有不同的属性和格式。当插入数据时,并不需要预先定义它们的模式。
  2. 无共享架构:相对于将所有数据存储的存储区域网络中的全共享架构。NoSQL往往将数据划分后存储在各个本地服务器上。因为从本地磁盘读取数据的性能往往好于通过网络传输读取数据的性能,从而提高了系统的性能。
  3. 弹性可扩展:可以在系统运行的时候,动态增加或者删除结点。不需要停机维护,数据可以自动迁移。
  4. 分区:相对于将数据存放于同一个节点,NoSQL数据库需要将数据进行分区,将记录分散在多个节点上面。并且通常分区的同时还要做复制。这样既提高了并行性能,又能保证没有单点失效的问题。
  5. 异步复制:和RAID存储系统不同的是,NoSQL中的复制,往往是基于日志的异步复制。这样,数据就可以尽快地写入一个节点,而不会被网络传输引起迟延。缺点是并不总是能保证一致性,这样的方式在出现故障的时候,可能会丢失少量的数据。
  6. BASE:相对于事务严格的ACID特性,NoSQL数据库保证的是BASE特性。BASE是最终一致性和软事务。
    NoSQL数据库并没有一个统一的架构,两种NoSQL数据库之间的不同,甚至远远超过两种关系型数据库的不同。可以说,NoSQL各有所长,成功的NoSQL必然特别适用于某些场合或者某些应用,在这些场合中会远远胜过关系型数据库和其他的NoSQL

    常用的nosql数据库

    临时性键值存储|永久性键值存储|面向文档的数据库|面向列的数据库
    -|:-:|:-:|:-:|
    Memcached|Tokyo Tyrant|MangoDB|Cassandra
    Redis|Flare|CouchDB|HBase
     |ROMA||HyperTable
     |Redis||

    redis安装和配置

    安装

    redis主要用于linux下,下面centos7下面安装最新版本redis-4.0.9。
    1
    2
    3
    4
    5
    wget http://download.redis.io/releases/redis-4.0.9.tar.gz
    tar xzf redis-4.0.9.tar.gz
    cd redis-4.0.9/
    make
    cd src && make all

配置

redis可以单机多实例,通过修改配置文件,不同实例使用不同的配置文件和端口号即可。
下面配置文件统一存放在conf目录中。

1
2
3
4
5
cd /usr/local/src/   
mv redis-4.0.9 redis #目录重命名,取消版本信息
cd redis
mkdir conf #新建配置文件目录,统一存放配置文件
cp redis.conf conf/redis_6379.conf #配置文件,以端口号命名

修改redis_6379.conf文件,默认该配置项为no,修改为yes。
该参数表示是否使用守护线程的方式启动。
当设置为yes时,表示开启守护进程模式。该模式下,redis在后台运行,并将进程pid写入至配置文件中设置的pidfile中,此时redis将一直运行,除非手动kill该进程。
当设置为no时,当前界面将进入redis的命令行界面,ctrl+c强制退出或者关闭连接工具都会导致redis进程退出。

1
daemonize yes

启动

1
redis-server /usr/local/src/redis/conf/redis_6379.conf

确认是否启动
通过进程确认

1
2
3
[root@VM_0_4_centos conf]# ps aux|grep redis
root 25841 0.0 0.1 141772 1976 ? Ssl 23:26 0:00 redis-server 127.0.0.1:6379
root 25856 0.0 0.0 112644 964 pts/1 R+ 23:26 0:00 grep --color=auto redis

通过端口号确认

1
2
[root@VM_0_4_centos conf]# netstat -lntp |grep 6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 25841/redis-server

错误信息说明

  • 未安装gcc编译工具
    redis基于C语言编写,需要使用gcc等编译工具,若未安装,在make编译过程中会报错。使用yum install gcc安装,默认会安装gcc及对应的依赖包即可。
  • 未安装jemalloc
    默认情况下redis的memory allocatorjemalloc,若未安装会出现下面报错信息
    1
    2
    3
    4
    5
    6
    7
    zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
    #include <jemalloc/jemalloc.h>
    ^
    compilation terminated.
    make[1]: *** [adlist.o] Error 1
    make[1]: Leaving directory `/usr/local/src/redis-4.0.9/src'
    make: *** [all] Error 2

可以设置使用libc malloc,编译的时候使用make MALLOC=libc即可。
具体更多内容可以参见redis解压目录下的redis.MD文件中Allocator部分。

  • 异机连接端口不通
    在redis配置文件中,默认情况下bing 127.0.0.1,也就是仅允许本机连接。当通过其他机器连接的时候会出现无法连接的情况。
    修改redis配置文件,将bing 127.0.0.1修改为bind 0.0.0.0,然后重启redis-server服务。

    redis数据类型

    redis支持5种数据类型,分别是String(字符串)、List(列表)、Hash(字典)、Set(集合)、Sorted Set(有序集合)。
    本质上来说,redis存储的是key-value对,其中key是字符串,对应的value类型决定了redis的数据类型。
  • String(字符串)
    string是redis最基本的类型,其基本模型也是一个key对应一个value。
    string类型是二进制安全的。也就是说redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
    string类型是Redis最基本的数据类型,一个键最大能存储512MB。

    1
    2
    3
    4
    127.0.0.1:6379> SET name "xiaohh"
    OK
    127.0.0.1:6379> GET name
    "xiaohh"
  • List(列表)
    Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    127.0.0.1:6379> lpush xiaohh redis
    (integer) 1
    127.0.0.1:6379> lpush xiaohh mongodb
    (integer) 2
    127.0.0.1:6379> lpush xiaohh rabitmq
    (integer) 3
    127.0.0.1:6379> lrange xiaohh 0 2
    1) "rabitmq"
    2) "mongodb"
    3) "redis"
  • Hash(字典)
    Redis hash 是一个键值(key=>value)对集合。
    Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

    1
    2
    3
    4
    5
    6
    127.0.0.1:6379> HMSET myhash fileld1 "Hello" fileld2 "World"
    OK
    127.0.0.1:6379> HGET myhash fileld1
    "Hello"
    127.0.0.1:6379> HGET myhash fileld2
    "World"
  • Set(集合)
    Redis的Set是string类型的无序集合。
    集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    27.0.0.1:6379> sadd type redis
    (integer) 1
    127.0.0.1:6379> sadd type mongodb
    (integer) 1
    127.0.0.1:6379> sadd type rabbitmq
    (integer) 1
    127.0.0.1:6379> sadd type rabbitmq
    (integer) 0
    127.0.0.1:6379> smembers type
    1) "rabbitmq"
    2) "mongodb"
    3) "redis"

由于Set中元素具有唯一性的,所以重复添加的rabbitmq只有一个,第二次添加将被忽略。

  • Sorted Set(有序集合)
    Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
    不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
    zset的成员是唯一的,但分数(score)却可以重复。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    127.0.0.1:6379> zadd  type1 0 redis
    (integer) 1
    127.0.0.1:6379> zadd type1 3 mongodb
    (integer) 1
    127.0.0.1:6379> zadd type1 2 rabbitmq
    (integer) 1
    127.0.0.1:6379> zadd type1 2 rabbitmq
    (integer) 0
    127.0.0.1:6379> ZRANGEBYSCORE type1 0 10
    1) "redis"
    2) "rabbitmq"
    3) "mongodb"

python访问redis

python访问redis需要安装对应的redis包。

1
pip install redis

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

1
2
3
4
5
6
import redis

pool = redis.ConnectionPool(host="118.24.18.158", port="6379")
r = redis.Redis(connection_pool=pool)
r.set("name", "xiaohh")
print(r.get("name")) #输出结果:"xiaohh"

通过python对redis数据库进行操作,首先建立redis的连接,然后对不同的数据类型采用不同的方法进行操作。
具体操作方法点击python访问redis查看。
更多redis相关内容可以点击查看官方文档

Recommended Posts