安装
sudo apt-get install redis-server
开启服务
sudo service redis start
关闭服务
sudo service rdis stop
配置文件
/etc/redis/redis.conf
默认端口:6379
每隔15分钟更新一条数据至物理存储:save 900 1
每隔5分钟更新十条数据至物理存储:save 300 10
每隔60分钟更新10000条数据至物理存储:save 60 10000
需注释掉bind行,或者指定bind IP
获取帮助:
连接Redis
redis-cli
数据操作
- redis是key-value的数据,所以每个数据都是一个键值对
- 键的类型是字符串
值的类型分为五种:
- 字符串string
- 哈希hash
- 列表list
- 集合set
- 有序集合zset
help @值类型
help 方法
string
- string是redis最基本的类型
- 最大能存储512MB数据
- string类型是二进制安全的,即可以为任何数据,比如数字、图片、序列化对象等
新增:
SET key vale ##当key一样时,新值会覆盖掉旧值
如果存在则不创建:
SET key value NX
如果存在则创建:
SET key value XX
设置数据过期时间(单位为秒):
SET key 时间 value
获取:
GET key127.0.0.1:6379> set name 'hello' OK 127.0.0.1:6379> get name "hello" 127.0.0.1:6379>
MGET key1 key2
127.0.0.1:6379> set age 18 OK 127.0.0.1:6379> mget name age 1) "hello" 2) "18"
运算 :
INCR key number 值必须为整数型,每次执行,增加1
127.0.0.1:6379> set age 18 OK 127.0.0.1:6379> incr age (integer) 19 127.0.0.1:6379> incr age (integer) 20 127.0.0.1:6379> incr age (integer) 21DECR key 值必须为整数型,每次执行,减少1
其它:
APPEND key value 追加值127.0.0.1:6379> get name "hello" 127.0.0.1:6379> APPEND name ' python' (integer) 12 127.0.0.1:6379> GET name "hello python"STRLEN key 获取值长度
127.0.0.1:6379> STRLEN name (integer) 12
EXISTS key 判断建知否存在,若存在返回1 不存在则放回0
127.0.0.1:6379> EXISTS name (integer) 1 127.0.0.1:6379> EXISTS nokey (integer) 0
KEYS * 查看当前所有的键
127.0.0.1:6379> KEYS * 1) "age" 2) "name"DEL key 删除键,若创建时,无删除时间,则用DEL删除
TTL key 查询键的删除时间
Hash:
hash用于存储对象,对象的格式为键值对
新增:
HSET key field value 新增一个值的hash对象
127.0.0.1:6379> HSET TestHash name hash (integer) 1
HSET key field [value1,values2....]
127.0.0.1:6379> HSET Nhash name [nhash1,nhash2,nhash3] (integer) 1
获取:
HGET key field 获取一个值的hash
127.0.0.1:6379> HGET TestHash name "hash"HMGET key field 获取多个值的hash
127.0.0.1:6379> HMGET Nhash name 1) "[nhash1,nhash2,nhash3]"HMGET key 获取属性和值
HKEYS key 获取所有的属性
HLEN key 返回包含属性的个数
HVALS key 获取所有值
其它:
- 判断属性是否存在
HEXISTS key field
- 删除属性及值
HDEL key field [field ...]
- 返回值的字符串长度
HSTRLEN key field
list
- 列表的元素类型为string
- 按照插入顺序排序
- 在列表的头部或者尾部添加元素
新增:
LPUSH key value [value ...] #在列表头部添加值
RPUSH key value [value ...] #在列表尾部添加值
LINSERT key BEFORE|AFTER pivot value #在一个元素的前后添加值
127.0.0.1:6379> LPUSH l1 python (integer) 1 127.0.0.1:6379> RPUSH l1 unix (integer) 2 127.0.0.1:6379> LINSERT l1 AFTER 'unix' 'centos' (integer) 3
获取:
LRANGE key start stop
- 返回存储在 key 的列表里指定范围内的元素
- start 和 end 偏移量都是基于0的下标
- 偏移量也可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
127.0.0.1:6379> LRANGE l1 0 -1 1) "python" 2) "unix" 3) "centos"
- 返回存储在 key 里的list的长度
LLEN key
- 返回列表里索引对应的元素
LINDEX key index
127.0.0.1:6379> LLEN l1 (integer) 3 127.0.0.1:6379> LINDEX l1 1 "unix"
- 移除并且返回 key 对应的 list 的第一个元素
LPOP key
- 移除并返回存于 key 的 list 的最后一个元素
RPOP key
127.0.0.1:6379> LPOP l1 "python" 127.0.0.1:6379> LPOP l1 "unix" 127.0.0.1:6379> LPOP l1 "centos" 127.0.0.1:6379> LRANGE l1 0 -1 (empty list or set)
set:
- 无序集合
- 元素为string类型
- 元素具有唯一性,不重复
新增:
- 添加元素
SADD key member [member ...]
获取:
- 返回key集合所有的元素
SMEMBERS key
- 返回集合元素个数
SCARD key
127.0.0.1:6379> SADD set1 test1,test2,test3,test4,test5 (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "test1,test2,test3,test4,test5" 127.0.0.1:6379> SCARD set1 (integer) 1
其它
- 求多个集合的交集
SINTER key [key ...]
- 求某集合与其它集合的差集
SDIFF key [key ...]
- 求多个集合的合集
SUNION key [key ...]
- 判断元素是否在集合中
SISMEMBER key member
redis> SADD key1 "a" (integer) 1 redis> SADD key1 "b" (integer) 1 redis> SADD key1 "c" (integer) 1 redis> SADD key2 "c" (integer) 1 redis> SADD key2 "d" (integer) 1 redis> SADD key2 "e" (integer) 1 redis> SINTER key1 key2 1) "c" redis>
zset
- sorted set,有序集合
- 元素为string类型
- 元素具有唯一性,不重复
- 每个元素都会关联一个double类型的score,表示权重,通过权重将元素从小到大排序
- 元素的score可以相同
命令
设置
- 添加
ZADD key score member [score member ...]
获取
- 返回指定范围内的元素
ZRANGE key start stop
127.0.0.1:6379> ZADD zset1 1 test1 2 test2 3 test3 (integer) 3
- 返回元素个数
ZCARD key
127.0.0.1:6379> ZCARD zset1 (integer) 3
- 返回有序集key中,score值在min和max之间的成员
ZCOUNT key min max
127.0.0.1:6379> ZRANGE zset1 0 2 1) "test1" 2) "test2" 3) "test3"
- 返回有序集key中,成员member的score值
ZSCORE key member
127.0.0.1:6379> ZSCORE zset1 test1 "1"
发布订阅
- 发布者不是计划发送消息给特定的接收者(订阅者),而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅
- 订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的
- 发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑
- 客户端发到频道的消息,将会被推送到所有订阅此频道的客户端
- 客户端不需要主动去获取消息,只需要订阅频道,这个频道的内容就会被推送过来
消息的格式
- 推送消息的格式包含三部分
- part1:消息类型,包含三种类型
- subscribe,表示订阅成功
- unsubscribe,表示取消订阅成功
- message,表示其它终端发布消息
- 如果第一部分的值为subscribe,则第二部分是频道,第三部分是现在订阅的频道的数量
- 如果第一部分的值为unsubscribe,则第二部分是频道,第三部分是现在订阅的频道的数量,如果为0则表示当前没有订阅任何频道,当在Pub/Sub以外状态,客户端可以发出任何redis命令
- 如果第一部分的值为message,则第二部分是来源频道的名称,第三部分是消息的内容
命令
- 订阅
SUBSCRIBE 频道名称 [频道名称 ...]
- 取消订阅
- 如果不写参数,表示取消所有订阅
UNSUBSCRIBE 频道名称 [频道名称 ...]
- 发布
PUBLISH 频道 消息
安装包
- 联网安装
sudo pip install redis
- 使用源码安装
unzip redis-py-master.zip
cd redis-py-master
sudo python setup.py install
交互代码
- 引入模块
import redis
- 连接
try:
r=redis.StrictRedis(host='localhost',port=6379)
except Exception,e:
print e.message
- 方式一:根据数据类型的不同,调用相应的方法,完成读写
- 更多方法同前面学的命令
r.set('name','hello')
r.get('name')
- 方式二:pipline
- 缓冲多条命令,然后一次性执行,减少服务器-客户端之间TCP数据库包,从而提高效率
pipe = r.pipeline()
pipe.set('name', 'world')
pipe.get('name')
pipe.execute()
封装
- 连接redis服务器部分是一致的
- 这里将string类型的读写进行封装
import redis
class RedisHelper():
def __init__(self,host='localhost',port=6379):
self.__redis = redis.StrictRedis(host, port)
def get(self,key):
if self.__redis.exists(key):
return self.__redis.get(key)
else:
return ""
def set(self,key,value):
self.__redis.set(key,value)
Python、Redis、,Mysql实例
实现用户登录,从redis中先查询,若redis中无数据,则查找mysql数据库,并对用户密码进行sha1加密
from pymysql import * from redis import * from hashlib import sha1 #定义mysql类 class Mysql_work(object): def __init__(self,host,user,passwd,db,port=3306,charset='utf8'): try: #连接数据库 self.clinet = connect(host,user,passwd,db,port,charset) except Exception: print("Mysql on client") #封装,私有方法用于增、删、改 def __work(self,sql,parmary): try: #获取游标 work_client = self.clinet.cursor() #执行sql语句,parmary接收列表,用于填充sql中%s的占位值 result = work_client.execute(sql,parmary) #默认开启事务,即执行sql后需要执行commit self.clinet.commit() #关闭游标 work_client.close() print('OK') #返回数据库受影响的值:0.1.2.3.4.5.6.7条数 return result except Exception: print("Error") #更新 def update(self,sql,parmary=[]): return self.__work(sql,parmary) #新增 def insert(self,sql,parmary=[]): return self.__work(sql,parmary) #删除 def delect(self,sql,parmary=[]): return self.__work(sql,parmary) #查找 def select(self,sql,parmary = []): try: work_client = self.clinet.cursor() work_client.execute(sql, parmary) #用于接收查看到的数据 result = work_client.fetchall() # print(result) work_client.close() #返回出查找到的数据 return result except Exception: print("Error") #关闭数据库连接 def close(self): self.clinet.close() class Redis_work(object): #连接redis def __init__(self,host='localhost',port=6379): try: self.__redisClient = StrictRedis(host,port) except Exception: print('Redis no client') #get redis的中值 def Get(self,values): #判断reids中是否有对应的键,如果有返回1(True),如果没有返回0(False) if self.__redisClient.exists(values): return self.__redisClient.get(values).decode('utf-8') else: #返回空字符串,空为False return '' #set Redis中的数据 def Set(self,key,values): self.__redisClient.set(key,values) #定义密码hash加密 class Sha1(object): def __init__(self): #创建sha1加密对象 self.s = sha1() def encryption(self,values): #使用sha1 编码后加密 self.s.update(values.encode('utf-8')) #获取加密后的值 result = self.s.hexdigest() return result def main(): user1 = input("请输入账号:") passwd1 = input("请输入密码:") #对密码进行sha1加密 passwdHash = Sha1() passwd2 = passwdHash.encryption(passwd1) #连接redis redisStart = Redis_work(host='192.168.5.154',port=6379) #查询redis是否有数据 redis_result = redisStart.Get(user1) #判断从redis中是否有返回值,空为false,非空为true if redis_result: if passwd2 == redis_result: print('登录成功') else: print('密码错误') else: #连接mysql mysqlStart = Mysql_work('192.168.5.154', 'root', '0p-0p-0p-', 'python3') #sql语句 sql = "select username,passwd from users where username = %s " #sql语句中占位值,用户输入 parmary = [user1] #执行sql语句 mysql_result = mysqlStart.select(sql, parmary) #关闭sql连接 mysqlStart.close() #判断sql查出的值是否为空,空为false,没有对应用户,如果有值,则判断密码是否正确 if mysql_result: #判断密码是否正确 if passwd2 == mysql_result[0][1]: #向redis中添加缓存 redisStart.Set(user1, passwd2) print("登录成功") else: print('登录失败') if __name__ == '__main__': main()