1)Redis:REmote DIctionary Server(远程字典服务器)html
2)是彻底开源免费的,用C语言编写的,遵照BSD开源协议,python
是一个高性能的(key/value)分布式内存数据库,基于内存运行,mysql
并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。redis
3)Redis 与其余 key - value 缓存产品有如下三个特色:sql
3.1)Redis支持数据的持久化,能够将内存中的数据保持在磁盘中,重启的时候能够再次加载进行使用数据库
3.2)Redis不只仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储vim
3.3)Redis支持数据的备份,即master-slave模式的数据备份缓存
1)内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务安全
2)取最新N个数据的操做,如:能够将最新的10条评论的ID放在List集合服务器
3)模拟相似于HttpSession这种须要设定过时时间的功能
4)发布、订阅消息系统
5)定时器、计数器
因为企业里面作Redis开发,99%都是Linux版的运用和安装,
几乎不会涉及到Windows版。
安装包括服务端和客户端
在 Ubuntu 系统安装 Redi 可使用如下命令:
sudo apt-get update
sudo apt-get install redis-server
启动 Redis 服务
redis-server
或者
sudo redis-server /etc/redis/redis.conf
使用 redis 客户端查看是否启动
redis-cli
检查是否安装成功
127.0.0.1 是本机 IP ,6379 是 redis 服务端口。如今咱们输入 PING 命令。
以上说明咱们已经成功安装了redis
下载:打开redis官方网站(https://redis.io/),推荐下载稳定版本(stable)
http://www.redis.cn/
解压
tar zxvf redis-3.2.5.tar.gz
复制:推荐放到usr/local目录下
sudo mv -r redis-3.2.5/* /usr/local/redis/
进入redis目录
cd /usr/local/redis/
生成
sudo make
测试
sudo make test
这段运行时间会较长
安装:将redis的命令安装到/usr/bin/目录
sudo make install
启动服务器:在桌面目录
redis-server 或者 sudo redis-server /etc/redis/redis.conf 按ctrl+c中止
启动客户端:在新终端中运行以下代码
redis-cli
运行命令
ping set 'a' '123'
当添加键值后,发如今当前运行的目录下,建立了一个文件:dump.rdb,这个文件用于将数据持久化存储
查看redis的版本有两种方式:
4 1. 查询服务端
redis-server --version
或者
redis-server -v
获得的结果是:
Redis server v=3.0.6 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=687a2a319020fa42
redis-cli --version
或者
redis-cli -v
获得的结果是:redis-cli 3.0.6
严格上说:经过 redis-cli 获得的结果应该是redis-cli 的版本,可是 redis-cli 和redis-server 通常都是从同一套源码编译出的。因此应该是同样的。
在原文件/usr/local/redis目录下,文件redis.conf为配置文件
已经移动到/etc/redis/目录下,文件redis.conf为配置文件
打开配置文件命令:sudo subl /etc/redis/redis.conf
绑定地址:若是须要远程访问,可将此行注释
bind 127.0.0.1
建议不要修改
port 6379
推荐改成yes,以守护进程运行
daemonize no|yes
数据文件
dbfilename dump.rdb
设置数据文件存储路径
dir的默认值为./,表示当前目录
推荐改成:dir /var/lib/redis
注意,删除后,插入数据重启redis服务器才能看到数据库
sudo cp /usr/local/redis/redis.conf /etc/redis/
ps ajx|grep redis
#推荐指定配置文件启动
sudo redis-server /etc/redis/redis.conf
或者
sudo service redis start
sudo kill -9 redis的进程id
或者
sudo service redis stop
sudo service redis restart
当配置文件从新配置后,通常会重启服务器这样配置才生效
redis是key-value的数据,因此每一个数据都是一个键值对
键的类型是字符串
值的类型分为五种:
数据操做的所有命令,
能够查看redis中文网站(http://redis.cn/commands.html)
接下来逐个介绍操做各种型的命令
启动redis服务
sudo redis-server /etc/redis/redis.conf
或者
sudo service redis start
启动客户端:在新终端中运行以下代码
redis-cli
启动后效果如图
1.1.1 设置键值
set key value
SETEX key seconds value
注意,key和值不加引号也能够
MSET key value [key value ...] 案例: mset 'key1' 'hello' 'key2' 'world'
根据键获取值,若是不存在此键则返回nil,get不区分大小写也就是说get和GET均可以获得数据
GET key
MGET key [key ...] 案例 mget 'key1' 'key2'
INCR key
INCRBY key increment
DECR key
DECRBY key decrement
APPEND key value
STRLEN key
KEYS pattern
EXISTS key [key ...]
TYPE key
DEL key [key ...]
为给定 key 设置生存时间,当 key 过时时(生存时间为 0 ),它会被自动删除。
能够对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。没有过时的是-1,过时的是-2
EXPIRE key seconds
查看有效时间,以秒为单位
TTL key
hash用于存储对象,对象的格式为键值对
hash 特别适合用于存储对象。相对于将对象的每一个字段存成单个string 类型。将一个对象
存储在hash 类型中会占用更少的内存,而且能够更方便的存取整个对象。省内存的缘由是
新建一个hash 对象时开始是用zipmap(又称为small hash)来存储的。这个zipmap 其实并
不是hash table,可是zipmap 相比正常的hash 实现能够节省很多hash 自己须要的一些元
数据存储开销。尽管zipmap 的添加,删除,查找都是O(n),可是因为通常对象的field
数量都不太多。因此使用zipmap 也是很快的,也就是说添加删除平均仍是O(1)。若是field
或者value 的大小超出必定限制后,redis 会在内部自动将zipmap 替换成正常的hash 实现.
这个限制能够在配置文件中指定。
hash-max-zipmap-entries 64 #配置字段最多64 个
hash-max-zipmap-value 512 #配置value 最大为512 字节
hset key field value 设置 hash field为指定值,若是 key不存在,则建立
返回值:
若是 field 是哈希表中的一个新建域,而且值设置成功,返回 1 。
若是哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。
HSET key field value
例子:
hset py3 name '郭靖'
HMSET key field value [field value ...]
hmset py4 name 'gj' gender '0'
HGET key field
HMGET key field [field ...]
HGETALL key
HKEYS key
HLEN key
HVALS key
HEXISTS key field
HDEL key field [field ...]
1)列表的元素类型为string
2)按照插入顺序排序
3)在列表的头部或者尾部添加元素
语法和案例
LPUSH key value [value ...]
案例
lpush py5 'abc' 'efg'
查看数据
查看类型
RPUSH key value [value ...]
具体案例
rpush py5 'hij' 'qlm'
查看插入的数据
LINSERT key BEFORE|AFTER pivot value
具体案例:
linsert py5 after 'abc' '123'
LSET key index value
LRANGE key start stop
例如:
lrange py5 2 -1
LPOP key
lpop py5
RPOP key
案例:
ppop py5
LTRIM key start stop
案例:
ltrim py5 1 2
LLEN key
LINDEX key index
1)无序集合
2)元素为string类型
3)元素具备惟一性,不重复
SADD key member [member ...]
例子:
sadd py6 abc 123 defg
SMEMBERS key
例子:获得py6集合全部元素
smembers py6
SCARD key
例如:查看py6集合元素的个数
scard py6
sadd py6 defg 123 abc 456
sadd py7 abc 123 world 456
SINTER key [key ...]
例如:求py6和py7两个集合的交集
sinter py6 py7
SDIFF key [key ...]
例如:从py6中减掉py7中py6也存在的元素
sdiff py6 py7
例如:从py7中减掉py6中py7也存在的元素
sdiff py7 py6
SUNION key [key ...]
例如:
sunion py6 py7
SISMEMBER key member
1)sorted set,有序集合
2)元素为string类型
3)元素具备惟一性,不重复
4)每一个元素都会关联一个double类型的score,表示权重,经过权重将元素从小到大排序
5)元素的score能够相同
ZADD key score member [score member ...]
ZRANGE key start stop
ZCARD key
ZCOUNT key min max
ZSCORE key member
发布者不是计划发送消息给特定的接收者(订阅者),而是发布的消息分到不一样的频道,不须要知道什么样的订阅者订阅。
订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不须要知道什么样的发布者发布的。
发布者和订阅者的解耦合能够带来更大的扩展性和更加动态的网络拓扑。
客户端发到频道的消息,将会被推送到全部订阅此频道的客户端。
客户端不须要主动去获取消息,只须要订阅频道,这个频道的内容就会被推送过来。
select 0
或者
select 1
说明,
SUBSCRIBE 频道名称 [频道名称 ...]
subscribe频道名称 [频道名称 ...]
直接使用Ctrl+c退出也能够取消订阅
UNSUBSCRIBE 频道名称 [频道名称 ...]
或者
unsubscribe 频道名称 [频道名称 ...]
由于订阅平道后当前终端处于阻塞状态,没法输入取出订阅命令,那么在使用Python代码交互的时候,使用该该命令用于取消订阅某个或者一些频道。
PUBLISH 频道 消息
或者
publish 平道 消息
一个master能够拥有多个slave,一个slave又能够拥有多个slave,如此下去,造成了强大的多级服务器集群架构。
好比,将ip为192.168.1.10的机器做为主服务器,将ip为192.168.1.11的机器做为从服务器。
使用vim或者其余文本工具找到redis.conf配置文件
sudo vim /etc/redis/redis.conf
设置主服务器的配置
bind 192.168.1.29
保存退出,而且重启redis服务器
使用vim或者其余文本工具找到redis.conf配置文件
sudo vim /etc/redis/redis.conf
注意:在slaveof后面写主机ip,再写端口,并且端口必须写
bind 192.168.1.91
slaveof 192.168.1.29 6379
保存退出,而且重启redis服务器
在master和slave分别执行info命令,查看输出信息
redis-cli -h 192.168.1.29
set hello world
Slave机器上本身的ip,必定要指定,不然会没有数据
get hello
到中文官网(http://redis.cn/clients.html)查找客户端代码
sudo pip3 install redis
unzip redis-py-master.zip cd redis-py-master sudo python setup.py install
import redis
try: red = redis.StrictRedis(host="192.168.31.114",port=6379) except Exception as e: print(e)
else: #name是key,hello world是值 red.set("name","hello world") #根据key获得值 print(red.get("name"))#b'hello world'
运行效果:
#缓冲多条命令,而后一次性执行,减小服务器-客户端之间TCP数据库包,从而提升效率 pipe = red.pipeline() pipe.set('name', 'world') print(pipe.get('name')) #执行命令 pipe.execute()
模块test.py代码以下:
import redis class RedisHelper(): def __init__(self,host='192.168.31.114',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) if __name__ == "__main__": red = RedisHelper() #name是key,hello world是值 red.set("name","hello world") #根据key获得值 print(red.get("name"))#b'hello world'
业务过程以下:
输入用户名、密码
密码加密
判断redis中是否记录了用户名,若是有则成功
若是redis中没有用户名,则到mysql中查询
从mysql中查询成功后,将用户名记录到redis中
import pymysql import redis class RedisHelp(object): def __init__(self,host="192.168.31.114",port=6379): self.__redis = redis.StrictRedis(host=host,port=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) class MySQLHelp(object): def __init__(self,host): self.host=host self.port=3306 self.user='afu' self.password='123456' self.db='python2' self.charset='utf8' #创建连接 def open(self): self.conn = pymysql.connect( host=self.host, port=self.port, user=self.user, password=self.password, db=self.db, charset=self.charset ) #执行sql语句和查询数据 self.cursor = self.conn.cursor() #关闭连接,释放资源 def close(self): self.cursor.close() self.conn.close() #获得因此数据 def get_all(self,sql,params=[]): result = None try: #打开连接 self.open() self.cursor.execute(sql,params) #获得数据 result = self.cursor.fetchall() return result except Exception as e: print(e) # self.close() return result # 获得因此数据 def get_one(self, sql, params=[]): result = None try: # 打开连接 self.open() self.cursor.execute(sql, params) # 获得数据 result = self.cursor.fetchone() self.close() return result except Exception as e: print(e) return result #增长,删除,修改--提交事务 def cul(self, sql, params=[]): try: # 打开连接 self.open() count = self.cursor.execute(sql, params) # 提交事务 self.conn.commit() self.close() print("执行完毕!") return count except Exception as e: print(e) return None #增长数据 def insert(self,sql,params=[]): return self.cul(sql,params) #删除 def delete(self,sql,params=[]): return self.cul(sql,params) # 修改 def update(self, sql, params=[]): return self.cul(sql, params)
from hashlib import sha1 re = RedisHelp(host="localhost") name = input("请输入登陆帐号:") password = input("请登陆密码:") #加密后的密码 password = sha1(password.encode()).hexdigest() uname = re.get("uname").decode("utf-8") upwd = re.get("upwd").decode("utf-8") print(type(uname)) print(uname == name) if str(uname) == name: if str(upwd) == password: print("登陆成功,数据来自redis数据库") else: print("密码错误,数据来自redis数据库") else: help = MySQLHelp("localhost") #(id,uname,upwd) sql = "select * from userinfos where uname = %s" params = [name] result = help.get_one(sql,params) # print(result) if result == None: print("帐号不存在") else: if result[1] == name and result[2] ==password: print("登陆成功!来自mysql") #保存数据到redis下次可使用 re.set("uname",name) re.set("upwd",password) else: print("密码错误!")
运行结果: