Redis - 缓存性数据库
Redis 特性
特性一:速度快 - 快的原因就是内存
数据存在内存中
特性二
持久化 - 断电不丢数据
Redis所有数据保存在内存中,对数据的跟新将异步地保存在磁盘上
redis 支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是 Append-only file(缩写 aof)的方式。
Redis 特性三
特性三 - 多数据结构
Redis 特性四
支持多种客户端语言
Redis 特性五
功能丰富
安装redis
方式一
通过yum工具安装redis
yum install redis -y
方式二
编译安装redis
下载redis安装包
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
解压缩redis安装包
tar -zxvf redis-4.0.10.tar.gz
进入到解压后的文件夹目录中进行编译
make && make install
编辑redis的配置文件redis.conf,让其支持更安全的启动方式‘
requirepass 123456#打开redis密码的参数
protected-mode yes #开启安全模式
bind 0.0.0.0 #修改redis的默认绑定地址
port 6800 #修改redis的默认启动端口
过滤出非空行,注释行的内容,重定向写入到一个文件中
grep -v "^$" redis.conf |grep -v "^#" > new_redis.conf
在新配置文件结尾加上后台启动参数
daemonize yes
启动redis服务端
启动时指定加载写好的配置文件
redis-server new_redis.conf
验证redis是否启动
ps -ef|grep redis
指定密码登录redis
redis-cli -p 6800
测试
127.0.0.1:6800> ping
(error) NOAUTH Authentication required.
127.0.0.1:6800> auth 123456
OK
127.0.0.1:6800> ping
PONG
基础命令
keys * 查看所有key
type key 查看key类型
expire key seconds 过期时间
ttl key 查看key过期剩余时间,-2表示key已经不存在了
persist 取消key的过期时间,-1表示key存在,没有过期时间
exists key 判断key存在 存在返回1 否则0
del keys 删除key 可以删除多个
dbsize 计算key的数量
config get requirepass 查看redis是否设置密码
config set requirepass “xx” 为redis设置密码
redis的五大数据类型
字符串(strings)
set 设置key
>set v1 a
get 获取key
>get v1
append 追加string
>append v1 b
mset 设置多个键值对
>mset v2 a v3 b
mget 获取多个键值对
>mget v1 v2 v3
del 删除key
>del v1
incr 递增+1
>set v4 =1
>incr v4
decr 递减-1
>decr v4
列表(lists)
lpush 从列表左边插
>lpush v1 1 2
rpush 从列表右边插
>rpush v1 3 4
lrange 获取一定长度的元素
>lrange v1 0 -1
ltrim 截取一定长度列表
>ltrim v1 0 -1
lpop 删除最左边一个元素
>lpop v1
rpop 删除最右边一个元素
>rpop v1
lpushx/rpushx key存在则添加值,不存在不处理
集合(sets)
sadd/srem 添加/删除 元素
>sadd v1 1 2 3 4
>sadd v2 3 4 5 6
sismember 判断是否为set的一个元素
>sismember v1 2
smembers 返回集合所有的成员
sdiff 返回一个集合和其他集合的差异
>sdiff v1 v2
sinter 返回几个集合的交集
>sinter v1 v2
sunion 返回几个集合的并集
>sunion v1 v2
有序集合(sorted sets)
zadd/zrem 添加/删除
>zadd v1 10 a
>zadd v1 10 b
zrange 从小到大查看
>zrange v1 0 -1
zrevrange 从大到小查看
>zrevrange v1 0 -1
散列(hashes)
hset 设置散列值
>hset v1 age 10
>hset v1 sex 0
hget 获取散列值
>hget v1 age
hmset 设置多对散列值
>hmset v2 age 15 sex 1
hmget 获取多对散列值
>hmget v2 age sex
hsetnx 如果散列已经存在,则不设置(防止覆盖ke
hkeys 返回所有keys
>hkeys v2
hvals 返回所有values
>hvals v2
hlen 返回散列包含域(field)的数量
>hlen v2
hdel 删除散列指定的域(field)
>hdel v2 name age
hexists 判断是否存在
>hexists v2 name
发布订阅
Redis 通过 PUBLISH(发布者)、 SUBSCRIBE (订阅者)等命令实现了订阅与发布模式。发布者在指定频道发布消息,订阅者通过订阅这个频道来获取消息。一个发布者可以对应多个订阅者
#发布者
>publish pd1 abc
>publish pd2 123
#订阅者1
>subscribe pd1 pd2
>pd1
>abc
>pd2
>123
#订阅者2
>subscribe pd2
>pd2
>123
模糊匹配频道
#发布者
>publish pd1 abc
>publish pd2 123
#订阅者
>psubscribe pd*
>abc
>123
持久化存储
Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,Redis提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失。
RDB持久化
redis提供了RDB持久化的功能,这个功能可以将redis在内存中的的状态保存到硬盘中,它可以手动执行。也可以再redis.conf中配置,定期执行。
RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。
使用rdb持久化
1.准备配置文件
touch rdbredis.conf
写入以下内容
daemonize yes #后台运行
port 6379 #指定端口
logfile /data/6379/redis.log #指定日志路径
dir /data/6379 #redis的数据文件,会存放在这里
dbfilename dbmp.rdb #开启rdb持久化,指定持久化文件名
bind 0.0.0.0
save 900 1 #定义触发rdb持久化的时间机制,也可以手动使用save进行持久化
save 300 10
save 60 10000
2.创建数据文件夹
mkdir -p /data/6379
3.指定rdb文件启动redis
redis-server rdbredis.conf
AOF持久化
记录服务器执行的所有变更操作命令(例如set del等),并在服务器启动时,通过重新执行这些命令来还原数据集。AOF 文件中的命令全部以redis协议的格式保存,新命令追加到文件末尾。
优点:最大程序保证数据不丢
缺点:日志记录非常大
使用aof持久化
1.准备配置文件
touch aofredis.conf
写入以下内容
daemonize yes #后台运行
port 6379 # 指定端口
logfile /data/6379/redis.log # 指定日志路径
dir /data/6379 #redis的数据文件,会存放在这里
appendonly yes #开启aof的俩参数
appendfsync everysec #aof的持久化机制
# 参数
#always 总是修改类的操作
#everysec 每秒做一次持久化
#no 依赖于系统自带的缓存大小机制
2.创建数据文件夹
mkdir -p /data/6379
3.指定aof文件启动redis
redis-server aofredis.conf
RDB切换AOF
在redis4.0中,通过config set命令,达到不重启redis服务,从RDB持久化切换为AOF。在进行切换之前注意文件的备份。
config set appendonly yes # #开启AOF功能
config set save "" #关闭RDB功能
此时RDB已经正确切换AOF,但它是临时生效,注意还得修改redis.conf添加AOF设置,不然重启后,通过config set的配置将丢失
主从复制
redis的主从复制基于redis的多实例完成,基于不同的端口,运行独立的数据库
主库具有读写的权限,从库只有读的权限
使用主从复制
1.准备三个库的配置文件
主库配置文件 masterreids.conf
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6380
protected-mode no
从库1配置文件 slaveredis1.conf
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6381
protected-mode no
从库2配置文件 slaveredis2.conf
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6382
protected-mode no
2.创建三个数据库的数据文件夹
mkdir -p /data/{6380,6381,6382}
3.分别启动三个数据库实例
redis-server masterredis.conf
redis-server slaveredis1.conf
redis-server slaveredis2.conf
4.使用命令建立主从复制关系
redis-cli -p 6381 slaveof 127.0.0.1 6380
redis-cli -p 6382 slaveof 127.0.0.1 6380
5.查看库信息
redis-cli -p 6380 info replication
redis-cli -p 6381 info replication
redis-cli -p 6382 info replication
主库:
# Replication
role:master # 身份
connected_slaves:2 # 两个连接者
slave0:ip=127.0.0.1,port=6381,state=online,offset=14,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=14,lag=1
从库:
role:slave # 身份
master_host:127.0.0.1
master_port:6380
master_link_status:up # 连接状态
6.当主库由于某种原因挂掉后,手动将从库切换为主库,继续主从复制
# 剔除自己的从库身份
127.0.0.1:6381> slaveof no one
7.再次启动一个新的从库,以6381为主库即可
补充:除了通过指令建立主库和从库的关系外还可以在配置文件中直接指定为从库
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6381/redis.log"
dbfilename dump.rdb
dir /data/6381
protected-mode no
slaveof 127.0.0.1 6380 # 指定为从库
哨兵配置
Redis-Sentinel是redis官方推荐的高可用性解决方案,当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,自动发现master宕机,进行自动切换slave > master。
sentinel主要功能
1.持续监视redis运行状态,如果节点不可达就会对节点进行下线标识
2.如果被标识的是主节点,sentinel就会和其他的sentinel节点“协商”,如果其他节点也认为主节点不可达,就会选举一个sentinel节点来完成自动故障转义
3.在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
使用redis哨兵
1.准备三个库的配置文件
主库配置文件 masterreids.conf
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6380
protected-mode no
从库1配置文件 slaveredis1.conf
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6381
protected-mode no
slaveof 127.0.0.1 6380
从库2配置文件 slaveredis2.conf
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6382
protected-mode no
slaveof 127.0.0.1 6380
2.创建三个数据库的数据文件夹
mkdir -p /data/{6380,6381,6382}
3.分别启动三个数据库实例
redis-server masterredis.conf
redis-server slaveredis1.conf
redis-server slaveredis2.conf
4.准备三个哨兵(sentinel)的配置文件,这三个配置文件,仅仅是端口的不同,默认端口是26379
sentinel1.conf
port 26379 # 端口
dir /var/redis/data/ # 数据文件
logfile "26379.log" # 日志
sentinel monitor mymaster 127.0.0.1 6380 2
// 当前Sentinel节点监控 192.168.119.10:6380 这个主节点
// 2代表判断主节点失败至少需要2个Sentinel节点节点同意
// mymaster是主节点的别名
sentinel down-after-milliseconds mymaster 30000
//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒(30s)没有回复,则判定不可达
sentinel parallel-syncs mymaster 1
//当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,
原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel failover-timeout mymaster 180000
//故障转移超时时间为180000毫秒
daemonize yes
//后台运行哨兵
替换 端口生成另外两个配置文件
sed 's/26379/26380/g' sentinel1.conf > sentinel2.conf
sed 's/26379/26381/g' sentinel1.conf > sentinel3.conf
5.创建数据文件夹
mkdir -p /var/reids/data/
6.分别启动三个哨兵进程
redis-sentinel sentinel1.conf
redis-sentinel sentinel2.conf
redis-sentinel sentinel3.conf
[redis-4.0.10]# ps -ef |grep redis
root 15754 1 0 Mar16 ? 00:00:40 redis-server *:6380
root 15764 1 0 Mar16 ? 00:00:39 redis-server *:6381
root 15771 1 0 Mar16 ? 00:00:39 redis-server *:6382
root 16988 1 0 16:09 ? 00:00:00 redis-sentinel *:26379 [sentinel]
root 16999 1 0 16:10 ? 00:00:00 redis-sentinel *:26380 [sentinel]
root 17004 1 0 16:10 ? 00:00:00 redis-sentinel *:26381 [sentinel]
当主库挂掉30秒后哨兵会将其中一个从库变为主库,并将这个库的配置文件修改(删掉slaveof 配置),然后会让另一个从库变为自己的从库。当挂掉的这个库重启,会在一段时间内将这个库自动变为从库。
redis集群
redis3.0集群采用P2P模式,完全去中心化,将redis所有的key分成了16384个槽位,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新。redis实例集群主要思想是将redis数据的key进行散列,通过hash函数特定的key会映射到指定的redis节点上
数据分布理论
分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。
顺序分区
哈希分区
例如按照节点取余的方式,分三个节点,节点取余的优点是简单,客户端分片直接是哈希+取余
1~100的数据对3取余,可以分为三类
- 余数为0
- 余数为1
- 余数为2
一致性哈希
客户端进行分片,哈希+顺时针取余
虚拟槽分区
Redis Cluster采用虚拟槽分区
虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。
Redis Cluster槽的范围是0 ~ 16383。
槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,
每个节点负责一定数量的槽。
搭建redis cluster
搭建三主三从的数据库主从集群
1.准备6个数据库节点(7000~7005 )各个节点仅是端口的不同
# redis-7000.conf
port 7000
daemonize yes
dir "/opt/redis/data"
logfile "7000.log"
dbfilename "dump-7000.rdb"
cluster-enabled yes #开启集群模式
cluster-config-file nodes-7000.conf #集群内部的配置文件
sed 's/7000/7001/g' redis-7000.conf > redis-7001.conf
sed 's/7000/7002/g' redis-7000.conf > redis-7002.conf
sed 's/7000/7003/g' redis-7000.conf > redis-7003.conf
sed 's/7000/7005/g' redis-7000.conf > redis-7005.conf
2.分别启动6个redis节点
redis-server redis-7000.conf
redis-server redis-7001.conf
redis-server redis-7002.conf
redis-server redis-7003.conf
redis-server redis-7004.conf
redis-server redis-7005.conf
3.配置ruby环境,一键创建redis机群slot槽位分配
安装ruby解释器
yum install ruby -y
下载ruby操作redis的模块
wget http://rubygems.org/downloads/redis-3.3.0.gem
gem install -l redis-3.3.0.gem
先找到ruby的绝对路径
[opt]# find / -name redis-trib.rb
/opt/redis-4.0.10/src/redis-trib.rb
一键开启redis集群槽位分配
/opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
[root@izhk773c62kz06z redis-4.0.10]# /opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 1b1d442426ade3249d833f910531579bf70a6209 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: 1429bfd7306b2bec90b86a5f4e3c0c4105f286fc 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: 285d0ad96a9de180786c3ea1b682aeeab727eb8b 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: 6af27019c3230081b0b492ffacb29a4548b9db58 127.0.0.1:7003
replicates 285d0ad96a9de180786c3ea1b682aeeab727eb8b
S: 29b1640bab990b358291b7e547bc6b4beefd74f4 127.0.0.1:7004
replicates 1b1d442426ade3249d833f910531579bf70a6209
S: 92b567379ee3e5c7488a2dc0a6984d4358d01e33 127.0.0.1:7005
replicates 1429bfd7306b2bec90b86a5f4e3c0c4105f286fc
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join..
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 1b1d442426ade3249d833f910531579bf70a6209 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 92b567379ee3e5c7488a2dc0a6984d4358d01e33 127.0.0.1:7005
slots: (0 slots) slave
replicates 1429bfd7306b2bec90b86a5f4e3c0c4105f286fc
M: 1429bfd7306b2bec90b86a5f4e3c0c4105f286fc 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 29b1640bab990b358291b7e547bc6b4beefd74f4 127.0.0.1:7004
slots: (0 slots) slave
replicates 1b1d442426ade3249d833f910531579bf70a6209
S: 6af27019c3230081b0b492ffacb29a4548b9db58 127.0.0.1:7003
slots: (0 slots) slave
replicates 285d0ad96a9de180786c3ea1b682aeeab727eb8b
M: 285d0ad96a9de180786c3ea1b682aeeab727eb8b 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
4.以集群模式登陆redis-cluster
redis-cli -p 7000 -c
5.向集群中写入数据,查看数据重定向
[root@izhk773c62kz06z redis-4.0.10]# redis-cli -p 7000 -c
127.0.0.1:7000> keys *
(empty list or set)
127.0.0.1:7000> set v1 1
OK
127.0.0.1:7000> set v2 2
-> Redirected to slot [13550] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set v5 3
-> Redirected to slot [1033] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get v5
"3"
127.0.0.1:7000> get v2
-> Redirected to slot [13550] located at 127.0.0.1:7002
"2"
127.0.0.1:7002>
django使用redis
安装django-redis模块
pip3 install django-redis
在settings中配置redis配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100},
"PASSWORD": "12345",
}
}
}
视图中使用
from django_redis import get_redis_connection
conn = get_redis_connection("default")
使用redis做缓存
全站缓存
# 中间件配置
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
单视图缓存
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request):
...
url缓存
from django.views.decorators.cache import cache_page
urlpatterns = [
url(r'^index/$', cache_page(60 * 15)(my_view)),
]
页面局部缓存
{% load cache %}
{% cache 5000 缓存key %}
缓存内容
{% endcache %}
使用Redis做session
# 配置session存储
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"