Fork me on GitHub

redis基础

一:缓存概念

    缓存是为了调节速度不一致的两个或多个不同的物质的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用,比如CPU的一级、二级缓存是保存了CPU最近经常访问的数据,内存是保存CPU经常访问硬盘的数据,而且硬盘也有大小不一的缓存,甚至是物理服务器的raid 卡有也缓存,都是为了起到加速CPU 访问硬盘数据的目的,因为CPU的速度太快了,CPU需要的数据硬盘往往不能在短时间内满足CPU的需求,因此PCU缓存、内存、Raid 卡以及硬盘缓存就在一定程度上满足了CPU的数据需求,即CPU 从缓存读取数据可以大幅提高CPU的工作效率。

1.1:系统缓存

1.1.1:buffer与cache

buffer:缓冲也叫写缓冲,一般用于写操作,可以将数据先写入内存在写入磁盘,buffer 一般用于写缓冲,用于解决不同介质的速度不一致的缓冲,先将数据临时写入到里自己最近的地方,以提高写入速度,CPU会把数据线写到内存的磁盘缓冲区,然后就认为数据已经写入完成看,然后内核的线程在后面的时间在写入磁盘,所以服务器突然断电会丢失内存中的部分数据。

cache:缓存也叫读缓存,一般用于读操作,CPU读文件从内存读,如果内存没有就先从硬盘读到内存再读到CPU,将需要频繁读取的数据放在里自己最近的缓存区域,下次读取的时候即可快速读取。

1.1.2:cache的保存位置

客户端:浏览器

内存:本地服务器、远程服务器

硬盘:本机硬盘、远程服务器硬盘

速度对比:

客户端浏览器-内存-远程内存-硬盘-远程硬盘。

1.2:CDN缓存

1.2.1:CDN概念

    内容分发网络(Content Delivery Network),通过将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服务可用性。

第一降低机房的使用带宽,因为很多资源通过CDN就直接返回用户了;

第二解决不同运营商之间的互联,因为可以让联通的网络访问联通,让电信的网络访问电信,起到加速用户访问的目的;

第三:解决用户访问的地域问题,就近返回用户资源。

百度CDN:https://cloud.baidu.com/product/cdn.html

阿里CDN:https://www.aliyun.com/product/cdn

腾讯CDN:https://www.qcloud.com/product/cdn

1.2.2:CDN主要优势

    提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不通而进行不通级别的缓存,例如访问量最高的资源访问CDN 边缘节点的内存,其次的放在SSD或者SATA,再其次的放在云存储,这样兼顾了速度与成本。缓存-缓存到最快的地方如内存,缓存的数据准确命中率高,访问速度就快

调度准确-将用户调度到最近的边缘节点

性能优化-CDN 专门用于缓存响应速度快

安全相关-抵御攻击

节省带宽:由于用户请求由边缘节点响应,因此大幅降低到源站带宽。

1.3:应用层缓存

    Nginx、PHP等web服务可以设置应用缓存以加速响应用户请求,另外有些解释性语言比如PHP/Python不能直接运行,需要先编译成字节码,但字节码需要解释器解释为机器码之后才能执行,因此字节码也是一种缓存,有时候会出现程序代码上线后字节码没有更新的现象。

1.4:其他层面缓存

CPU缓存(L1的数据缓存和L1的指令缓存)、二级缓存、三级缓存

磁盘缓存

RAID卡

分布式缓存:redis、memcache

二:redis部署

2.1.1:redis简介:

    Redis(Remote Dictionary Server)在2009年发布,开发者Salvatore Sanfilippo是意大利开发者,他本想为自己的公司开发一个用于替换MySQL的产品Redis,但是没有想到他把Redis开源后大受欢迎,短短几年,Redis就有了很大的用户群体,目前国内外使用的公司有知乎网、新浪微博、GitHub等

    redis是一个开源的、遵循BSD协议的、基于内存的而且目前比较流行的键值数据库(key-value database),是一个非关系型数据库,redis提供将内存通过网络远程共享的一种服务,提供类似功能的还有memcache,但相比memcache,redis还提供了易扩展、高性能、具备数据持久性等功能。Redis在高并发、低延迟环境要求比较高的环境使用量非常广泛

2.1.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语言开发。

2.1.3:redis 典型应用场景

Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享

消息队列:ELK的日志缓存、部分业务的订阅发布系统

计数器:访问排行榜、商品浏览数等和次数相关的场景

缓存:数据查询、电商网站商品信息、新闻内容

微博/微信社交场合:共同好友、点赞评论等

2.2:Redis安装及使用

官方下载地址:http://download.redis.io/releases/

2.2.1:yum安装redis

1
2
3
4
5
[root@centos7 ~]#yum -y install redis
[root@centos7 ~]#systemctl start redis 端口号6379
[root@centos7 ~]#systemctl enable redis
[root@centos7 ~]# redis-cli
127.0.0.1:6379> info

2.2.2:编译安装redis

下载当前最新release版本redis 源码包:

2.2.2.1:编译安装命令

官方的安装命令:

https://redis.io/download

1
2
3
4
5
6
7
8
9
10
11
12
[root@centos7 src]#pwd
/usr/local/src
[root@centos7 src]#tar xf redis-5.0.3.tar.gz
[root@centos7 src]#cd redis-5.0.3
[root@centos7 src]#pwd
/usr/local/src/redis-5.0.3
[root@centos7 redis-5.0.3]#make PREFIX=/usr/local/redis [MALLOC=libc] install
[root@centos7 redis-5.0.3]#ll /usr/local/redis/
total 0
drwxr-xr-x 2 root root 134 Dec 27 11:28 bin
[root@centos7 redis-5.0.3]#mkdir /usr/local/redis/etc
[root@centos7 redis-5.0.3]#cp redis.conf /usr/local/redis/etc/

2.2.2.2:前台启动redis

1
[root@centos7 redis-5.0.3]#/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

2.2.2.3:解决当前的警告提示

2.2.2.3.1:tcp-backlog

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 request may be ignored so that a later reattempt at connection succeeds.

backlog参数控制的是三次握手的时候server端收到client ack确认号之后的队列值。

1
2
vim /etc/sysctl.conf
net.core.somaxconn = 512

2.2.2.3.2:vm.overcommit_memory

​ 0、表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

​ 1、表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

​ 2、表示内核允许分配超过所有物理内存和交换空间总和的内存

1
2
vim /etc/sysctl.conf
vm.overcommit_memory = 1

2.2.2.3.3:transparent hugepage

开启大页内存动态分配,需要关闭让redis 负责内存管理。

1
echo never > /sys/kernel/mm/transparent_hugepage/enabled

2.2.2.4:编辑redis服务启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@centos7 ~]#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/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf --supervised systemd
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

2.2.2.5:创建redis 用户和数据目录

1
2
3
[root@centos7 ~]#groupadd  -g 1000 redis && useradd   -u 1000 -g 1000 redis -s /sbin/nologin
[root@centos7 ~]#mkdir -pv /usr/local/redis/{logs,data,run}
[root@centos7 ~]#chown redis.redis -R /usr/local/redis/

2.2.2.6:创建命令软连接

1
[root@centos7 ~]#ln -sv /usr/local/redis/bin/redis-* /usr/bin/

2.2.2.7:重启redis服务

1
[root@centos7 ~]#systemctl restart redis

2.2.2.8:使用客户端连接redis

1
[root@centos7 ~]#/usr/local/redis/bin/redis-cli -h IP

2.2.2.9:编译安装后的命令

1
2
3
4
5
6
7
8
[root@redis-s1 ~]# ll /usr/local/redis/bin/
total 32656
-rwxr-xr-x 1 redis redis 4365488 Dec 13 09:21 redis-benchmark #redis性能测试工具
-rwxr-xr-x 1 redis redis 8088920 Dec 13 09:21 redis-check-aof #AOF文件检查工具
-rwxr-xr-x 1 redis redis 8088920 Dec 13 09:21 redis-check-rdb #RDB文件检查工具
-rwxr-xr-x 1 redis redis 4800752 Dec 13 09:21 redis-cli #redis #客户端工具
lrwxrwxrwx 1 redis redis 12 Dec 13 09:21 redis-sentinel -> redis-server #哨兵,软连接到server
-rwxr-xr-x 1 redis redis 8088920 Dec 13 09:21 #redis-server #redis 服务端

2.2.3:连接到Redis

主要分为运维人员的连接和程序的连接

2.2.3.1:本机非密码连接

1
redis-cli

2.2.3.2:跨主机非密码连接

1
redis-cli  -h HOSTNAME/IP  -p PORT

2.2.3.3:跨主机密码连接

1
redis-cli  -h HOSTNAME/IP  -p PORT  -a  PASSWORD

2.2.3.4:python连接方式

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/env  python
#Author: ZhangJie

import redis
import time
pool = redis.ConnectionPool(host="192.168.7.101", 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)

三:redis配置文件

  • 基本配置项
  • 网络配置项
  • 持久化相关配置
  • 复制相关的配置
  • 安全相关配置
  • Limit相关的配置
  • SlowLog相关的配置
  • INCLUDES
  • Advanced配置

3.1:网络配置项

bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听IP

protected-mode yes #redis3.2 之后加入的新特性,在没有设置bind IP和密码的时候只允许访问127.0.0.1:6379

port 6379 #监听端口

tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值。

timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时。

tcp-keepalive 300 #tcp 会话保持时间

3.2:通用配置项

daemonize no #认情况下 redis 不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成 yes,当redis作为守护进程运行的时候,它会写一个 pid 到 /var/run/redis.pid 文件里面

supervised no #和操作系统相关参数,可以设置通过upstart和systemd管理Redis守护进程,centos 7以后都使用systemd

pidfile /var/run/redis_6379.pid #pid文件路径

loglevel notice #日志级别

logfile “” #日志路径

databases 16 #设置db 库数量,默认16个库

always-show-logo yes #在启动redis 时是否显示log

3.3:快照配置项

save 900 1 #在900秒内有一个键内容发生更改就出就快照机制

save 300 10

save 60 10000

stop-writes-on-bgsave-error yes #快照出错时是否禁止redis 写入操作

rdbcompression yes #持久化到RDB文件时,是否压缩,”yes”为压缩,”no”则反之

rdbchecksum yes #是否开启RC64校验,默认是开启

dbfilename dump.rdb #快照文件名

dir ./ #快照文件保存路径​

3.4:复制相关的配置

slave-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:

  • 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求;
  • 如果slave-serve-stale-data设置为no,除去指定的命令之外的任何请求都会返回一个错误”SYNC with master in progress”。

slave-read-only yes #是否设置从库只读

repl-diskless-sync no #是否使用socket方式复制数据,目前redis复制提供两种方式,disk和socket,如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件,有2种方式:

  1. disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave
  2. socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave,

  3. disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件,

  4. socket的方式就是一个个slave顺序复制,只有在磁盘速度缓慢但是网络相对较快的情况下才使用socket方式,否则使用默认的disk方式

repl-diskless-sync-delay 5 #diskless复制的延迟时间,设置0为关闭,一旦复制开始还没有结束之前,master节点不会再接收新slave的复制请求,直到下一次开始

repl-ping-slave-period 10 #slave根据master指定的时间进行周期性的PING 监测

repl-timeout 60 #复制链接超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no #在socket模式下是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,

  • 如果你选择“yes”Redis将使用更少的TCP包和带宽来向slaves发送数据。但是这将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒;
  • 如果你选择了 “no” 数据传输到salve的延迟将会减少但要使用更多的带宽

repl-backlog-size 1mb #复制缓冲区大小,只有在slave连接之后才分配内存。

repl-backlog-ttl 3600 #多次时间master没有slave连接,就清空backlog缓冲区。

slave-priority 100 #当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。

3.5:安全相关配置

requirepass foobared #设置redis 连接密码

rename-command #重命名一些高危命令

3.6:Limit相关的配置

maxclients 10000 #最大连接客户端

maxmemory #最大内存,单位为bytes字节,8G内存的计算方式
$$
8(G)1024(MB)1024(KB)*1024(Kbyte)
$$
需要注意的是slave的输出缓冲区是不计算在maxmemory内。

3.7:APPEND ONLY MODE

appendonly no #是否开启AOF日志记录,默认 redis 使用的是 rdb 方式持久化,这种方式在许多应用中已经足够用了。但是 redis 如果中途宕机,会导致可能有几分钟的数据丢失,根据 save 来策略进行持久化,Append Only File 是另一种持久化方式,可以提供更好的持久化特性。Redis 会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时 Redis 都会先把这个文件的数据读入内存里,先忽略 RDB 文件。

appendfilename “appendonly.aof” #AOF文件名

appendfsync everysec #aof 持久化策略的配置;

  1. no 表示不执行fsync,由操作系统保证数据同步到磁盘;
  2. always表示每次写入都执行fsync,以保证数据同步到磁盘;
  3. everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。

no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。默认为no,表示”不暂缓”,新的aof记录仍然会被立即同步,Linux的默认fsync策略是30秒,如果为yes 可能丢失30秒数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐。

auto-aof-rewrite-percentage 100 # 当Aof log增长超过指定比例时,重写log file, 设置为0表示不自动重写Aof 日志,重写是为了使aof体积保持最小,而确保保存最完整的数据。

auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件尺寸

aof-load-truncated yes #是否加载由于其他原因导致的末尾异常的AOF文件(主进程被kill/断电等)

aof-use-rdb-preamble yes #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内存则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据)。

3.8: LUA SCRIPTING

lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒

3.9: REDIS CLUSTER

cluster-enabled yes #是否开启集群模式,默认是单机模式

cluster-config-file nodes-6379.conf #由node节点自动生成和的集群配置文件

cluster-node-timeout 15000 #集群中node节点连接超时时间

cluster-replica-validity-factor 10 #在执行故障转移的时候可能有些节点和master断开一段时间数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移

cluster-migration-barrier 1 #一个主节点拥有的至少正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。

cluster-require-full-coverage yes #集群槽位覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes情况下redis集群槽位验证不全就不再对外提供服务,而no则可以继续使用但是会出现查询数据查不到的情况(因为有数据丢失)。

cluster-replica-no-failover no

3.10: SLOW LOG

    Slow log 是 Redis 用来记录查询执行时间的日志系统,slow log 保存在内存里面,读写速度非常快,因此你可以放心地使用它,不必担心因为开启 slow log 而损害 Redis 的速度。

slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。

slowlog-max-len 128 #记录多少条慢日志保存在队列,超出后会删除最早的,以此滚动删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
127.0.0.1:6379> slowlog len

(integer) 14

127.0.0.1:6379> slowlog get

(integer) 14

(integer) 1544690617

(integer) 4

"slowlog"

127.0.0.1:6379> SLOWLOG reset

OK

3.2:redis持久化

    redis 虽然是一个内存级别的缓存程序,即redis 是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘上,从而实现数据持久保存的目的,redis支持两种不同方式的数据持久化保存机制,分别是RDB和AOF

3.2.1:RDB模式

RDB:基于时间的快照,只保留当前最新的一次快照,特点是执行速度比较快,缺点是可能会丢失从上次快照到当前快照未完成之间的数据。

    RDB实现的具体过程Redis从主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如dump.rdb.temp,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保存每一次做RDB快照的时候保存的数据都是完整的,因为直接替换RDB文件的时候可能会出现突然断电等问题而导致RDB文件还没有保存完整就突然关机停止保存而导致数据丢失的情况,可以手动将每次生成的RDB文件进程备份,这样可以最大化保存历史数据。

3.2.2:RDB模式的优缺点

优点:

  1. RDB快照保存了某个时间点的数据,可以通过脚本执行bgsave(非阻塞)或者save(阻塞)命令自定义时间点北备份,可以保留多个备份,当出现问题可以恢复到不同时间点的版本。
  2. 可以最大化o的性能,因为父进程在保存RDB 文件的时候唯一要做的是fork出一个子进程,然后的-操作都会有这个子进程操作,父进程无需任何的IO操作
  3. RDB在大量数据比如几个G的数据,恢复的速度比AOF的快

缺点:

  1. 不能时时的保存数据,会丢失自上一次执行RDB备份到当前的内存数据
  2. 数据量非常大的时候,从父进程fork的时候需要一点时间,可能是毫秒或者秒

3.2.3:AOF模式

AOF:按照操作顺序依次将操作添加到指定的日志文件当中,特点是数据安全性相对较高,缺点是即使有些操作是重复的也会全部记录。

    AOF和RDB一样使用了写时复制机制,AOF默认为每秒钟fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障的话顶多也就丢失1秒钟之内的数据,也可以设置不同的fsync策略,或者设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用户的正常请求而不受到写入AOF文件的IO影响

3.2.4:AOF模式优缺点

  1. AOF的文件大小要大于RDB格式的文件
  2. 根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec即每秒执行一次fsync

四:redis 数据类型

4.1:字符串(string)

    字符串是所有编程语言中最常见的和最常用的数据类型,而且也是redis最基本的数据类型之一,而且redis中所有的key的类型都是字符串。

4.1.1:添加一个key

1
2
3
4
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> type key1
string

4.1.2:获取一个key的内容

1
2
127.0.0.1:6379> get key1
"value1"

4.1.3:删除一个key

1
2
127.0.0.1:6379> del key1
(integer) 1

4.1.4:批量设置多个key

1
2
127.0.0.1:6379> MSET key1 value1 key2 value2
OK

4.1.5:批量获取多个key

1
2
127.0.0.1:6379> MSET key1 value1 key2 value2
OK

4.1.6:追加数据

1
2
3
4
127.0.0.1:6379> APPEND key1 append
(integer) 12
127.0.0.1:6379> get key1
"value1append"

4.1.7:数值递增

1
2
3
4
5
6
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> INCR num
(integer) 11
127.0.0.1:6379> get num
"11"

4.1.8:数值递减

1
2
3
4
5
6
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> decr num
(integer) 9
127.0.0.1:6379> get num
"9"

4.1.9:返回字符串key长度

1
2
127.0.0.1:6379> strlen key1
(integer) 12

4.2:列表(list)

    列表是一个双向可读写的管道,其头部是左侧尾部是右侧,一个列表最多可以包含2^32-1个元素即4294967295个元素。

4.2.1:生成列表并插入数据

1
2
3
4
127.0.0.1:6379> LPUSH list1 jack
(integer) 1
127.0.0.1:6379> TYPE list1
list

4.2.2:向列表追加数据

1
2
3
4
127.0.0.1:6379> LPUSH list1 tom
(integer) 2
127.0.0.1:6379> RPUSH list1 jack
(integer) 3

4.2.3:获取列表长度

1
2
127.0.0.1:6379> LLEN list1
(integer) 3

4.2.4:移除列表数据

1
2
3
4
127.0.0.1:6379> RPOP list1 #最后一个
"jack"
127.0.0.1:6379> LPOP list1 #第一个
"tom"

4.3:集合(set)

    Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

4.3.1:生成集合key

1
2
3
4
5
6
7
8
127.0.0.1:6379> SADD set1 v1 
(integer) 1
127.0.0.1:6379> SADD set2 v2 v4
(integer) 2
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

4.3.2:追加数值

追加的时候不能追加已经存在的数值

1
2
3
4
5
6
7
8
127.0.0.1:6379> SADD set1 v2 v3 v4
(integer) 3
127.0.0.1:6379> SADD set1 v2 #没有追加成功
(integer) 0
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

4.3.3:查看集合的所有数据

1
2
3
4
5
6
7
8
127.0.0.1:6379> SMEMBERS set1
1) "v4"
2) "v1"
3) "v3"
4) "v2"
127.0.0.1:6379> SMEMBERS set2
1) "v4"
2) "v2"

4.2.4:获取集合的差集

差集:已属于A而不属于B的元素称为A与B的差(集)

1
2
3
127.0.0.1:6379> SDIFF set1 set2
1) "v1"
2) "v3"

4.3.5:获取集合的交集

交集:已属于A且属于B的元素称为A与B的交(集)

1
2
3
127.0.0.1:6379> SINTER set1 set2
1) "v4"
2) "v2"

4.3.6:获取集合的并集

并集:已属于A或属于B的元素为称为A与B的并(集)

1
2
3
4
5
127.0.0.1:6379> SUNION  set1 set2
1) "v2"
2) "v4"
3) "v1"
4) "v3"

4.4:sorted set(有序集合)

    Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序,序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1), 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

4.4.1:生成有序集合

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> ZADD zset1 1 v1 
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v3
(integer) 1
127.0.0.1:6379> ZADD zset1 3 v4
(integer) 1
127.0.0.1:6379> TYPE zset1
zset
127.0.0.1:6379> TYPE zset2
none

排行案例:

1
2
3
4
5
6
7
8
9
192.168.7.104:6379> ZADD paihangbang 10 key1 20 key2 30 key3
(integer) 3
192.168.7.104:6379> ZREVRANGE paihangbang 0 -1 withscores
1) "key3"
2) "30"
3) "key2"
4) "20"
5) "key1"
6) "10"

4.4.2:批量添加多个数值

1
2
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 4 v3 5 v5
(integer) 4

4.4.3:获取集合的长度数

1
2
3
4
127.0.0.1:6379> ZCARD zset1 
(integer) 4
127.0.0.1:6379> ZCARD zset2
(integer) 4

4.4.4:基于索引返回数值

1
2
3
4
5
6
7
8
127.0.0.1:6379> ZRANGE zset1 1 3
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> ZRANGE zset1 0 2
1) "v1"
2) "v2"
3) "v3"

4.4.5:返回某个数值的索引

1
2
3
4
5
127.0.0.1:6379> ZRANK zset1 v2
(integer) 1

127.0.0.1:6379> ZRANK zset1 v3
(integer) 2

4.5:哈希(hash)

    hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象,Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

4.5.1:生成hash key

1
2
3
4
5
6
7
127.0.0.1:6379> HSET hset1 name tom 
(integer) 1
127.0.0.1:6379> HSET hset1 age 18
(integer) 1
或者 127.0.0.1:6379> HMSET hset1 name tom age 18
127.0.0.1:6379> TYPE hset1
hash

4.5.2:获取hash key字段值

1
2
3
4
127.0.0.1:6379> HGET hset1 name
"tom"
127.0.0.1:6379> HGET hset1 age
"18"

4.5.3:删除一个hash key的字段

1
2
127.0.0.1:6379> HDEL hset1 age
(integer) 1

4.5.4:获取所有hash表中的字段

1
2
3
4
5
127.0.0.1:6379> HMSET hset1 name tom age 19
(integer) 1
127.0.0.1:6379> HKEYS hset1
1) "name"
2) "age"

五:消息队列

    消息队列主要分为两种,分别是生产者消费者模式和发布者订阅者模式,这两种模式Redis都支持。

5.1:生产者消费者模式

    在生产者消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至指定的频道(channel)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步的操作就直接返回数据给外部请求,如果还有下一步的操作就再将任务发布到另外一个频道,由另外一个消费者继续监听和处理。

5.1.1:模式介绍

    生产者消费者模式下,多个消费者同时监听一个队里,但是一个消息只能被最先抢到消息的消费者消费,即消息任务是一次性读取和处理,此模式在分布式业务架构中非常常用,比较常用的软件还有RabbitMQ、Kafka、RocketMQ、ActiveMQ等

5.1.2:队列介绍

    队列当中的 消息由不同的生产者写入也会有不同的消费者取出进行消费处理,但是买一个消息一定是只能被取出一次也就是被消费一次。

5.1.3:生产者发布消息

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@centos7 ~]# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> LPUSH channel1 msg1 #从管道的左侧写入
(integer) 1
127.0.0.1:6379> LPUSH channel1 msg2
(integer) 2
127.0.0.1:6379> LPUSH channel1 msg3
(integer) 3
127.0.0.1:6379> LPUSH channel1 msg4
(integer) 4
127.0.0.1:6379> LPUSH channel1 msg5
(integer) 5

5.1.4:查看队列所有消息

1
2
3
4
5
6
127.0.0.1:6379> LRANGE channel1  0  -1
1) "msg5"
2) "msg4"
3) "msg3"
4) "msg2"
5) "msg1"

5.1.5:消费者消费消息

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> RPOP channel1 #从管道的右侧消费
"msg1"
127.0.0.1:6379> RPOP channel1
"msg2"
127.0.0.1:6379> RPOP channel1
"msg3"
127.0.0.1:6379> RPOP channel1
"msg4"
127.0.0.1:6379> RPOP channel1
"msg5"
127.0.0.1:6379> RPOP channel1
(nil)

5.1.6:再次验证队列消息

1
2
127.0.0.1:6379>  LRANGE channel1  0  -1 
(empty list or set) #队列中的消息已经被已全部消费完毕

5.2:发布者订阅模式

5.2.1:模式简介

    在发布者订阅者模式下,发布者将消息发布到指定的channel里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机模式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。

此模式常用语群聊天、群通知、群公告等场景。

Subscriber:订阅者

Publisher:发布者

Channel:频道

5.2.2:订阅者监听频道

1
2
3
4
5
6
7
8
[root@centos ~]# redis-cli 
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SUBSCRIBE channel1 #订阅者订阅指定的频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1

5.2.3:发布者发布消息

1
2
3
4
5
127.0.0.1:6379> PUBLISH channel1 test1 #发布者发布消息
(integer) 2
127.0.0.1:6379> PUBLISH channel1 test2
(integer) 2
127.0.0.1:6379>

5.2.4:订阅多个频道

订阅指定的多个频道

1
SUBSCRIBE channel1 channel2

5.2.5:订阅所有频道

1
127.0.0.1:6379> PSUBSCRIBE *

5.2.6:订阅匹配的频道

1
PSUBSCRIBE chann* #匹配订阅多个频道

六:redis其他命令

6.1:查看当前redis配置、以及不重启更改redis配置等

1
127.0.0.1:6379> CONFIG GET *

6.1.1:更改最大内存

1
2
3
4
5
127.0.0.1:6379> CONFIG set maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG get maxmemory
1) "maxmemory"
2) "8589934592"

6.1.2:设置连接密码(临时有效)

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> [root@centos7 ~]#redis-cli
127.0.0.1:6379> CONFIG SET requirepass 123456
OK
127.0.0.1:6379> CONFIG GET requirepass
(error) NOAUTH Authentication requirepass.
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "123456"
127.0.0.1:6379>
OK

6.2:显示当前节点redis运行状态信息

1
127.0.0.1:6379> info

6.3:切换数据库

1
2
3
127.0.0.1:6379> SELECT 1
ok
127.0.0.1:6379[1]>

6.4:查看当前库下的所有key

1
127.0.0.1:6379> keys *

6.5:手动在后台执行RDB持久化操作

1
127.0.0.1:6379>BGSAVE

6.6:返回当前库下的所有key 数量

1
127.0.0.1:6379>DBSIZE

6.7:清空当前数据库

1
127.0.0.1:6379>FLUSHDB

6.8:清空所有数据库

1
127.0.0.1:6379>FLUSHALL
---------------- The End ----------------
坚持原创技术分享,您的支持将鼓励我继续创作!