一:redis简介一:介绍1:简介:redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、
一:redis简介
一:介绍
1:简介:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
2:主要功能:
高速读写
数据类型丰富
支持持久化
多种内存分配及回收策略
支持事务
消息队列、消息订阅
支持高可用
支持分布式分片集群
3:redis与memcached对比:
Memcached:
优点:高性能读写、单一数据类型、支持客户端式分布式集群、一致性hash
多核结构、多线程读写性能高。
缺点:无持久化、节点故障可能出现缓存穿透、分布式需要客户端实现、跨机房数据同步困难、架构扩容复杂度高
Redis:
优点:高性能读写、多数据类型支持、数据持久化、高可用架构、支持自定义虚拟内存、支持分布式分片集群、单线程读写性能极高
缺点:多线程读写较Memcached慢
memcache与redis在读写性能的对比:
memcached 由于是多核结构能高效利用cpu,所以适合多用户访问,每个用户少量的rw
redis 是单核结构,适合少用户访问,每个用户大量rw
4:Redis使用场景介绍
Memcached:多核的缓存服务,更加适合于多用户并发访问次数较少的应用场景
Redis:单核的缓存服务,单节点情况下,更加适合于少量用户,多次访问的应用场景。
所以解决redis无法高效利用cpu的问题,可以在单机上采用多实例架构,配合redis集群出现,这样对cpu的利用率就高了。
二:redis的安装与部署
一:linux下安装:
下载:
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
解压:
上传至 /data
tar xzf redis-3.2.12.tar.gz
mv redis-3.2.12 redis
安装:
cd redis
make
启动:
src/redis-server & # 加个‘&’ 符号代表后台启动的意思
环境变量:
vim /etc/profile
export PATH=/data/redis/src:$PATH
source /etc/profile
redis-server &
redis-cli
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> get num
10
二:redis基本管理操作
1:基础配置文件介绍:
[root@standby ~]# redis-cli shutdown
mkdir /data/6379
cat >>/data/6379/redis.conf <daemonize yes
port 6379
logfile /data/6379/redis.log
dir /data/6379
dbfilename dump.rdb
EOF
重启redis
redis-cli shutdown
redis-server /data/6379/redis.conf
netstat -lnp|grep 63
+++++++++++配置文件说明++++++++++++++
redis.conf
是否后台运行:
daemonize yes
默认端口:
port 6379
日志文件位置
logfile /var/log/redis.log
持久化文件存储位置
dir /data/6379
RDB持久化数据文件:
dbfilename dump.rdb
+++++++++++++++++++++++++
redis-cli
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
2:redis安全配置
redis-cli 客户端登录命令常用参数说明
redis-cli 刚装完,可以在redis服务器上直接登录redis
-p 6379 指定端口号
-h 指定链接地址
-a 指定链接密码
但是redis默认开启了保护模式,只允许本地回环地址登录并访问数据库,外部登录需要设置一下。
1):
禁止protected-mode
protected-mode yes/no (保护模式,是否只允许本地访问)
2):
①Bind :指定IP进行监听:
echo "bind 10.0.0.200 127.0.0.1" >>/data/6379/redis.conf
②增加requirepass {password}:
echo "requirepass 123" >>/data/6379/redis.conf
----------验证-----
重启redis
redis-cli shutdown
redis-server /data/6379/redis.conf
[root@python-linux ~]# redis-cli -a 123
127.0.0.1:6379> set name zhangsan
OK
三:redis持久化存储
一:redis持久化(内存数据保存到磁盘)
作用:可以有效防止,在redis宕机后,缓存失效的问题.
两种方式:RDB AOF
RDB 持久化
可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
优点:速度快,适合于用做备份,主从复制也是基于RDB持久化功能实现的。
缺点:会有数据丢失
rdb持久化核心配置参数:
vim /data/6379/redis.conf
dir /data/6379
dbfilename dump.rdb
save 900 1
save 300 10
save 60 10000
配置分别表示:
900秒(15分钟)内有1个更改
300秒(5分钟)内有10个更改
60秒内有10000个更改
----------
AOF 持久化(append-only log file)
记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集,类似于mysql的binlog。
AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
优点:可以最大程度保证数据不丢
缺点:日志记录量级比较大
举个例子:
set a 1
set a 2
set a 3
那么RDB只记录a的最终值,即3
而AOF会将3条命令都记录,显得比较臃肿
-------------
AOF持久化配置两行参数就可以
# 开启
appendonly yes
# 每秒触发一次 一般级别配置成everysec就可以了
appendfsync everysec
appendonly yes/no #是否打开aof日志功能
appendfsync always #每1个命令,都立即同步到aof
appendfsync everysec #每秒写1次
appendfsync no #写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof.
四:redis发布订阅
一:什么是发布订阅
发布订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
二:简单说明与使用
Linux下:
发布订阅
PUBLISH channel msg
将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...]
订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...]
取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所 有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类
PUNSUBSCRIBE [pattern [pattern ...]]
退订指定的规则, 如果没有参数则会退订所有规则
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态
注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。
发布订阅例子:
窗口1:
#收听者订阅频道
127.0.0.1:6379> SUBSCRIBE baodi
窗口2:
# 发布者往频道发布消息,订阅者自动收到消息
127.0.0.1:6379> PUBLISH baodi "jin tian zhen kaixin!"
订阅多频道:
窗口1:
127.0.0.1:6379> PSUBSCRIBE wang*
窗口2:
127.0.0.1:6379> PUBLISH wangbaoqiang "jintian zhennanshou "
三:python+redis实现发布订阅
发布者
# -*- coding:utf-8 -*-
# Author : liuqingzheng
# Data : 2018/11/23 19:17
import redis
conn=redis.Redis(host='127.0.0.1',port=6379)
# 频道,发布内容
conn.publish('98k','hello world')
订阅者
# -*- coding:utf-8 -*-
# Author : liuqingzheng
# Data : 2018/11/23 19:20
import redis
conn=redis.Redis(host='127.0.0.1',port=6379)
# 拿到发布者对象
pub=conn.pubsub()
# 订阅频道
pub.subscribe('98k')
# 可以订阅多个频道
# pub.subscribe('998')
# 循环等待
while True:
# 接收到消息,解析响应
msg=pub.parse_response()
print(msg)
一些应用场景:
1 构建实时消息系统,比如普通的即时聊天,群聊等功能
2 在我们的分布式架构中,常常会遇到读写分离的场景,在写入的过程中,就可以使用redis发布订阅,使得写入值及时发布到各个读的程序中,就保证数据的完整一致性
3 在一个博客网站中,有100个粉丝订阅了你,当你发布新文章,就可以推送消息给粉丝们
五:redis事务及锁
一:简介
redis中的事务跟关系型数据库中的事务是一个相似的概念,但是有不同之处。关系型数据库事务执行失败后面的sql语句不在执行,而redis中的一条命令执行失败,其余的命令照常执行。 redis中开启一个事务是使用multi,相当于begin\start transaction,exec提交事务,discard取消队列命令(非回滚操作)。
redis的事务是基于队列实现的。redis开始事务后每执行一条命令,都加入到队列中,并未真的执行。mysql的事务是基于事务日志实现的。
开启事务功能时(multi)
multi
command1
command2
command3
command4
4条语句作为一个组,并没有真正执行,而是被放入同一队列中。
如果,这时执行discard,会直接丢弃队列中所有的命令,而不是做回滚。
exec
当执行exec时,队列中所有操作,要么全成功要么全失败
二:redis事务中的锁
redis执行事务时为乐观锁工作原理,相当于不加锁,mysql执行事务时为悲观锁。
例子1:
窗口1:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> set b 2
QUEUED
127.0.0.1:6379>
窗口2:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 3
QUEUED
127.0.0.1:6379> set b 4
QUEUED
127.0.0.1:6379>
窗口1:
127.0.0.1:6379> exec
窗口2:
127.0.0.1:6379> exec
127.0.0.1:6379> get a
"3"
127.0.0.1:6379> get b
"4"
可以看到,两个事务都执行成功,并且后exec的覆盖前面的。假设现在是买票的场景,只剩1张票,A和B都生成订单了,A先付款会提示付款成功,B后付款也会提示付款成功,这乱套了。
View Code
可以运用watch 使得执行事务类似悲观锁
例子2:
模拟抢票
窗口1:
127.0.0.1:6379> set ticket 1
OK
127.0.0.1:6379> watch ticket
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set ticket 0
QUEUED
窗口2:
127.0.0.1:6379> watch ticket
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set ticket 0
QUEUED
窗口1:
127.0.0.1:6379> exec
1) OK
窗口2:
127.0.0.1:6379> exec
(nil)
窗口1提交成功后,窗口2提交失败,完成需求
View Code