【第二章】redis 简介&部署
redis 基础
Redis和 Memcached是 也称为 。相对的,MySQL、Mariadb、SQL Server、PostgreSQL、Oracle 数据库属于关系型数据(RDBMS, Relational Database Management System)
1. redis 简介
Redis(Remote Dictionary Server) 于2009 年发布, 开发者 Salvatore Sanfilippo 是意大利开发者, 他本想为自己的公司开发一个用于替换 MySQL 的产品, 但是没有想到他把 Redis 开源后大受欢迎,短短几年,Redis 就有了很大的用户群体,目前国内外使用的公司有知乎网、新浪微博、 GitHub 等。
Redis是一个开源的、遵循 BSD协议的、基于内存的、而且目前比较流行的键值型数据库(key-value database),是一个非关系型数据库。redis 提供将内存通过网络远程共享的一种服务。
提供类似功能的还有memcache,但相比 memcache, redis 还提供了易扩展、高性能、 具备数据持久性等功能。Redis 在高并发、低延迟环境要求比较高的环境使用量非常广泛, 目前 redis 在 DB-Engine 月排行榜 中一直比较靠前,而且一直是键值型存储类的首位。
DB-Engine 月排行榜2. redis 对比 memcached
支持数据的持久化
:可以将内存中的数据保持在磁盘中,重启 redis 服务或者服务器之后可以从备份文件中恢复数据到内存继续使用。
支持更多的数据类型
:支持 string(字符串)、 hash(哈希数据)、 list(列表)、 set(集合)、 zet(有序集合)
支持数据的备份
:可以实现类似于数据的 master-slave 模式的数据备份,另外也支持使用快照+AOF。
支持更大的 value 数据
: memcache 单个 key value 最大只支持 1MB,而 redis 最大支持 512MB。
Redis 是单线程, 而 memcache 是多线程
, 所以单机情况下没有 memcache 并发高, 但 redis 支持分布式集群以实现更高的并发, 单 Redis 实例可以实现数万并发。
支持集群横向扩展
:基于 redis cluster 的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性。
都是基于C 语言开发
。
3. redis 典型应用场景
Session 共享:常见于 web 集群中的 Tomcat 或者 PHP 中多 web 服务器 session 共享
消息队列: ELK 的日志缓存、 部分业务的订阅发布系统
计数器: 访问排行榜、商品浏览数等和次数相关的数值统计场景
缓存: 数据查询、 电商网站商品信息、 新闻内容
微博/微信社交场合: 共同好友、 点赞评论等
Redis 安装及使用
官方下载地址: http://download.redis.io/releases/
1. yum 安装 redis
在 centos 系统上需要安装 epel 源。
1.1 查看 yum 仓库 redis 版本
查看 yum 仓库 redis 版本1.2 安装 redis
[root@node1 ~]# yum install redis -y
[root@node1 ~]# systemctl start redis && systemctl enable redis
[root@node1 ~]# redis-cli
127.0.0.1:6379> info
# Server
redis_version:3.2.12
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7897e7d0e13773f
redis_mode:standalone
os:Linux 3.10.0-514.el7.x86_64 x86_64
arch_bits:64
2. 编译安装 redis
下载当前最新 release 版本 redis 源码包:http://download.redis.io/releases/
redis 源码包2.1 编译安装命令
官方的安装命令:https://redis.io/download
[root@node1 ~]# cd /usr/local/src/
[root@node1 src]# tar zxvf redis-5.0.8.tar.gz
[root@node1 src]# cd redis-5.0.8/
[root@node1 redis-5.0.8]# make PREFIX=/apps/redis install
[root@node1 redis-5.0.8]# ll /apps/redis/
total 0
drwxr-xr-x. 2 root root 134 Apr 9 23:37 bin
[root@node1 redis-5.0.8]# mkdir -pv /apps/redis/etc
[root@node1 redis-5.0.8]# cp redis.conf /apps/redis/etc/
2.2 前台启动 redis
[root@node1 ~]# /apps/redis/bin/redis-server /apps/redis/etc/redis.conf
image
2.3 解决当前的警告提示
2.3.1 tcp-backlog
# 告警详情:
34395:M 09 Apr 2020 23:41:55.542 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
backlog 参数控制的是三次握手的时候 server 端收到 client ack 确认号之后的队列值。
The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the reque be ignored so that a later reattempt at connection succeeds.
解决办法:
# 配置kernel参数net.core.somaxconn
# 命令行配置(立刻生效,但重启后失效)
# 查看net.core.somaxconn的值
[root@node1 ~]# sysctl -a | grep net.core.somaxconn
# 修改参数值的语法
[root@node1 ~]# sysctl -w net.core.somaxconn=512
net.core.somaxconn = 512
# 修改配置文件(永久生效)
[root@node1 ~]# grep -v '#' /etc/sysctl.conf
[root@node1 ~]# vim /etc/sysctl.conf
[root@node1 ~]# grep -v '#' /etc/sysctl.conf
net.core.somaxconn=512
[root@node1 ~]# sysctl -p
net.core.somaxconn = 512
2.3.2 vm.overcommit_memory
# 告警详情:
43659:M 10 Apr 2020 14:10:49.627 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
0
:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1
:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2
:表示内核允许分配超过所有物理内存和交换空间总和的内存。
解决办法:
# 配置kernel参数vm.overcommit_memory
# 命令行配置(立刻生效,但重启后失效)
# 查看vm.overcommit_memory 的值
[root@node1 ~]# sysctl -a | grep vm.overcommit_memory
# 修改参数值的语法
[root@node1 ~]# sysctl -w vm.overcommit_memory=1
vm.overcommit_memory = 1
# 修改配置文件(永久生效)
[root@node1 ~]# grep -v '#' /etc/sysctl.conf
[root@node1 ~]# vim /etc/sysctl.conf
[root@node1 ~]# grep -v '#' /etc/sysctl.conf
vm.overcommit_memory=1
[root@node1 ~]# sysctl -p
vm.overcommit_memory=1
2.3.3 transparent hugepage
开启大页内存动态分配,需要关闭让 redis 负责内存管理。
[root@node1 ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
2.3.4 再次启动 redis
无告警2.4:创建 redis 服务启动脚本:
[root@node1 redis]# vim /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
#ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=root
Group=root
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
2.5 创建 redis 用户和数据目录
[root@node1 redis]# groupadd -g 1000 redis && useradd -u 1000 -g 1000 redis -s /usr/sbin/nologin
[root@node1 redis]# mkdir -pv /apps/redis/{etc,logs,data,run}
[root@node1 redis]# chown redis.redis -R /apps/redis/
2.2.6 验证 redis 启动
image2.7 使用客户端连接 redis
/apps/redis/bin/redis-cli -h IP/HOSTNAME -p PORT -a PASSWORD
2.8 创建命令软连接
ln -sv /apps/redis/bin/redis-* /usr/bin/
2.9 编译安装后的命令
[root@node1 redis]# ll /apps/redis/bin/
total 32768
-rwxr-xr-x. 1 redis redis 4365480 Apr 10 14:36 redis-benchmark #redis 性能测试工具
-rwxr-xr-x. 1 redis redis 8124472 Apr 10 14:36 redis-check-aof #AOF 文件检查工具
-rwxr-xr-x. 1 redis redis 8124472 Apr 10 14:36 redis-check-rdb #rdb 文件检查工具
-rwxr-xr-x. 1 redis redis 4806592 Apr 10 14:36 redis-cli #redis 客户端工具
lrwxrwxrwx. 1 redis redis 12 Apr 10 14:36 redis-sentinel -> redis-server #哨兵,软连接到server
-rwxr-xr-x. 1 redis redis 8124472 Apr 10 14:36 redis-server #redis 服务端
3. 连接到 Redis
主要分为运维人员的连接和程序的连接
3.1 本机非密码连接
redis-cli
3.2 跨主机非密码连接
redis-cli -h HOSTNAME/IP -p PORT
3.3 跨主机密码连接
redis-cli -h HOSTNAME/IP -p PORT -a PASSWORD
3.4 python 连接方式
import redis
import time
pool = redis.ConnectionPool(host='<redis_bind_ip>', port=6379, password='')
r = redis.Redis(connection_pool=pool)
for i in range(100):
r.set("k%d" % i, "v%d" % i)
time.sleep(1)
data = r.get("k%d" % i)
print(data)