一、数据类型
1、String
String 类型是 Redis 最基本的数据类型,一个 key 对应一个 value,String 类型的值最大能存储 512MB。
String类型一般用于缓存、限流、计数器、分布式锁、分布式Session。
操作
127.0.0.1:6379> set k1 v1 #设置k1的值
OK
127.0.0.1:6379> get k1 #获取k1的值
"v1"
127.0.0.1:6379> mset k2 v2 k3 v3 #同时设置k2,k3的值
OK
127.0.0.1:6379> mget k2 k3 #获取k2,k3的值
1) "v2"
2) "v3"
127.0.0.1:6379> getset k1 v11 #更改k1的值,并返回k1的旧值
"v1"
127.0.0.1:6379> setex k4 10 v4 #设置k4的值,并将k4的过期时间设为10秒
OK
127.0.0.1:6379> get k4 #10秒后获取k4的值,为空
(nil)
127.0.0.1:6379> setnx k4 v4 #当k4不存在时,设置k4的值,设置成功
(integer) 1
127.0.0.1:6379> setnx k1 v1 #k1存在,设置失败
(integer) 0
127.0.0.1:6379> get k4
"v4"
127.0.0.1:6379> get k1
"v11"
127.0.0.1:6379> set k5 100
OK
127.0.0.1:6379> incr k5 #将k5中储存的数值加1
(integer) 101
127.0.0.1:6379> get k5
"101"
127.0.0.1:6379> incrby k5 19 #将k5中储存的数值加19
(integer) 120
127.0.0.1:6379> get k5
"120"
127.0.0.1:6379> decr k5 #将k5中储存的数值减1
(integer) 119
127.0.0.1:6379> get k5
"119"
127.0.0.1:6379> decrby k5 19 #将k5中储存的数值减19
(integer) 100
127.0.0.1:6379> get k5
"100"
127.0.0.1:6379> append k1 v22 #如果 key 已经存在并且是一个字符串,APPEND 命令将指
(integer) 6 #定的 value 追加到该 key 原来值 value 的末尾
127.0.0.1:6379> get k1
"v11v22"
2、List
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2^32^ - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
List类型一般用于关注人、简单队列等。
操作
127.0.0.1:6379> lpush k1 1 2 3 4 5 #将一个或多个值插入到列表头部
(integer) 5
127.0.0.1:6379> lrange k1 0 -1 #获取k1内的元素,(0,-1)代表所有
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lpop k1 2 #移出k1前2个元素,并返回该值
1) "5"
2) "4"
127.0.0.1:6379> lrange k1 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lpushx k1 4 5 #将4,5插入到已存在的k1键头部
(integer) 5
127.0.0.1:6379> lrange k1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> rpush k1 6 7 #将6,7添加到k1尾部
(integer) 7
127.0.0.1:6379> lrange k1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "6"
7) "7"
127.0.0.1:6379> rpop k1 2 #移出k1尾部2个元素
1) "7"
2) "6"
127.0.0.1:6379> lrange k1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> llen k1 #获取k1的长度
(integer) 5
127.0.0.1:6379> ltrim k1 1 -2 #删除在范围(1,-2)以外的元素
OK
127.0.0.1:6379> lrange k1 0 -1
1) "4"
2) "3"
3) "2"
3、Set
Redis 的 Set 是 String 类型的无序集合。集合中成员是唯一的,这就意味着集合中不能出现重复的数据。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32^ - 1 (4294967295, 每个集合可存储40多亿个成员)。
Set类型一般用于赞、踩、标签、好友关系等。
基础操作
127.0.0.1:6379> sadd k1 a b c d e #向k1集合添加成员
(integer) 5
127.0.0.1:6379> SMEMBERS k1 #查看k1中所有的成员
1) "d"
2) "a"
3) "c"
4) "b"
5) "e"
127.0.0.1:6379> SCARD k1 #获取集合的成员数
(integer) 5
127.0.0.1:6379> SISMEMBER k1 f #查看f是否是k1中的成员(0代表否,1代表是)
(integer) 0
127.0.0.1:6379> SISMEMBER k1 e
(integer) 1
127.0.0.1:6379> sadd k2 a c e f g
(integer) 5
127.0.0.1:6379> SDIFF k1 k2 #返回k1与k2的差集,k1在前,k2在后,返回的是k2
1) "d" #中没有k1的成员,这里返回k2中没有k1的b、d
2) "b"
127.0.0.1:6379> SDIFF k2 k1
1) "f"
2) "g"
127.0.0.1:6379> SINTER k1 k2 #返回k1、k2的交集
1) "a"
2) "c"
3) "e"
127.0.0.1:6379> SUNION k1 k2 #返回k1、k2的并集
1) "g"
2) "a"
3) "c"
4) "e"
5) "d"
6) "f"
7) "b"
127.0.0.1:6379> spop k1 1 #随机删除k1中的一个成员并返回该值
1) "b"
127.0.0.1:6379> spop k1 1
1) "d"
4、Zset
Redis 有序集合和集合一样也是string类型元素的集合且不允许重复的成员。不同的是每个元素都会关联一个==double类型的分数==。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 2^32^ - 1 (4294967295, 每个集合可存储40多亿个成员)。
Zset类型一般用于排行榜等。
基础操作
127.0.0.1:6379> zadd k1 60 'zhangsan' 70 'lisi' 80 'wangwu' 90 'xiaohong'
(integer) 4 #添加成绩以及成员
127.0.0.1:6379> ZCARD k1 #返回k1的成员数
(integer) 4
127.0.0.1:6379> ZCOUNT k1 60 80 #返回指定分数返回的成员数
(integer) 3
127.0.0.1:6379> ZINCRBY k1 5 'zhangsan' #增加并返回指定成员的指定分数
"65"
127.0.0.1:6379> ZRANGE k1 0 -1 #返回索引区间内的成员
1) "zhangsan"
2) "lisi"
3) "wangwu"
4) "xiaohong"
127.0.0.1:6379> ZRANGE k1 0 -1 withscores #返回索引区间内的成员及分数
1) "zhangsan"
2) "65"
3) "lisi"
4) "70"
5) "wangwu"
6) "80"
7) "xiaohong"
8) "90"
127.0.0.1:6379> zrem k1 'xiaohong' #删除k1中的成员以及分数
(integer) 1
127.0.0.1:6379> ZREVRANK k1 'zhangsan' #返回有序集合中指定成员的排名,有序集成员按
(integer) 2 #分数值递减(从大到小)排序
127.0.0.1:6379> ZREVRANK k1 'wangwu'
(integer) 0
127.0.0.1:6379> ZSCORE k1 'lisi' #返回k1中,成员的分数值
"70"
5、Hash
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。Redis 中每个 hash 可以存储 2^32^ - 1 键值对(40多亿)。
Hash类型一般用于存储用户信息、用户主页访问量、组合查询等。
基础操作
127.0.0.1:6379> hset k1 id 1 name 'zhangsan' gender 'M'
(integer) 3 #设置k1中field和value的值
127.0.0.1:6379> hget k1 name #获取k1中name的值
"zhangsan"
127.0.0.1:6379> HGETALL k1 #获取k1所有的field以及值
1) "id"
2) "1"
3) "name"
4) "zhangsan"
5) "gender"
6) "M"
127.0.0.1:6379> HEXISTS k1 birth #判断k1中是否存在birth字段
(integer) 0
127.0.0.1:6379> HEXISTS k1 id
(integer) 1
127.0.0.1:6379> hsetnx k1 name 'lisi' #当name字段不存在时,才设置该字段以及值,
(integer) 0 #当name字段存在时,对原数据不影响
127.0.0.1:6379> HGETALL k1
1) "id"
2) "1"
3) "name"
4) "zhangsan"
5) "gender"
6) "M"
7) "birth"
8) "2000-01-01"
127.0.0.1:6379> hkeys k1 #获取k1中的所有字段
1) "id"
2) "name"
3) "gender"
4) "birth"
127.0.0.1:6379> HVALS k1 #获取k1中的所有值
1) "1"
2) "zhangsan"
3) "M"
4) "2000-01-01"
127.0.0.1:6379> hlen k1 #获取k1中字段的数量
(integer) 4
127.0.0.1:6379> hmget k1 name id #获取指定字段的值
1) "zhangsan"
2) "1"
127.0.0.1:6379> HINCRBY k1 id 2 #对k1中的id字段加2
(integer) 3
127.0.0.1:6379> hget k1 id
"3"
127.0.0.1:6379> hdel k1 birth #删除k1中的birth字段
(integer) 1
127.0.0.1:6379> hkeys k1
1) "id"
2) "name"
3) "gender"
6、Bitmaps
1)Bitmaps本身不是一种数据类型,实际上它就是字符串(key-value),但是它可以对字符串的位进行操作。
2)Bitmaps单独提供了一套命令,所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。
7、HyperLogLog
在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用Redis的incr、incrby轻松实现。
但像UV(UniqueVisitor,独立访客)、独立IP数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8},那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
解决基数问题有很多种方案:
1)数据存储在MySQL表中,使用distinct count计算不重复个数
2)使用Redis提供的hash、set、bitmaps等数据结构来处理
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。
为了能够降低一定的精度来平衡存储空间,Redis推出了HyperLogLog。
HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
基础操作
127.0.0.1:6379> PFADD course "redis" #添加指定元素
(integer) 1
127.0.0.1:6379> PFADD course "mongodb"
(integer) 1
127.0.0.1:6379> PFADD course "mysql"
(integer) 1
127.0.0.1:6379> PFADD course "redis"
(integer) 0
redis 127.0.0.1:6379> PFCOUNT course #返回给定 HyperLogLog 的基数估算值
(integer) 3
127.0.0.1:6379> PFADD course1 "redis"
(integer) 0
redis 127.0.0.1:6379> pfmerge course course1 #将多个 HyperLogLog 合并为一个 HyperLogLog
(integer) 1
redis 127.0.0.1:6379> PFCOUNT course
(integer) 3
8、Geospatial
Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。
基础操作
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90
beijing
127.0.0.1:6379> geopos china:city beijing shanghai km #获取两城市之间的直线距离
#有效的经度从 -180 度到 180 度。有效的纬度从 -85.05112878 度到 85.05112878 度。
当坐标位置超出指定范围时,该命令将会返回一个错误。
已经添加的数据,是无法再次往里面添加的。
二、Redis数据持久化
Redis的配置文件默认是安装目录下的redis.conf文件,我们可以使用cp命令把配置文件移动到/etc/目录下
1、RDB
RDB 方式适合大规模的数据恢复,并且对数据完整性和一致性要求不高更适合使用。
优势:
1.节省磁盘空间
2.恢复速度快
劣势
Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑,虽然Redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。,在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。
vim /etc/redis.conf
……
412################################ SNAPSHOTTING#共##共共########
413
414 # Save the DB to disk.
*415
416 #save<seconds> <changes> <seconds> <changes>
417在
418# Redis will save the DB if the given number of seconds elapsed and it
419 # surpassed the given number of write operations against the DB.420#421 # Snapshotting can be completely disabled with a single empty string argument422 # as in following example:
423#
424save
425年426# Unless specified otherwise, by default Redis will save the DB:427* After 3600 seconds (an hour) if at least 1 change was performed428 #* After 300 seconds (5 minutes) if at least 100 changes were performed在429* After 60 seconds if at least 10000 changes were performed
#430
431# You can set these explicitly by uncommenting the following line.
432#
433 #3600 1 300 100 60 10000save
434605save
435By default Redis will stop accepting writes if RDB snapshots are enabled436 # (at least one save point) and the latest background save failed.
……
save "" 代表RDB备份方式关闭,以下是配置示例
save 900 1 # 在900s内如果有1条数据被写入,则产生一次快照。
save 300 10 # 在300s内如果有10条数据被写入,则产生一次快照
save 60 10000 # 在60s内如果有10000条数据被写入,则产生一次快照
stop-writes-on-bgsave-error yes # 如果为yes则表示,当备份进程出错的时候,主进程就停止进行接受新的写入操作,这样是为了保护持久化的数据一致性的问题。
我们把持久化的策略修改为 save 30 5,表示 30 秒内写入 5 条数据就产生一次快照,也就是生成 rdb 文件。设置后使用systemctl restart redis命令重启服务
我们发现在默认安装包路径下,有了dump.rdb文件
[root@localhost]# ll dump.rdb
-rw--r-- root root 139 7月 20 16:52 dump.rdb
2、AOF
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据。简单说,Redis 重启时会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
在Redis的默认配置中AOF(Append Only File)持久化机制是没有开启的,要想使用AOF持久化需要先开启此功能。AOF持久化会将被执行的写命令写到AOF文件末尾,以此来记录数据发生的变化,因此只要Redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集。
修改 redis.conf 配置文件:
1.通过修改redis.conf配置中appendonly yes来开启AOF持久化
2.通过appendfilename指定日志文件名字(默认为appendonly.aof)
- 通过appendfsync指定日志记录频率
# Please check https://redis.io/topics/persistence for more information#
appendonly yes
# The base name of the appendonly file.
#
# Redis 7 and newer use a set of append-only files to persist the dataset
# and changes applied to it. There are two basic types of files in use:
#
# - Base files, which are a snapshot representing the complete state of the
# dataset at the time the file was created. Base files can be either in
# the form of RDB (binary serialized) or AOF (textual commands).
# - Incremental files, which contain additional commands that were applied
# to the dataset following the previous file
# In addition, manifest files are used to track the files and the order in
# which they were created and should be applied.
# Append-only file names are created by Redis following a specific pattern.
# The file name's prefixis based on the 'appendfilename!configuration
# parameter,followed by additional information about the sequence and type.
#
# For example,if appendilename is set toappendonly.aof,the following file
# names could be derived appendonly.aof.1.base.rdbas a base file.
#
# - appendonly.aof.1.base.rdb as a base files.
# - appendonly.aof.1.incr.aof,appendonly.aof.2.incr.aof as incremental files.
# - appendonly.aof.manifest as a manifest file.
Appendonly filename “appendonly.aof”
重启服务后,我们发现默认安装路径下多了appendonlydir目录
[root@localhost ]#ll appendonlydir/
总用量 8
--rw-r--r-- 1 root root 89 7月 20 16:56 appendonly.aof.1.base.rdb.
--rw-r--r-- 1 root root 0 7月20 16:56 appendonly.aof.1. incr.aof
--rw-r--r-- 1 root root 88 7月20 16:56 appendonly.aof.manifest.
进入redis,设置多个键,让备份文件有记录,然后退出杀死redis进程,重启服务
[rootalocalhostn# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> set k1 v1
0K
127.0.0.1:6379> set k2 v2
0K
127.0.0.1:6379> set k3 v3
0K
127.0.0.1:6379> lpush mylist 1 2 3 4 5
(integer) 5
127.0.0.1:6379> exit
[rootalocalhost ~]# ps -ef | grep redis-server
root 2669 1 0 16:56 ? 00:00:00 /usr/local/src/redis-7.0.11/src/redis-server
root 2718 2120 0 16:59 pts/ 00:00:00 grep --color=auto redis-server
[rootalocalhost ~]# kill -9 2669
[rootlocalhost ~]# ps -ef | grep redis-server
Root 2723 2120 0 16:59 pts/0 00:00:00 grep --color=auto redis-server
[rootalocalhost ~]#systemctl restart redis.service
2门#
这时候再查看appendonly.aof.1.incr.aof文件
略
*n代表一共有两部分
$n代表一共几个字符