Redis 日常操作

words: 3.3k    views:    time: 13min

官方文档:https://redis.io/commands/

Remote Dictionary Server远程字典服务,是一个开源的使用C语言编写的Key-Value数据库。redis是一个基于内存的存储系统,当然也支持持久化,它会周期性的把更新的数据写入磁盘(RDB)或者把修改操作追加的记录文件(AOF),并在此基础上实现master-slave(主从)同步。所以redis可以用于高速缓存(内存&多路复用IO),同时它支持多种数据类型,以及集群和事务的操作,进而也可以用于发布订阅、地图信息分析、计数器等系统

redis.conf

Redis安装很简单,官网下载安装包后直接解压执行:make install,安装完之后在目录 \usr\local\bin 下可以看到redis的可执行文件

然后修改配置redis.conf,并在启动时需要指定配置文件,比如:redis-server /path/to/redis.conf,当然也可以用多个配置文件启动多个redis实例

以下是一个配置模板,并忽略了部分不常用的配置

redis.conf 6.2.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
################################################## INCLUDES #################################################
# 配置包含,如果有相同配置值,后面的会覆盖前面的
# include /path/to/other.conf

################################################## MODULES ##################################################
# 加载模块
# loadmodule /path/to/other_module.so

################################################## NETWORK ##################################################
# 绑定地址,允许哪些网络连接,比如127.0.0.1只允许本地连接,不设置或者0.0.0.0则允许所有连接
bind 127.0.0.1 -::1

# 默认开启保护模式
protected-mode yes

# 默认监听端口:6379
port 6379

# tcp服务默认有两个队列:即tcp-backlog用于存放未连接队列,和somaxconn用于存放已连接队列
# 在完成tcp三次握手之前,首先进入未连接队列,完成tcp三次握手之后正式建立连接,进入已连接队列
#
# 因为redis是单线程的,如果出现慢查询的话,会导致已连接队列堆满,从而新accept的连接不能被处理,
# 不能进入已连接队列,进一步导致未连接(状态为SYN_RECV)队列堆满,
# 然后新连接的客户端将一直处于SYN_SENT状态,等待服务的ACK应答,最终连接超时
#
# 关于TCP三次握手
# 1. 建立连接,客户端发送syn包(syn=j)到服务,并进入SYN_SEND状态,等待服务确认;
# 2. 服务收到syn包,确认客户端的SYN(ack=j+1),然后也发送一个SYN包(syn=k),即SYN+ACK包,进入SYN_RECV状态;
# 3. 客户端收到服务的SYN+ACK包,向服务发送确认ACK(ack=k+1),发送完毕之后,客户端和服务进入ESTABLISHED状态;
#
# 内核配置:
# 修改未连接队列长度:vim /proc/sys/net/ipv4/tcp_max_syn_backlog
# 修改已连接队列长度:vim /proc/sys/net/core/somaxconn
# 如果想永久修改这两个内核参数的话可以写到配置文件,改完之后执行:sysctl -p 生效:
# vim /etc/sysctl.conf
# net.ipv4.tcp_max_syn_backlog = 2048
# net.core.somaxconn = 2048
#
# 另外,这里tcp-backlog配置时注意不要大于somaxconn的值,否则会被Linux静默地覆盖成somaxconn的值
tcp-backlog 511

# 对于Linux,如果redis客户端和服务都在同一台机子,可以使用unix socket,不需要走TCP监听网络端口
# UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC),
# 它不需要经过网络协议栈、打包拆包、计算校验和、维护序号和应答等,
# 只需将应用层数据从一个进程拷贝到另一个进程,因此可以进一步降低延时
unixsocket /run/redis.sock
# 配置unix socket使用文件的权限
unixsocketperm 700

# 连接最大空闲时间(单位秒),即客户端在一定时间内没有任何操作,则关闭该连接,默认0表示关闭此设置
timeout 0

# 配置TCP连接是否为长连接,心跳信号由服务维护,周期性向客户端发送探测消息,因此长连接会额外增加服务侧的开销
tcp-keepalive 300

################################################## GENERAL ##################################################
# 默认不是在后台运行,一般改成yes
daemonize no

# 通过upstart和systemd管理Redis守护进程
# no :没有监督互动
# upstart :通过将Redis置于SIGSTOP模式来启动信号
# systemd :signal systemd将READY = 1写入$NOTIFY_SOCKET
# auto :检测upstart或systemd方法,基于UPSTART_JOB或NOTIFY_SOCKET环境变量
supervised auto

# 后台运行时,Redis会将pid记在/var/run/redis.pid,因此当运行多个redis实例时,应该指定不同的pid文件和端口
pidfile /var/run/redis.pid

# log级别
# debug 调试信息,一般用于开发测试
# varbose 有用的信息,不像debug会记录那么多
# notice 普通的verbose,一般用于生产环境
# warning 只记录重要或者警告信息
loglevel notice

# log文件地址,默认stdout,如果配置为空,并且是后台运行模式,则会输出到/dev/null
logfile /var/log/redis/redis.log

syslog-enabled no
syslog-ident redis
syslog-facility local0

crash-log-enabled no
crash-memcheck-enabled no

# 可用数据库数,默认为16,默认选择数据库0
databases 16

always-show-logo no

set-proc-title yes

# supported:
#
# {title} Name of process as executed if parent, or type of child process.
# {listen-addr} Bind address or '*' followed by TCP or TLS port listening on, or
# Unix socket if only that's available.
# {server-mode} Special mode, i.e. "[sentinel]" or "[cluster]".
# {port} TCP port listening on, or 0.
# {tls-port} TLS port listening on, or 0.
# {unixsocket} Unix domain socket listening on, or "".
# {config-file} Name of configuration file used.
proc-title-template "{title} {listen-addr} {server-mode}"

############################################### SNAPSHOTTING ###############################################
## 默认RDB持久化方式 :周期性将redis中数据快照到dump.rdb文件
## 优势 :备份恢复简单。RDB通过子进程完成持久化工作,相对比AOF启动效率高
## 劣势 :服务器故障会丢失几分钟内的数据

# 900秒内至少有1个key被改变,则持久化快照
save 900 1
# 300秒内至少有300个key被改变,则持久化快照
save 300 10
# 60秒内至少有10000个key被改变,则持久化快照
save 60 10000

# 默认当持久化失败时则拒绝写入动作,比如磁盘满了,则拒绝set操作
stop-writes-on-bgsave-error yes

# 默认持久化到rdb文件时进行压缩
rdbcompression yes

# 默认对rdb文件进行校验
rdbchecksum yes

sanitize-dump-payload no

# 默认持久化文件名为dump.rdb
dbfilename dump.rdb

# 在没有启用持久性的情况下,删除复制实例中使用的RDB文件,默认禁用
rdb-del-sync-files no

# 默认持久化文件目录为当前目录
dir ./

常用操作

redis自带客户端,通过 redis-cli -h 127.0.0.1 -p 6379 便可以连接本地实例,然后进行操作,所有的操作都是原子的

db 操作:

select 3 切换数据库
dbsize 查看当前库大小
flush db 清空当前数据库
flushall 清空所有数据库

key 操作:

keys * 获取所有的key
exists key 是否存在key
move key 1 从数据库1中删除key
type key 查看key类型
expire key 10 设置key过期时间
ttl key 查看key剩余时间

String 操作:

set key value 设置key的值
get key 获取key的值
mset k1 v1 k2 v2 k3 v3 设置多值
mget k1 k2 k3 获取多值
setnx key value 如果当前key不存在,则设置成功
msetnx k1 v1 k2 v2 如果当前key不存在,则设置成功(一个失败则全部失败)
getset key value 返回当前值,并设置新值
setex key 10 value 设置key的值,并设置10秒过期时间
strlen key 查看key对应值的长度
append key value 在key的值后面拼接字符串,如果key不存在则相当于set
setrange key 2 value 设置key的值,并从位置2开始的地方进行覆盖
getrange key 0 5 获取key的值,并截取位置0-5
incr key key的值+1
decr key key的值-1
incrby key 10 key的值+10
decrby key 10 ey的值-10

场景:使用mset/mget存取对象,相对直接存取json可以更灵活的操作,比如存取人员信息

1
2
mset user:1:name shanhm user:1:age 30 user:1:sex man     
mget user:1:name user:1:age user:1:sex

List 操作:

lpush key v1 v2 从头部向列表中放入值
rpush key v3 v4 从尾部向列表中放入值
lpop key 从头部弹出值
rpop key 从尾部弹出值
lindex key index 根据索引获取值
lrange key 0 1 按照索引(首尾)获取多值
llen key 获取列表长度
lrem key count value 从列表中移除指定个数(count)的值(value)
ltrim key index count 根据下标(index)截取(count)个元素,改变原列表
lset key index value 更新列表指定位置的值,前提key列表已经存在,且index存在
linsert key before|after v1 v2 在v1的前后插入值v2
rpoplpush key1 key2 组合命令:将列表key1中的尾部元素移到列表key2头部

redis中的list本质上是一个双向链表,其结构如下:

list
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct listNode {

struct listNode* prev; //前驱节点

struct listNodee* next; //后继结点

void* value; //节点值, 因为是void*类型,所以可以存储各种类型的值
} listNode;

typedef struct list {

listNode* head; //头结点, prev为NULL

listNode* tail; //尾节点, next为NULL

int len; //链表长度

void *(*dup)(void *ptr); //节点值复制函数duplicated

void (*free)(void *ptr); //节点值释放函数

int (*match)(void *ptr, void *key); //节点值对比函数
}

Set 操作:

sadd key value 向set中添加元素,如果已存在则失败
srem key value 从set中移除值
smembers key 查看set中所有元素
sismember key value 查看set(key)中是否存在元素value
scard key 查看set的元素个数
srandmember key 从set中随机抽取1个元素
srandmember key n 从set中随机抽取n个元素
spop key 随机删除一个元素
smove k1 k2 value 将k1中的值移到k2中
sdiff k1 k2 取k1与k2的差集(在k1中,不在k2中)
sinter k1 k2 取k1和k2的交集
sunion k1 k2 取k1和k2的并集

Hash 操作:

hset key field value 设置map的字段值
hget key field 获取map指定字段的值
hgetall key 获取map所有字段-值
hdel key field 删除map指定的字段
hmset key field1 value1 field2 value2 设置map多个字段值
hmget key field1 field2 获取map多个字段的值
hlen key 获取map的字段数
hexists key field 查看map是否存在字段
hkeys key 获取map所有字段
hvals key 获取map所有字段值

map支持string中类似的操作,比如 setnx 对应 hsetnx,incrby 对应 hincrby

Zset 操作

zset即有序集合,可以给定score以便排序

zadd key score value 设置值,指定score
zadd key score1 value1 score2 value2 设置多个值
zrange key 0 1 withscores 按索引排序获取
zrevrange key 0 -1 withscores 按索引倒叙获取
zrangebyscore key -inf +inf withscores 按score排序获取(指定区间)
zrevrangebyscore key 500 100 withscores 按score倒叙获取(指定区间)
zrem key value 删除指定元素
zcard key 获取元素个数
acount key score1 score2 获取指定区间元素个数

geospatial 操作:

地理位置集合(经度 纬度 value),其底层也是通过zset来实现的,所以支持zset的所有命令,比如可以通过zrange排序获取位置,或者zrem删除位置

geoadd key 116.40 39.90 beijing 添加城市北京
geopos key beijing 获取指定城市位置
geodist key beijing shanghai 单位 获取两个位置距离,单位(m/km/mi英里/ft英尺)
georadius geodist key 经度 纬度 半径 单位 withcoord count 获取指定位置(坐标)指定半径内的位置
georadius geodist key beijing 半径 单位 withcoord count 获取指定位置指定半径内的位置

hyperloglog 操作

基数统计算法,就是统计集合中不重复的元素个数。通常也许可以通过set去重来count,但对于超大集合的内存消耗显然是不能接受的,这时hyperloglog算法可以保证只消耗12kb内存的情况下估算出集合基数,而且出错率只有0.81%

pfadd key value ... 添加元素,可多值
pfcount key 获取基数
pfmerge key3 key1 key2 合并key1集合,key2集合,结果为key3集合

bitmaps 操作:

位图,即位存储,只保存0和1两个状态

setbit key 0 1 设置第0位为1
setbit key 1 0 设置第1位为0
getbit key 1 获取第1位值
bitcount key 统计值为1的位数

事务操作:

redis事务即一组命令集合,将所有命令序列化,然后按照顺序执行,所以只有在发起执行命令时事务才开始进行,它可以保证一次性、顺序性、排他性,但是没有事务隔离级别的概念。另外,如果命令错误则直接放弃,而如果是命令执行失败则正常进行。

1.开启事务(multi)
2.命令入队(…)
3.执行事务(exec) 或者 放弃事务(discard)

乐观锁:

可以通过 watch 在事务开启前对key的值进行监视,如果在事务执行时发现key的发生变化,则事务失败,一般如果失败之后,会在再次监视之前会先解除锁以便获取最新的值进行监视

1.解除锁(unwatch)
2.监视乐观锁(watch key)
3.开启事务(multi)
4.命令入队(…)
5.执行事务(exec)


参考: