一、Redis 介绍
redis是业界主流的key-value nosql 数据库之一。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis优点:
- 异常快速 : Redis是非常快的,每秒可以执行大约110000设置操作,81000个/每秒的读取操作。
- 支持丰富的数据类型 : Redis支持最大多数开发人员已经知道如列表,集合,可排序集合,哈希等数据类型。这使得在应用中很容易解决的各种问题,因为我们知道哪些问题处理使用哪种数据类型更好解决。
- 操作都是原子的 : 所有 Redis 的操作都是原子,从而确保当两个客户同时访问 Redis 服务器得到的是更新后的值(最新值)。
- MultiUtility工具:Redis是一个多功能实用工具,可以在很多如:缓存,消息传递队列中使用(Redis原生支持发布/订阅),在应用程序中,如:Web应用程序会话,网站页面点击数等任何短暂的数据;
安装Redis环境:
要在 Ubuntu 上安装 Redis,打开终端,然后输入以下命令:
$sudo apt-get update
$sudo apt-get install redis-server
这将在您的计算机上安装Redis
启动 Redis
$redis-server
查看 redis 是否还在运行
$redis-cli
这将打开一个 Redis 提示符,如下图所示:
redis 127.0.0.1:6379>
在上面的提示信息中:127.0.0.1 是本机的IP地址,6379是 Redis 服务器运行的端口。现在输入 PING 命令,如下图所示:
redis 127.0.0.1:6379> ping
PONG
这说明现在你已经成功地在计算机上安装了 Redis。
二、python操作redis
2.1、安装redis模块
sudo pip install redis
or
sudo easy_install redis
or
源码安装
详见:https://github.com/WoLpH/redis-py
2.2、连接方式
①逻辑图
②操作模式
redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。
import redis
r = redis.Redis(host='localhost', port=6379)
r.set('foo', 'Bar')
print r.get('foo')
③连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
import redis
pool = redis.ConnectionPool(host="localhost",port=6379)
r = redis.Redis(connection_pool=pool)
r.set('foo','bar')
print(r.get('foo')) #打印出来的是bytes类型,因为在python3中,通过socket的都是bytes类型
三、python操作
3.1、String操作
redis中的String在在内存中按照一个name对应一个value来存储。如图:
3.2、操作方式
1、set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中设置值,默认,不存在则创建,存在则修改
参数:
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行
xx,如果设置为True,则只有name存在时,岗前set操作才执行
redis命令操作:
127.0.0.1:6379> set age 22 #设置age为22
OK
127.0.0.1:6379> set age 22 ex 2 #设置age为22,过期时间为2秒
OK
127.0.0.1:6379> set age 23
OK
127.0.0.1:6379> set age 24 nx #当age的值已经存在,则无法重新设置新的值
(nil)
127.0.0.1:6379> get age
"23"
127.0.0.1:6379> set age 24 xx #当age的值已经存在,则才能重新设置新的值
OK
127.0.0.1:6379> get age
"24"
2、setnx(name, value)
设置值,只有name不存在时,执行设置操作(添加),相当于set name zhangqigao nx
3、setex(name, value, time)
# 设置值
# 参数:
# time,过期时间(数字秒 或 timedelta对象)
#相当于 set name zhangqigao ex 2
4、psetex(name, time_ms, value)
# 设置值
# 参数:
# time_ms,过期时间(数字毫秒 或 timedelta对象)
#相当于 set name zhangqigao px 2
5、mset(*args, **kwargs)
批量设置值
如:
mset(k1='v1', k2='v2')
或
mget({'k1': 'v1', 'k2': 'v2'})
redis命令操作:
127.0.0.1:6379[2]> mset name zhangqigao age 22
OK
127.0.0.1:6379[2]> keys *
1) "age"
2) "name"
127.0.0.1:6379[2]> get name
"zhangqigao"
6、get(name)
获取值
redis命令操作:
127.0.0.1:6379> set age 23 #设置age的值为23
OK
127.0.0.1:6379> get age #获取age的值
"23"
7、mget(keys, *args)
批量获取
如:
mget('shuaigaogao', 'gaoxiansheng')
或
r.mget(['shuaigaogao', 'gaoxiansheng'])
8、getset(name, value)
设置新值并获取原来的值
redis命令操作:
127.0.0.1:6379[1]> set age 23 #设置age的值为23
OK
127.0.0.1:6379[1]> getset age 18 #重新设置age的值为18,并返回原来的值23
"23"
127.0.0.1:6379[1]> get age #获取age当前的值
"18"
9、getrange(key, start, end)
# 获取子序列(根据字节获取,非字符)
# 参数:
# name,Redis 的 name
# start,起始位置(字节)
# end,结束位置(字节)
# 如: "张其高" ,0-3表示 "张"
redis命令操作:
127.0.0.1:6379[1]> set name zhangqigao
OK
127.0.0.1:6379[1]> getrange name 0 1 #获取0到1的字符串,这边相当于切片,但是是顾头又顾尾
"zh"
10、setrange(name, offset, value)
# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
# 参数:
# offset,字符串的索引,字节(一个汉字三个字节)
# value,要设置的值
redis命令操作:
127.0.0.1:6379[1]> get name
"zhangqigao"
127.0.0.1:6379[1]> setrange name 3 m #把字符串中的第3个字符替换成m
(integer) 10
127.0.0.1:6379[1]> get name
"zhamgqigao"
11、setbit(name, offset, value)
# 对name对应值的二进制表示的位进行操作
# 参数:
# name,redis的name
# offset,位的索引(将值变换成二进制后再进行索引)
# value,值只能是 1 或 0
# 注:如果在Redis中有一个对应: n1 = "foo",
那么字符串foo的二进制表示为:01100110 01101111 01101111
所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1,
那么最终二进制则变成 01100111 01101111 01101111,即:"goo"
# 扩展,转换二进制表示:
# source = "武沛齐"
source = "foo"
for i in source:
num = ord(i)
print bin(num).replace('b','')
特别的,如果source是汉字 "武沛齐"怎么办?
答:对于utf-8,每一个汉字占 3 个字节,那么 "武沛齐" 则有 9个字节
对于汉字,for循环时候会按照 字节 迭代,那么在迭代时,将每一个字节转换 十进制数,然后再将十进制数转换成二进制
11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 10010000
-------------------------- ----------------------------- -----------------------------
武 沛 齐
*用途举例,用最省空间的方式,存储在线用户数及分别是哪些用户在线
12、getbit(name, offset)
# 获取name对应的值的二进制表示中的某位的值 (0或1)
13、bitcount(key, start=None, end=None)
# 获取name对应的值的二进制表示中 1 的个数
# 参数:
# key,Redis的name
# start,位起始位置
# end,位结束位置
14、strlen(name)
# 返回name对应值的字节长度(一个汉字3个字节)
redis的操作:
127.0.0.1:6379[1]> get name
"zhamgqigao"
127.0.0.1:6379[1]> strlen name #计算name值得字符串的长度
(integer) 10
15、incr(self, name, amount=1)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
# 参数:
# name,Redis的name
# amount,自增数(必须是整数)
# 注:同incrby
redis的操作:
127.0.0.1:6379[1]> INCR user_name
(integer) 1
127.0.0.1:6379[1]> INCR user_name
(integer) 2
127.0.0.1:6379[1]> INCR user_name
(integer) 3
*用途举例,这个一般用于计算用户的登录的总量的。
16、incrbyfloat(self, name, amount=1.0)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
# 参数:
# name,Redis的name
# amount,自增数(浮点型)
redis的操作:
127.0.0.1:6379[1]> incrbyfloat user_login 1.2
"1.2"
127.0.0.1:6379[1]> incrbyfloat user_login 1.4
"2.6"
17、decr(self, name, amount=1)
# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。
# 参数:
# name,Redis的name
# amount,自减数(整数)
redis的操作:
127.0.0.1:6379[1]> decr user_name
(integer) 2
127.0.0.1:6379[1]> decr user_name
(integer) 1
127.0.0.1:6379[1]> decr user_name
(integer) 0
*用途举例,用于如果用户账户失效,则减去
18、append(key, value)
# 在redis name对应的值后面追加内容
# 参数:
key, redis的name
value, 要追加的字符串
redis的操作:
127.0.0.1:6379[1]> get name
"zhamgqigao"
127.0.0.1:6379[1]> append name xiao #在name值后面追加xiao字符串
(integer) 14
127.0.0.1:6379[1]> get name
"zhamgqigaoxiao"
19、help 变量名
#查看操作的使用方法
redis的操作方法:
127.0.0.1:6379[1]> help set #help 命令
SET key value [EX seconds] [PX milliseconds] [NX|XX] #set命令的用法
summary: Set the string value of a key #作用
since: 1.0.0
group: string #所属类型,是string