Linux 运维知识梳理(7)Redis 详解

Linux 专栏收录该内容
15 篇文章 4 订阅

一、Redis介绍

1、介绍

Redis(Remote Dictionary Server ),即远程字典服务,由意大利人 antirez (Salvatore Sanfilippo) 开发的一款,内存高速缓存数据库。

它支持丰富的数据结构,比如 String、list(双向链表)、hash(哈希)、set(集合)、sorted set(zset有序集合)

可持久化(保存数据到磁盘中),保证了数据安全

2、业务使用场合

  • [Sort Set] 排行榜应用,取 top N 操作,例如 sina 微博热门话题

  • [List] 获得最新 N 个数据 或 某个分类的最新数据

  • [String] 计数器应用

  • [Set] sns (social network site) 获得共同好友

  • [Set] 防攻击系统(ip判断)黑白名单等等

3、对比 memcached

  • Redis 不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
  • Redis 支持 master-slave (主—从)模式应用。
  • Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
  • Redis 单个 value 存储 string 的最大限制是 512MB,memcached 只能保存 1MB 的数据
  • Redis 是单核,memcached 是多核

二、源码编译安装

官方网址:https://redis.io

github: https://github.com/antirez/redis

安装脚本

vi install.sh
#!/bin/bash
yum install -y wget gcc vim
wget https://download.redis.io/releases/redis-5.0.14.tar.gz
tar -zxvf redis-5.0.14.tar.gz
cd redis-5.0.14
make PREFIX=/opt/redis install
cp redis.conf /opt/redis
cp sentinel.conf /opt/redis
echo 'export PATH=$PATH:/opt/redis/bin' >> ~/.bashrc
source ~/.bashrc

# 编写启动脚本
cat > /usr/lib/systemd/system/redis.service << EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
PIDFile=/var/run/redis_6379.pid
ExecStart=/opt/redis/bin/redis-server /opt/redis/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
LimitNOFILE=655360
PrivateTmp=true
Type=notify
User=root
Group=root

[Install]
WantedBy=multi-user.target
EOF
cat > /usr/lib/systemd/system/redis-sentinel.service << EOF
[Unit]
Description=Redis Sentinel
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
PIDFile=/var/run/redis-sentinel.pid
ExecStart=/opt/redis/bin/redis-sentinel /opt/redis/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=root
Group=root

[Install]
WantedBy=multi-user.target
EOF

安装

source install.sh

启动 redis.server

systemctl start redis && systemctl enable redis

三、数据结构类型操作

Redis 支持五种数据类型:

  • string(字符串)
  • hash(哈希)
  • list(列表)
  • set(集合)
  • zset(sorted set:有序集合)
类型简介特性场景
String二进制安全可以包含任何数据,比如 jpg 图片或者序列化的对象,一个键最大能存储 512M大部分场景
Hash键值对集合,即编程语言中的 Map 类型适合存储对象,并且可以像数据库中 update 一个属性一样只修改某一项属性值存储、读取、修改用户属性
List链表(双向链表)增删快,提供了操作某一段元素的 API1、最新消息排行等功能(比如朋友圈的时间线)
2、消息队列
Set哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1)
2、为集合提供了求交集、并集、差集等操作
1、共同好友
2、利用唯一性,统计访问网站的所有独立ip
3、好友推荐时,根据 tag 求交集,大于某个阈值就可以推荐
Sorted Set将 Set 中的元素增加一个权重参数 score,元素按 score 有序排列数据插入集合时,已经进行天然排序1、排行榜
2、带权重的消息队列

数据库

Redis 支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。

Redis 是一个字典结构的存储服务器,而实际上一个 Redis 实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。

每个数据库对外都是一个从 0 开始的递增数字命名,Redis 默认支持 16 个数据库(可以通过配置文件 databases 16
支持更多,无上限)。客户端与 Redis 建立连接后会自动选择 0 号数据库,不过可以随时使用 SELECT 命令更换数据库,如要选择 1 号数据库:

redis> SELECT 1
OK
redis [1] > GET foo
(nil)

然而这些以数字命名的数据库又与我们理解的数据库有所区别。

  1. Redis 不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。
  2. Redis 也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。
  3. 最重要的一点是多个数据库之间并不是完全隔离的,比如 FLUSHALL 命令可以清空一个 Redis 实例中所有数据库中的数据。

综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用 0 号数据库存储某个应用生产环境中的数据,使用 1 号数据库存储测试环境中的数据,但不适宜使用 0 号数据库存储 A 应用的数据而使用 1 号数据库 B 应用的数据,不同的应用应该使用不同的 Redis 实例存储数据。

1、String

String 是 Redis 最基本的类型,一个 key 对应一个 value。String 类型的值最大能存储 512MB。
String 类型是二进制安全的。意思是 Redis 的 String 可以包含任何数据。比如 jpg 图片或者序列化的对象。

127.0.0.1:6379> SET Name 'liuli'
OK
127.0.0.1:6379> GET Name
"liuli"
127.0.0.1:6379> DEL Name
(integer) 1
127.0.0.1:6379> GET Name
(nil)

2、Hash

Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

127.0.0.1:6379> HMSET userInfo name 'liuli' age 25 phone 110
OK
127.0.0.1:6379> HGET userInfo name
"liuli"
127.0.0.1:6379> HGET userInfo age
"25"
127.0.0.1:6379> HGET userInfo phone
"110"
127.0.0.1:6379> HKEYS userInfo
1) "name"
2) "age"
3) "phone"
127.0.0.1:6379> HVALS userInfo
1) "liuli"
2) "25"
3) "110"
127.0.0.1:6379> HGETALL userInfo
1) "name"
2) "liuli"
3) "age"
4) "25"
5) "phone"
6) "110"

3、List

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

127.0.0.1:6379> LPUSH language C
(integer) 1
127.0.0.1:6379> LPUSH language Java
(integer) 2
127.0.0.1:6379> LPUSH language Python
(integer) 3
127.0.0.1:6379> LPUSH language PHP
(integer) 4
127.0.0.1:6379> RPUSH language Node
(integer) 5
127.0.0.1:6379> LRANGE language 0 10
1) "PHP"
2) "Python"
3) "Java"
4) "C"
5) "Node"

4、Set

Redis 的 Set 是 String 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

127.0.0.1:6379> SADD database redis
(integer) 1
127.0.0.1:6379> SADD database mysql
(integer) 1
127.0.0.1:6379> SADD database oracle
(integer) 1
127.0.0.1:6379> SMEMBERS database
1) "mysql"
2) "oracle"
3) "redis"

5、zset

Redis zset 和 set 一样也是 strin g类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
zset 的成员是唯一的,但分数(score)却可以重复。

127.0.0.1:6379> ZADD subject 99 math
(integer) 1
127.0.0.1:6379> ZADD subject 68 english
(integer) 1
127.0.0.1:6379> ZADD subject 77 physics
(integer) 1
127.0.0.1:6379> ZADD subject 87 Chinese
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE subject 0 100
1) "english"
2) "physics"
3) "Chinese"
4) "math"

四、数据持久化操作

数据 持久化(数据在服务或者软件重启之后不丢失)

如果数据只存在内存中,肯定会丢失,实现持久化,就需要把数据存储到磁盘中(hdd ssd)

1、snappshoting(快照)

默认 snappshoting 是开启的,有一个备份的频率

通过查看配置文件可以看到
在这里插入图片描述

备份文件名称

# The filename where to dump the DB
dbfilename dump.rdb

手动数据备份

127.0.0.1:6379> SAVE

数据恢复 需要先停掉 redis 服务

如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可

2、append only file

开启 aof 后,之前的 redis 里的数据会丢失

# 开启 aof 模式
appendonly yes
# 备份文件
appendfilename "appendonly.aof"
# 备份频率
# always 每操作一次备份一次
# everysec 每秒钟备份一次
# no redis 空闲时备份一次
appendfsync everysec

3、总结

snappshoting 一般的数据持久化使用,效率高,数据迁移方便

aof 适合于备份、数据实时性备份要求更高的情况

五、主从模式

ipRedis 版本角色
192.168.0.115.0.14master
192.168.0.125.0.14slave1
192.168.0.135.0.14slave2

注意:主从涉及主机间通讯,要提前开通防火墙的 6379 端口,或者使用命令 systemctl stop firewalld 关闭防火墙

搭建过程见本文的第二步源码编译安装,这里直接修改搭建后的配置文件实现主从

修改所有主机的 redis.conf 配置文件,bind 的 ip 指的是其他的主机需要和这个主机通讯的 ip

# 添加本机网卡绑定的IP
bind 0.0.0.0

# 关闭保护模式
protected-mode no

重启 redis

systemctl restart redis

修改 slave 主机的 redis.conf 配置文件,设置 master redis 信息

# 指定 master 主机的 ip port
replicaof 192.168.0.11 6379

重启 redis

systemctl restart redis

查看 master 同步信息

127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.13,port=6379,state=online,offset=28,lag=1
slave1:ip=192.168.0.12,port=6379,state=online,offset=28,lag=1
master_replid:d48302fed4894b3267a8bab3276a0342cb93d1d1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28

查看 slave 同步信息

127.0.0.1:6379> INFO replication
# Replication
role:slave
master_host:192.168.0.11
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:d48302fed4894b3267a8bab3276a0342cb93d1d1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70

六、哨兵模式

哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UkuIgTkw-1638272386053)(media/1559103536762.png)]
这里的哨兵有两个作用

  • 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到 master 宕机,会自动将 slave 切换成 master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对 Redis 服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
在这里插入图片描述

ipRedis 版本角色端口
192.168.0.115.0.14master、Sentinel6379、26379
192.168.0.125.0.14slave1、Sentinel6379、26379
192.168.0.135.0.14slave2、Sentinel6379、26379

特别注意:使用 Redis 哨兵模式,最少需要 3 个节点(一主多从结构)

1、配置主服务器的 IP 和端口

slave 从服务器上,修改 sentinel.conf 配置文件,设置主服务器的 IP 和端口,并且加上权值为2,这里的权值,是用来计算我们需要将哪一台服务器升级升主服务器。

注意:这里只配置两个 slave 服务器即可

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 192.168.0.11 6379 2

3、启动所有的 Sentinel

systemctl start redis-sentinel && systemctl enable redis-sentinel

4、测试 master 宕机

将 master 服务器关机后

重新查看两个 slave 的主从情况,发现 192.168.0.12 已经成为 master 服务器了

  • 192.168.0.12
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.0.13,port=6379,state=online,offset=9157,lag=1
master_replid:e4c7fe2a464f81699f72ad63276fa042fcfcca12
master_replid2:1d1bab9ef29471bf516a86c75f33944fbf3fa205
master_repl_offset:9157
second_repl_offset:8426
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:9157
  • 192.168.0.13
127.0.0.1:6379> INFO replication
# Replication
role:slave
master_host:192.168.0.12
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:9157
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:e4c7fe2a464f81699f72ad63276fa042fcfcca12
master_replid2:1d1bab9ef29471bf516a86c75f33944fbf3fa205
master_repl_offset:9157
second_repl_offset:8426
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:9157

5、测试 master 重连

将 master 主机开机后,重新启动 redis 服务,查看主从情况,以 slave 的身份加入集群

127.0.0.1:6379> INFO replication
# Replication
role:slave
master_host:192.168.0.12
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:24902
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:e4c7fe2a464f81699f72ad63276fa042fcfcca12
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:24902
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:19681
repl_backlog_histlen:5222

七、Redis 集群

Redis 高可用在负载均衡的同时兼顾了高可用的特性,所以是企业中常用的一种架构,集群架构至少要三台 master 服务器,本文采用了三主三从的架构。

1、主机规划

注:实际运维工作中,大概需要3台机器,每台机器2个节点。但需详细规划主从关系,尽量不要把一组主从放在同一台服务器中。

IP端口角色配置文件
192.168.1.67001Masterredis_7001.conf
7002Slaveredis_7002.conf
192.168.1.77003Masterredis_7003.conf
7004Slaveredis_7004.conf
192.168.1.87005Masterredis_7005.conf
7006Slaveredis_7006.conf

2、环境初始化

  • 2.1 最大可打开文件数
vi /etc/security/limits.conf

追加如下内容

* soft nofile 65535
* hard nofile 65535
  • 2.2 TCP监听队列
echo 'net.core.somaxconn = 32767'  >> /etc/sysctl.conf

立即生效

sysctl -w net.core.somaxconn=32767
  • 2.3 关闭防火墙
systemctl stop firewalld.service && systemctl disable firewalld.service

3、编译安装

yum install -y wget gcc vim && \
wget https://download.redis.io/releases/redis-5.0.14.tar.gz && \
tar -zxvf redis-5.0.14.tar.gz && \
cd redis-5.0.14 && \
make PREFIX=/opt/redis install && \
mkdir /opt/redis/{logs,conf,data} && \
echo 'PATH=$PATH:/opt/redis/bin' >> ~/.bashrc && \
source ~/.bashrc 

生成配置文件,通过修改 PORT 值,生成不同的配置文件

export PORT=7001
cat > /opt/redis/conf/redis_$PORT.conf << EOF
# redis 端口
port $PORT
# 启用集群模式
cluster-enabled yes
# 集群配置文件
cluster-config-file /opt/redis/conf/cluster_nodes_$PORT.conf
# 集群中的节点最大不可用时长
cluster-node-timeout 5000
# 数据目录
dir /opt/redis/data/
# 数据文件名
dbfilename dump_$PORT.rdb
# 指定是否在每次更新操作后进行日志记录
appendonly yes
# 指定更新日志文件名
appendfilename appendonly_$PORT.aof
# 日志文件路径
logfile /opt/redis/logs/redis_$PORT.log
# pid 文件路径
pidfile /opt/redis/redis_$PORT.pid
# 后台运行
daemonize yes
# 非保护模式
protected-mode no
EOF

4、启动 redis-server 服务

# 依次将六个全部启动
/opt/redis/bin/redis-server /opt/redis/conf/redis_7001.conf

5、启动 redis 集群

该命令一台主机设置即可,主机按照三主、三从的顺序

redis-cli \
--cluster create \
192.168.1.6:7001 192.168.1.7:7003 192.168.1.8:7005 \
192.168.1.6:7002 192.168.1.7:7004 192.168.1.8:7006 \
--cluster-replicas 1

Redis 会自动交叉主机绑定主从关系(输入 yes 确认)防止一组主从在同一台主机上

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.1.7:7004 to 192.168.1.6:7001
Adding replica 192.168.1.8:7006 to 192.168.1.7:7003
Adding replica 192.168.1.6:7002 to 192.168.1.8:7005
M: e3bfb1bb0f86db12a7585f1321b1e4e6d647a14d 192.168.1.6:7001
   slots:[0-5460] (5461 slots) master
M: 38d64c4cc0497b93eca30ecd6de027b9460df4dd 192.168.1.7:7003
   slots:[5461-10922] (5462 slots) master
M: 2076ca0bb1ac06179a099ca9ff772e7da0fc01df 192.168.1.8:7005
   slots:[10923-16383] (5461 slots) master
S: a503b676025bbecb2847283f5a7c7c47cc8d1cdd 192.168.1.6:7002
   replicates 2076ca0bb1ac06179a099ca9ff772e7da0fc01df
S: de199f4d804c665a9e71b306ce408d88f93983e9 192.168.1.7:7004
   replicates e3bfb1bb0f86db12a7585f1321b1e4e6d647a14d
S: 3b041b0ba18393d36596d94e701e35817b5a1dda 192.168.1.8:7006
   replicates 38d64c4cc0497b93eca30ecd6de027b9460df4dd
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 192.168.1.6:7001)
M: e3bfb1bb0f86db12a7585f1321b1e4e6d647a14d 192.168.1.6:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 38d64c4cc0497b93eca30ecd6de027b9460df4dd 192.168.1.7:7003
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: de199f4d804c665a9e71b306ce408d88f93983e9 192.168.1.7:7004
   slots: (0 slots) slave
   replicates e3bfb1bb0f86db12a7585f1321b1e4e6d647a14d
S: 3b041b0ba18393d36596d94e701e35817b5a1dda 192.168.1.8:7006
   slots: (0 slots) slave
   replicates 38d64c4cc0497b93eca30ecd6de027b9460df4dd
M: 2076ca0bb1ac06179a099ca9ff772e7da0fc01df 192.168.1.8:7005
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: a503b676025bbecb2847283f5a7c7c47cc8d1cdd 192.168.1.6:7002
   slots: (0 slots) slave
   replicates 2076ca0bb1ac06179a099ca9ff772e7da0fc01df
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

6、测试集群

# 随意连接一个 redis 节点,设置一个 key,发现 redis 将该 key 值存放到 192.168.1.7 主机上
[root@localhost ~]# redis-cli -c -h 192.168.1.6 -p 7001
192.168.1.6:7001> set name liuli
-> Redirected to slot [5798] located at 192.168.1.7:7003
OK

关闭 192.168.1.7 主机模拟故障

# 发先 key 已经漂移到 192.168.1.8 主机上了
[root@localhost ~]# redis-cli -c -h 192.168.1.8 -p 7005
192.168.1.8:7005> get name
-> Redirected to slot [5798] located at 192.168.1.8:7006
"liuli"

八、安全设置

1、设置密码

修改 redis.conf 文件

# 设置密码为 passwd123
requirepass passwd123

重启 redis 后登录,使用 auth 密码登录

127.0.0.1:6379> KEYS *
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth passwd123
OK
127.0.0.1:6379> KEYS *
1) "id"

注意:如果开启了密码限制,搭建主从需要在 slave 配置 masterauth <master-password> 选项中填写 master 的密码

2、限制 IP 访问

修改 redis.conf 文件,打开配置 IP 限制

bind 127.0.0.1 (允许访问服务器的IP)

重启 redis 服务,生效

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页

打赏作者

刘李404not found

觉得博主文章有用,就鼓励一下呗

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值