什么是redis?
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
为什么要使用redis?
redis是Nosql数据库,是一个key-value存储系统。虽然redis是key-value的存储系统,但是redis支持的value存储类型是非常的多,比如字符串、链表、集合、有序集合和哈希。
那么为什么要使用类似redis这样的Nosql数据库呢?
- 当数据量的总大小一个机器放不下的时候
- 数据索引一个机器的内存放不下的时候
- 访问量(读写混合)一个实例放不下的时候
单机时代:
存储只用一台机器装mysql,如果每次存储成千上万条数据,这样很会导致mysql的性能很差,存储以及读取速度很慢,然后就演变成缓存+mysql+垂直拆分的方式。
cache作为缓存:
将所有的数据先保存到缓存中,然后再存入mysql中,减小数据库压力,提高效率。但是当数据再次增加到又一个量级,上面的方式也不能满足需求,由于数据库的写入压力增加,缓存只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性。Mysql的master-slave模式成为这个时候的网站标配了。
主从分离模式时代:
在redis的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。
Nosql数据库的优势
- 1)易扩展:这些类型的数据存储不需要固定的模式,无需多余的操作就可以进行横向的扩展。相对于关系型数据库可以减少表和字段特别多的情况。也无型之间在架构的层面上带来了可扩展的能力
- 2)大数据量提高性能
- 3)多样灵活的数据模型
redis特性:
- 速度快
- 持久化
- 多种数据结构
- 支持多种编程语言
- 功能丰富
- 主从复制
- 高可用、分布式
redis通用的一些命令
操作:
127.0.0.1:6379> set name yankerp
OK
127.0.0.1:6379> get name
"yankerp"
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> set name yankerp EX 20
OK
127.0.0.1:6379> get name
"yankerp"
127.0.0.1:6379> ttl name
(integer) 15
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name zhangsan EX 100
OK
127.0.0.1:6379> ttl name
(integer) 96
127.0.0.1:6379> PERSIST name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -1
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> type name
string
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS aaa
(integer) 0
127.0.0.1:6379>
使用python对redis进行操作
导入redis库并连接redis
In [2]: import redis
In [3]: redis.StrictRedis?
Init signature:
redis.StrictRedis(
host='localhost',
port=6379,
db=0,
password=None,
socket_timeout=None,
socket_connect_timeout=None,
socket_keepalive=None,
socket_keepalive_options=None
connection_pool=None,
unix_socket_path=None,
encoding='utf-8',
encoding_errors='strict',
charset=None,
errors=None,
decode_responses=False,
retry_on_timeout=False,
ssl=False,
ssl_keyfile=None,
ssl_certfile=None,
ssl_cert_reqs='required',
ssl_ca_certs=None,
max_connections=None,
)
进行连接操作:
In [6]: import redis
In [7]: redis_client = redis.StrictRedis(host='localhost', port=6379)
In [8]: redis_client
Out[8]: Redis<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>
使用get&&set
In [9]: redis_client.set("name", "yankerp")
Out[9]: True
In [10]: redis_client.get("name")
Out[10]: b'yankerp' # 返回字节
使用redis自增incr
In [11]: redis_client.incr?
Signature: redis_client.incr(name, amount=1)
Docstring:
Increments the value of ``key`` by ``amount``. If no key exists,
the value will be initialized as ``amount``
模拟一个用户访问某个网站访问一次
In [12]: redis_client.incr("yankerp:www.baidu.com")
Out[12]: 1
In [13]: redis_client.incr("yankerp:www.baidu.com")
Out[13]: 2
In [14]: redis_client.incr("yankerp:www.baidu.com")
Out[14]: 3
In [15]: redis_client.incr("yankerp:www.baidu.com")
Out[15]: 4
In [16]: redis_client.incr("yankerp:www.baidu.com")
Out[16]: 5
通过get获取次数
In [18]: redis_client.get("yankerp:www.baidu.com")
Out[18]: b'5'
写一个函数:
def access_count(user, url):
redis_client = ""
try:
redis_client = redis.StrictRedis(host='localhost', port=6379)
if redis_client:
redis_client.incr(user + ":" + url)
access_count = (redis_client.get(user + ":" + url))
print(f"{user}用户访问{url}页面一共访问了{int(access_count)}次....")
except Exception as e:
print("对不起,redis数据库连接失败,请您重试")
运行如下:
In [35]: access_count("zhangsan", "www.baidu.com")
zhangsan用户访问www.baidu.com页面一共访问了2次....
In [36]: access_count("zhangsan", "www.baidu.com")
zhangsan用户访问www.baidu.com页面一共访问了3次....
In [37]: access_count("zhangsan", "www.baidu.com")
zhangsan用户访问www.baidu.com页面一共访问了4次....
In [38]: access_count("zhangsan", "www.baidu.com")
zhangsan用户访问www.baidu.com页面一共访问了5次....
In [39]: access_count("zhangsan", "www.taobao.com")
zhangsan用户访问www.taobao.com页面一共访问了1次....
In [40]: access_count("zhangsan", "www.taobao.com")
zhangsan用户访问www.taobao.com页面一共访问了2次....
In [41]: access_count("zhangsan", "www.taobao.com")
zhangsan用户访问www.taobao.com页面一共访问了3次....
异常效果:
In [43]: access_count("zhangsan", "www.taobao.com")
对不起,redis数据库连接失败,请您重试
做一个查询函数:
def query(user, url):
redis_client = ""
try:
redis_client = redis.StrictRedis(host='localhost', port=6379)
if redis_client:
access_count = (redis_client.get(user + ":" + url))
if access_count:
print(f"{user}用户访问{url}页面一共访问了{int(access_count)}次....")
else:
print(f"{user}用户没有访问过{url}页面....")
except Exception as e:
print(e)
运行如下:
In [55]: query("yankai","www.baidu.com")
yankai用户访问www.baidu.com页面一共访问了4次....
In [56]: query("wangwu","www.baidu.com")
wangwu用户没有访问过www.baidu.com页面....
In [57]: query("yankerp","www.baidu.com")
yankerp用户访问www.baidu.com页面一共访问了5次....
In [58]: query("yankerp","www.taobao.com")
yankerp用户没有访问过www.taobao.com页面....
redis模拟缓存:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/5/9 18:26
# @Author : YanZanG
# @File : redis.py
# @Function: -----------
import time
import json
import redis
def get_data():
"""获取数据
1.从mysql中获取
2.从其他的一些接口获取数据
"""
data = {'iphone': ['iphone6', 'iphone7', 'iphone8'], 'Android': ['oppo', 'vivo']}
time.sleep(5)
return data
def show_data(data):
"""显示数据内容
"""
for k, v in data.items():
print(f"{k} : {v}")
def set_redis(k, data):
"""将数据加入到缓存中
"""
try:
# client = Client(('172.20.10.7', 11211))
client = redis.StrictRedis(host='localhost', port=6379)
client.set(k, json.dumps(data))
return True
except Exception as e:
print(e)
return False
def get_redis(k):
"""获取redis数据
"""
try:
# client = Client(('172.20.10.7', 11211))
client = redis.StrictRedis(host='localhost', port=6379)
return json.loads(client.get(k))
except Exception as e:
print(e)
return False
def main():
"""入口函数
"""
k = "Phone_menu"
result = get_redis(k)
if result:
print("这是从缓存中取数据")
show_data(result)
else:
print("这是从数据库取数据")
data = get_data()
show_data(data)
set_redis(k, data)
main()
将缓存存入不同的库
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/5/7 18:26
# @Author : YanZanG
# @File : redis.py
# @Function: -----------
import time
import json
import redis
def get_data(data_type="phone"):
"""获取数据
1.从mysql中获取
2.从其他的一些接口获取数据
"""
data = None
if data_type == "phone":
data = {'iphone': ['iphone6', 'iphone7', 'iphone8'], 'Android': ['oppo', 'vivo']}
elif data_type == "tv":
data = {'leveo': ['le001', 'le002', 'le003'], 'dell': ['dell1', 'dell2']}
time.sleep(5)
return data
def show_data(data):
"""显示数据内容
"""
for k, v in data.items():
print(f"{k} : {v}")
def set_redis(k, data, data_type="phone"):
"""将数据加入到缓存中
"""
client = None
try:
if data_type == "phone":
print("存入0号库......")
client = redis.StrictRedis(host='localhost', port=6379, db=0)
elif data_type == "tv":
print("存入1号库......")
client = redis.StrictRedis(host='localhost', port=6379, db=1)
client.set(k, json.dumps(data))
return True
except Exception as e:
print(e)
return False
def get_redis(k, data_type="phone"):
"""获取redis数据
"""
redis_type = {
'phone' : 0,
'tv' : 1
}
try:
client = redis.StrictRedis(host='localhost', port=6379, db=redis_type[data_type])
return json.loads(client.get(k))
except Exception as e:
print(e)
return False
def main():
"""入口函数
"""
k = "Phone_menu"
result = get_redis(k, data_type='tv')
if result:
print("这是从缓存中取数据")
show_data(result)
else:
print("这是从数据库取数据")
data = get_data(data_type="tv")
show_data(data)
set_redis(k, data, data_type='tv')
main()
#----------------------------------------
这是从数据库取数据
leveo : ['le001', 'le002', 'le003']
dell : ['dell1', 'dell2']
存入1号库......
# ---------------------------------------
这是从缓存中取数据
leveo : ['le001', 'le002', 'le003']
dell : ['dell1', 'dell2']
# -------------------------------0号库
这是从数据库取数据
iphone : ['iphone6', 'iphone7', 'iphone8']
Android : ['oppo', 'vivo']
存入0号库......
# -------------------------------------------
这是从缓存中取数据
iphone : ['iphone6', 'iphone7', 'iphone8']
Android : ['oppo', 'vivo']