Redis内容
Redis简介
数据库分两类
- 关系型数据库: 数据以虚拟表格的形式存储! mysql,sqlite,oracle,sqlserver,postgresql等...
- 非关系型/面向对象数据库/缓存数据库: 存储的key:value字符串! redis,mongdb,memcache
- 使用最多: redis
- 数据存储在内存中!
特点
- 以字典结构存储数据
- 允许通过TCP协议读取字典的内容
- 强大的缓存系统, 可以为每个键设置TTL, 以及按照一定规则自动淘汰不需要的键
- 支持使用列表的形式构造任务队列
- 数据存储在内存中也可以持久化到硬盘
重点: 存储字符串类型, 是键值对!
安装
- window
解压后直接使用
- 启动服务端 redis-server.exe 2. 启动内置客户端 redis-cli.exe 3. 简单指令
- 图形客户端
# ping 返回 pang 表示成功!
pang
# 设置值
set key value
set name zhangsn
set age lisi
# 获取值
get key
get name
get age
# 查询所有key
keys *
# 设置有效期
setex key senconds value
setex yanzhengma 60 123456 # 表示验证码1分钟之内有效!
文件说明
- redis-benchmark.exe 测redis性能的程序,可以同时模拟N多客户端查询和赋值
- redis-check-aof.exe 更新日志检查–修复日志
- redis-check-dump.exe 本地数据库检查
- redis.conf redis配置文件
- redis-cli.exe 客户端连接 redis服务器工具
- redis-server.exe redis服务器启动程序
配置说明
配置文件: redis.conf/redis.windows.conf
#端口
port 6379
# 允许远程访问
bind:绑定IP地址,只允许来自指定网卡的Redis请求,如果想允许任意地址访问将 bind 注释掉就行。
protected-mode: Redis 安全访护层,默认开启:
关闭protected-mode模式,此时外部网络可以直接访问
开启protected-mode保护模式,需配置bind ip或者设置访问密码# (1) 注释 bind 127.0.0.1
# (2) 如果允许匿名访问,关闭保护模式
protected-mode no
# (3) 如果开启保护模式,必须设置请求密码客户端在连接Redis时需要通过【AUTH 密码】命令提供密码
requirepass 123456 #密码任意
# 设置 Redis 是否以守护进程模式运行。 (允许后台启动) daemonize yes
启动时指定配置文件
cd /usr/local/bin
./redis-server /user/local/etc/redis.conf #指定配置文件启动 (覆盖redis的默认配置)
Reids数据库类型
常用的5种数据类型
- 字符串
- Hash(散列值/对象)
- 集合(Set)
- 有序集合(zset)
- 列表(list)
字符串
# 设置
set name lisi
# 获取
get name
# 删除
del name
# 查询多个
mget name age
# 自增
incr num
#每次num加1! 变量不存在默认就是1
# 自减
decr num
# 长度
strlen name
# 是否存在
exists name
Hash
Hashhash存储对象
工作中使用: 存储各种列表:商品列表.新闻列表,购物车列表.....
# 设置
# HSET key field valueHGET key field
# HMSET key field value [field value …] 多个属性
# HMGET key field [field …]HGETALL key
hset car price 500
hmset car price 500 name baoma
# 获取
hget 对象名 字段
hget car price
hmget car name price
Redis实现缓存
key:value内存数据集,把k:v值保存在内存中,系统访问非常快,是一种内存数据库.内置多种类型,秒杀系统用
到list(排队,队列处理) 库存和界面数据(String)
优缺对比
支持持久化,类型丰富,支持备份,支持集群支持动态添加服务器,内存超出自动保存到磁盘
缺点:单线程,性能略低
- redis与memcache的优缺点
- Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的
时候可以再次加载进行使用 - Redis不仅仅支持简单的string类型的数据,同时还提供list,set,hash
等数据结构的存储 - Redis支持数据的备份,即master-slave模式的数据备份
内存超出时redis将不常用缓存swap到磁盘 - redis支持集群,添加节点删除节点不丢数据
- redis是单线程
使用场景
缓存,集群session一致,聊天室.任务队列,排行榜,收藏夹等, 访问统计
redis应用场景
- 缓存
- 分布式集群架构中的session分离
- 聊天室的在线好友列表
- 任务队列。(秒杀、抢购 、12306等等)
- 应用排行榜
- 网站访问统计
- 数据过期处理(可以精确到毫秒)
安装
下载windows版,解压
https://github.com/MicrosoftArchive/redis/releases
- 文件介绍
- redis-benchmark.exe #性能测试
- redis-check-aof.exe # aof更新日志检测
- redischeck-dumps.exe # 本地数据库检查
- redis-cli.exe # 客户端
- redis-service.exe # 服务器
- redis.windows.conf #配置文件
- 启动Redis服务
window运行(快捷键 shift+鼠标右键).选择在此打开命令窗口,进入cmd操作系统窗口
# 启动redis服务
redis-server.exe redis.window.conf
# window建议做成*.bat批处理文件
# linux 做成shell 脚本 *.sh
- 客户端链接
进入cmd操作系统窗口
#运行
redis-cli.exe
#如果多服务器时,需要指定端口
redis-cli.exe -h 127.0.0.0.1 -p 6379
# 做成批处理
常用指令
事务
redis事务只是原子性操作,无回滚.一次性可以执行多个命名,只是把多个步骤联合为一个整体,内部按照顺
序来执行.
三个阶段:
- 开始事务multi
- 命令入队(redis指令)
- 执行事务 exec
管道Pipeline
管道是批量执行命令可提高执行效率
管道Pipeline
python中可通过管道Pipeline结合MULTI、EXEC实现Redis事务
Pipeline:批量操作命令
当我们要使用事务时:
首先实例化一个Pipeline类,可以先实例化StrctRedis类,然后调用实例
的pipeline()方法;
也可以直接实例化Pipeline类。两种方法都会创建BasePipeLine实例
Redis事务中对应的MULTI、EXEC、DISCARD、WATCH操作都对应到
BasePipeLine中的相应方法
# 1
redis = Redis(host='127.0.0.1',port=6379)
pipe = redis.pipeline()
# 2 pipe = Pipeline(host='127.0.0.1',port=6379)
pipe.对应方法() #watch监控key,如果key被改动,事务将被打断
程序使用
redis实现秒杀修改库存,构建队列
Redis实现秒杀修改库存
比如:修改库存(key,产品id,用户id,库存,价格)
# 秒杀修改库存(key,商品id,用户id,数量,价格)
def update_store(key,productid,userid,qty,price):
qty=int(qty)
# 实例化pipline
with sec_redis.pipeline() as pipe:
i = 0
# 10次机会(很多人会修改key,当别人修改时,事务就不会执行了.所以多给几次机会)
cart_key = 'cart:{}',format(userid)
while i<10:
try:
#关注一个key,watch字面含义就是监视的意识,这里可以看做数据库乐观锁的概念,谁都 可以读,谁都可以修改,但是修改的人必须保证自己watch的数据没有被别人修改过,否则就修改失败了
pipe.watch(key)
item = "%s-%s-%s-%s"%(userid,productid,qty,price)
# 缓存中取出数量,大于qty就开始
count = int(pipe.get(key))
if count >= qty: #有库存
#事务开始
pipe.multi()
# 剩余库存=库存-数量
remainqty= count-qty
pipe.set(key,remainqty)
pipe.sadd(cart_key,item)
pipe.execute()
#把命令推送过去, 事务结束
return True
break
else:
pipe.unwatch()
print("库存不足")
return False
except Exception:
pass
continue
finally:
pipe.reset()
Redis构建简单队列
定义队列
# 定义队列
queue_prodct_key = 'queue_' + product_key
que_cart = RedisQueue(queue_product_key)
que_cart.put(que_user)
# 数据:list 队列.put(商品1)
队列.put(商品2)
队列.put(商品3)
# 队列方法取
队列.get()
#队列取出一位
user= que_cart.get()
封装Redis 队列RedisQueue
# 封装redis 队列 RedisQueue
class RedisQueue(object):
"""Simple Queue with Redis Backend"""
def __init__(self,name,namespace='queue_ms',**redis_kwargs):
"""The defatul connection parameters are: host='localhost',port=6379,db=0"""
self.__db= redis.Redis(connection_pool=pool)
self.key= "%s:%s"%(namespace,name)
def qsize(self):
"""Return the approximate size of queue"""
return self.__db.llen(self,key)
def empty(self):
"""Return True if the queue is empty ,False otherwise"""
return self.qsize()==0
def put(self,item):
"""Put item into the queue"""
self.__db.rpush(self.key,item)
def get(self,block=True,timeout=None):
"""Romve and return an item from the queue, if optional args block is true and timeout is None(the
default), block if necessary until an item is avail """
if block: #是否为空
item = self.__db.blopo(self.key,timeout=timeout)
else:
item = self.__db.lpop(self.key)
if item:
item = item[1]
return item
Redis 集群配置-Sentinel(哨兵)
开发测试集群组成
- 一主(6379)
- 三从(6380-6382)
- 三哨兵(26379-26381)
三个从服务器配置
# 第1处: 改端口
port 6380
# 第2处更改: 从redis指定主的ip和端口
slaveof 127.0.0.1 6379
三个哨兵配置
- 新建哨兵配置目录
2.新建配置
3.拷贝sever和bat启动文件 - 更改哨兵端口
- 启动
哨兵配置
redissentinel.bat
redis-server.exe sentinel.conf --sentinel
sentinel.conf
#sentinel.conf
bind 0.0.0.0
port 26381
sentinel monitor seckill 127.0.0.1 6379 1
sentinel down-after-milliseconds seckill 5000
sentinel failover-timeout seckill 15000
logfile "sentinel.log"
启动
- 分别启动master,slave1,slave2,slave3
redisrunserver.bat
(redis-server.exe redis.windows.conf)
- 启动sentinel
redissentinel.bat
(redis-server.exe sentinel.conf --sentinel)
- 启动后页面
- 链接客户端
# cmd 打开redis-cli 打开master