Redis


redis简介

redis官网

Redis是什么

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

它是是一个开源的底层使用C语言编写的key-value存储数据库。可用于缓存、事件发布订阅、高速队列等场景。而且支持丰富的数据类型:string(字符串)、hash(哈希)、list(列表)、set(无序集合)、zset(sorted set:有序集合)

Redis的性能极高,读的速度是110000次/s,写的速度是81000次/s,支持事务,支持备份,丰富的数据类型。

Redis速度快的原因

1、Redis是纯内存操作,需要的时候需要我们手动持久化到硬盘中

2、Redis是单线程,从而避开了多线程中上下文频繁切换的操作。

3、Redis数据结构简单、对数据的操作也比较简单

4、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求

5、使用多路I/O复用模型,非阻塞I/O

多路I/O复用:

I/O 多路复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪,就是这个文件描述符进行读写操作之前),能够通知程序进行相应的读写操作

为什么使用redis

Redis是一种NoSQL数据库,NoSQL数据库在整个数据库领域的江湖地位已经不言而喻。在大数据时代,虽然RDBMS(关系型数据库管理系统)很优秀,但是面对快速增长的数据规模和日渐复杂的数据模型,RDBMS渐渐力不从心,无法应对很多数据库处理任务。

NoSQL数据库在整个数据库领域的江湖地位已经不言而喻。在大数据时代,虽然RDBMS很优秀,但是面对快速增长的数据规模和日渐复杂的数据模型,RDBMS渐渐力不从心,无法应对很多数据库处理任务,这时NoSQL凭借易扩展、大数据量和高性能以及灵活的数据模型成功的在数据库领域站稳了脚跟。

目前大家基本认同将NoSQL数据库分为四大类:键值存储数据库,文档型数据库,列存储数据库和图形数据库,其中每一种类型的数据库都能够解决关系型数据不能解决的问题。在实际应用中,NoSQL数据库的分类界限其实没有那么明显,往往会是多种类型的组合体。

Redis 是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。目前由VMware主持开发工作。

应用场景

1、缓存

缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非常多。

2、排行榜

很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis提供的有序集合数据类构能实现各种复杂的排行榜应用。

3、计数器

什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景。

4、分布式会话

集群模式下,在应用不多的情况下一般使用容器自带的session复制功能就能满足,当应用增多相对复杂的系统中,一般都会搭建以Redis等内存数据库为中心的session服务,session不再由容器管理,而是由session服务及内存数据库管理。

5、分布式锁

在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。

6、 社交网络

点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能。

7、最新列表

Redis列表结构,LPUSH可以在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接根据ID去到对应的内容页即可。

8、消息系统

消息队列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。Redis提供了发布/订阅及阻塞队列功能,能实现一个简单的消息队列系统。另外,这个不能和专业的消息中间件相比。

实际中常用的:
1.实时消息系统
2.实时聊天
3.订阅、关注系统都可以
情况大一点更多的使用MQ

redis简单内核优化相关参数

vim /etc/sysctl.conf
#添加
vm.max_map_count=262144
net.core.somaxconn= 32768
vm.overcommit_memory=1 

sysctl -p

同时也要根据情况调整文件限制
vim /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

#经常查看redis日志,根据日志来做调整

安装redis

1.安装

#安装依赖
yum -y install centos-release-scl
[root@localhost ~]# yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

#临时将此时的gcc版本改为9
[root@localhost ~]# scl enable devtoolset-9 bash
#或永久改变
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile

#查看gcc版本
[root@localhost ~]# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-9/root/usr/libexec/gcc/x86_64-redhat-linux/9/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/devtoolset-9/root/usr --mandir=/opt/rh/devtoolset-9/root/usr/share/man --infodir=/opt/rh/devtoolset-9/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --with-default-libstdcxx-abi=gcc4-compatible --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-9.3.1-20200408/obj-x86_64-redhat-linux/isl-install --disable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 9.3.1 20200408 (Red Hat 9.3.1-2) (GCC) 


#下载最新稳定版本
[root@localhost ~]# wget http://download.redis.io/releases/redis-6.0.6.tar.gz
[root@localhost ~]# tar xf redis-6.0.6.tar.gz -C /usr/local/
[root@localhost ~]# mv /usr/local/redis-6.0.6/ /usr/local/redis
[root@localhost ~]# cd /usr/local/redis/
[root@localhost redis]# make
[root@localhost redis]# make install

[root@localhost redis]# cp src/redis-server src/redis-cli /usr/bin/


如果是rhel8

#配好yum源和epel源后
dnf -y install scl-utils gcc-toolset-9 gcc-toolset-9-gcc-c++ gcc-toolset-9-binutils
scl enable gcc-toolset-9 bash #临时更改

2.配置开机自启

#新建redis.service服务文件
[root@localhost ~]# vim /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis Server Manager
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/usr/local/redis/src/redis-server /usr/local/redis/redis.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID

[Install]
WantedBy=multi-user.target


[root@localhost ~]# vim /usr/local/redis/redis.conf 
daemonize yes
……
supervised systemd



#刷新systemctl
systemctl daemon-reload
#启动redis
[root@localhost ~]# systemctl start redis
#设置redis开机自启动
[root@localhost ~]# systemctl enable redis
[root@localhost ~]# systemctl status redis
● redis.service - Redis Server Manager
   Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
   Active: active (running) since 四 2020-08-13 18:47:00 CST; 10s ago
  Process: 1401 ExecStart=/usr/local/redis/src/redis-server /usr/local/redis/redis.conf (code=exited, status=0/SUCCESS)
 Main PID: 1402 (redis-server)
   CGroup: /system.slice/redis.service
           └─1402 /usr/local/redis/src/redis-server 127.0.0.1:6379

8月 13 18:47:00 localhost.localdomain systemd[1]: Starting Redis Server Manager...
8月 13 18:47:00 localhost.localdomain redis-server[1401]: 1401:C 13 Aug 2020 18:47:00.235 # oO0OoO0OoO0Oo Redis ...0Oo
8月 13 18:47:00 localhost.localdomain redis-server[1401]: 1401:C 13 Aug 2020 18:47:00.235 # Redis version=6.0.6,...ted
8月 13 18:47:00 localhost.localdomain redis-server[1401]: 1401:C 13 Aug 2020 18:47:00.235 # Configuration loaded
8月 13 18:47:00 localhost.localdomain redis-server[1401]: 1401:C 13 Aug 2020 18:47:00.235 # WARNING supervised b...it.
8月 13 18:47:00 localhost.localdomain redis-server[1401]: 1401:C 13 Aug 2020 18:47:00.235 # systemd supervision ...und
8月 13 18:47:00 localhost.localdomain systemd[1]: Started Redis Server Manager.
Hint: Some lines were ellipsized, use -l to show in full.

3.设置密码

[root@localhost ~]# vim /usr/local/redis/redis.conf
requirepass 123456		//786行

[root@localhost ~]# systemctl restart redis
[root@localhost ~]# ss -tanl
State       Recv-Q Send-Q              Local Address:Port                             Peer Address:Port              
LISTEN      0      100                     127.0.0.1:25                                          *:*                  
LISTEN      0      128                     127.0.0.1:6379                                        *:*                  
LISTEN      0      128                             *:22                                          *:*                  
LISTEN      0      100                         [::1]:25                                       [::]:*                  
LISTEN      0      128                          [::]:22                                       [::]:*       


#登录认证
[root@localhost ~]# redis-cli 
127.0.0.1:6379> set foo bar
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> get foo
"bar"


#也可以-a选项登录
[root@localhost ~]# redis-cli -h 127.0.0.1 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set a 10
OK
127.0.0.1:6379> get a
"10"
#查看密码
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"



//在Redis集群中使用认证密码
//如果Redis服务器,使用了集群。除了在master中配置密码外,也需要在slave中进行相应配置。在slave的配置文件中找到如下行,去掉注释并修改与master相同的密码即可:

# masterauth master-password

4.常用命令

EXISTS key [key ...]

返回值

integer-reply,如下的整数结果

  • 1 如果key存在
  • 0 如果key不存在

例:

127.0.0.1:6379> EXISTS foo
(integer) 1
127.0.0.1:6379> EXISTS abc
(integer) 0

#keys * 查看所有key
127.0.0.1:6379> keys *
1) "a"
2) "foo"

EXISTS key [key ...]

key是否存在。

返回值

integer-reply,如下的整数结果

  • 1 如果key存在
  • 0 如果key不存在

例子

127.0.0.1:6379> set abc hello
OK
127.0.0.1:6379> EXISTS abc
(integer) 1
127.0.0.1:6379> EXISTS abcd
(integer) 0

APPEND key value

如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾。 如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。

返回值

Integer reply:返回append后字符串值(value)的长度。

例子

127.0.0.1:6379> EXISTS hello
(integer) 0
127.0.0.1:6379> APPEND hello "HELLO"
(integer) 5
127.0.0.1:6379> APPEND hello "WORLD"
(integer) 10
127.0.0.1:6379> GET hello
"HELLOWORLD"

DEL key [key ...]

删除指定的一批keys,如果删除中的某些key不存在,则直接忽略。

返回值

integer-reply: 被删除的keys的数量

例子

127.0.0.1:6379> SET a 1
OK
127.0.0.1:6379> SET b 2
OK
127.0.0.1:6379> set c 3
OK
127.0.0.1:6379> DEL a b 
(integer) 2
127.0.0.1:6379> keys *
1) "hello"
2) "foo"
3) "c"
4) "abc"

redis持久化存储

redis的数据存储在内存中,所以当我们关掉软件,或者拔掉电源时,内存中的数据就会丢失。针对此场景,这里提出持久化的方案。它的核心就是将内存中的数据存储到硬盘中进行持久化。

  • RDB: 基于快照的持久化,速度更快,一般用作备份。主从复制也是依赖于rdb持久化功能。
  • AOF:以追加的形式记录redis操作日志的文件。可以最大程度保证redis数据安全,类似于mysql的binlog。

方案一:RDB持久化

这个是redis默认的持久化的方案,它的原理是在一定时间内检测key的变化情况,然后持久化数据。它可以手动执行save来触发持久化数据,也可以通过配置redis.conf文件,执行定时执行。
RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。涉及核心配置如下:

[root@k8s001 ~]# cat /etc/redis.conf
dbfilename dump.rdb          # 指定rdb的数据文件   
dir ./                       # 指定rdb的数据路径


bind 0.0.0.0
requirepass redhat                # 指定redis的密码   
save 900 1                        # 代表900秒内,有1个修改key的操作,就进行持久化      
save 300 10                       # 300秒内,有10个修改类的操作,就持久化
save 60  10000                    # 60秒内,有10000个修改类的操作,就持久化

优点:速度快,适合做备份,主从复制就是基于RDB持久化功能实现

方案二:AOF持久化

这里不需要手动的save触发持久化。
记录服务器执行的所有变更操作命令(例如set del等),并在服务器启动时,通过重新执行这些命令来还原数据集。AOF 文件中的命令全部以redis协议的格式保存,新命令追加到文件末尾。
涉及核心配置如下:

[root@k8s001 ~]# cat /etc/redis.conf
appendonly yes            # 开启aof持久化的参数
appendfsync everysec      # 每秒进行一次aof持久化

优点:最大程度保证数据不丢失。
缺点:日志记录非常大

RDB 优点:访问性能最佳 缺点:数据不安全、fork消耗极大
AOF 优点:数据相对安全 缺点:访问性能相对不在最佳