Redis - 缓存性数据库

Redis 特性

特性一:速度快 - 快的原因就是内存
数据存在内存中

Redis - 缓存性数据库

Redis - 缓存性数据库

特性二

持久化 - 断电不丢数据
Redis所有数据保存在内存中,对数据的跟新将异步地保存在磁盘上

 redis 支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是 Append-only file(缩写 aof)的方式。

Redis - 缓存性数据库

Redis 特性三

特性三 - 多数据结构

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis 特性四

支持多种客户端语言

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 - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库
Redis - 缓存性数据库

Redis - 缓存性数据库

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

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库

Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库

列表(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存在则添加值,不存在不处理

Redis - 缓存性数据库

Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库

集合(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 - 缓存性数据库

Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库
Redis - 缓存性数据库

发布订阅

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节点上

数据分布理论

分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。

顺序分区
Redis - 缓存性数据库

哈希分区

例如按照节点取余的方式,分三个节点,节点取余的优点是简单,客户端分片直接是哈希+取余

1~100的数据对3取余,可以分为三类

  • 余数为0
  • 余数为1
  • 余数为2

Redis - 缓存性数据库

一致性哈希

客户端进行分片,哈希+顺时针取余

虚拟槽分区

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
[ 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.向集群中写入数据,查看数据重定向

[ 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"