# Redis

# Redis 基础

redis(Remote dictionary server)是一个开源的基于内存的数据存储系统。它可以用于数据库缓存,消息队列等各种场景,是一种 NoSQL 数据库。早期的互联网公司系统大多是通过 Mysql 这种传统的关系型数据库对外提供服务。随着互联网的快速发展,应用系统的访问量原来远大,数据库的性能瓶颈越来越明显,主要是由于磁盘 IO 所导致的,磁盘 IO 的读写速度与内存相比是非常慢的,如果能把数据存储在内存中,则可以大大数据存储的性能。于是便出现了 redis,这种基于内存的数据存储系统。

# 切换数据库

redis 默认有 16 个数据库,编号分别是 0-15 ,通过 select 来进行切换

select 10	# 切换数据库 10
dbsize		# 产看当前数据库大小(不含数据,则数据库大小为 0)

# 清空数据库

flushdb		# 清空当前数据库
flushall 	# 清空所有数据库

# 数据结构

redis 支持多种数据结构,包括五种基本数据类型和五种高级数据类型。
五种基本数据类型:

  • 字符串 String
  • 列表 List
  • 集合 Set
  • 有序集合 SortedSet
  • 哈希 Hash

五种高级数据类型:

  • 消息队列
  • 地理空间
  • HyperLogLog
  • 位图 Bitmap
  • 位域 Bitfiled

redis 的使用方式有三种:

  • CLI,命令行界面(Command Line Interface);通过 Redis-CLI 命令行工具来使用
  • API,应用程序接口(Application Programing Interface);
  • GUI,图形用户界面(Graphical User Interface);通过图形化工具来使用 Redis

# String

redis 中的数据是以键值对的形式存储的

# 字符串 String
set key value      		# 设置键值对(key, value)
get key 	        	# 获取 key 对应的 value 值,大小写敏感
# redis 内默认都是使用字符串来存储数据的,而且是二进制安全的(redis-cli --raw)
del key			   	    # 删除 key 对应的(key,value)键值对
exists key		    	# 判断是否存在 key 对应的键值对
keys pattern			# 查看与 pattern 匹配的键,* 表示所以 key
clear			    	# 清空屏幕
type key			    # 产看 key 的数据类型
append key addstring	 # 在 key 对应的 value 后追加 addstring
strlen key				# 获取 key 对应的 value 的长度
# 设置一个带过期时间的键值对
TTL key			   		# 查看 key 的过期时间,返回 - 1 表示没有设置过期时间,返回 - 2 表示设置了过期时间同时该键值对已经过期,返回正数表示过期时间
expire key seconds		# 为 key 对应的键值对设置过期时间 seconds
setex key seconds value  # 设置(key,value)键值对的过期时间
setnx key value			# 当键 key 不存在时,插入(key, value), 否则不插入
incr key				# key 对应的 value +1 
decr key				# key 对应的 value -1
incrby key add			# key 对应的 value +add
decrby key sub			# key 对应的 value -sub
getrange key start end 	 # 获取 key 对应的 value 的 [start, end] 的值
setrange key offset replace_string	# 替换 offset 小标开始的字符串为 replace_string
mset key1 value1 key2 value2 key3 value3  # 批量设置 key-value
mget key1 key2 key3						# 批量获取
msetnx 
getset key value		# 返回原始的 key 对应的值,若不存在返回 nil,同时修改 key 对应的值为 value

# list

list 也叫列表,一般用来存储和操作一组有顺序的数据,和数组的概念比较类似

# lish 操作
lpush key value 		# 往列表 key 的左边插入一个 value 的元素
rpush key value			# 往列表 key 的右边插入一个 value 的元素
lpush key value1 value2 value3 ...  # 一次性添加多个元素
lrange key start stop	# 获取列表 key 左边 [start, stop] 的所以元素索引 0 开始
lpop key 			   # 删除列表 key 最左边的元素,返回删除的元素值
lpop key count		   # 删除列表 key 最左边的 count 个元素(版本 >=6.0.2),返回删除的元素值
llen key			   # 获取列表 key 的长度
ltrim key start stop    # 保留列表 key 从左开始 [stop, stop] 内的元素,范围之外的元素均会被删除(索引均是从 0 开始)

# set

set 是一种无序集合,它和列表的区别是列表中的元素都是可以重复的,而 set 中的元素不可以重复,而且 set 中的元素并不像列表中的元素那样都是具有顺序的。

# set 操作
sadd key member			# 往无序集合 key 内添加 member 元素,若无序集合 key 内已经存在该 member,则添加失败
sadd key memeber1 member2 ...   # 往无序集合 key 内添加多个元素
smembers key			# 查看无序集合 key 的元素
sismember key member	 # 查看 member 是否是无序集合 key 内的元素
srem key memeber		# 删除无序集合 key 内的 member
srem key member1 member2 ...   # 删除无序集合 key 内的多个元素
# 集合运算操作

# sortedset

sortedset 是一种有序集合,又名 zset,其和集合的区别在于有序集合的每个元素都会关联一个浮点类型的分数,然后按照这个分数来对集合中的元素进行从小到大的顺序排序,有序集合的成员是唯一的,但是分数是可以重复的。

# sortedset 操作
zadd key score1 member1 score2 member2 ...  # 往有序集合 key 中插入 member1,member2,其对应的分数为 score1, scores2
zrange key start stop				# 查看有序集合 key 内 [start, stop] 内的元素
zrange key start stop withscores     # 查看有序集合 key 内 [start, stop] 内的元素和其对应的分数
zscore key member				    # 获取有序集合 key 内 member 的分数
zrank key member				    # 获取有序集合 key 内 member 的排名(从小到大排序,分数越小排名越高)
zrevrank key member				    # 获取有序集合 key 内 member 的排名(从大到小排序,分数越高排名越高)

# hash

哈希 hash 是一个字符类型的字段和值的映射表,简单来说就是一个键值对的集合,特别适合用来存储对象。

# hash 操作
hset key field value		# 往哈希 key 内插入 (field, value) 键值对
hget key field			    # 获取哈希 key 内 field 对应的值
hgetall key				   # 获取哈希 key 内所以的键值对
hdel key field  		   # 删除哈希 key 内 field 对应的键值
hexists key field 		    # 查看哈希 key 内是否存在 field 对应的键值
hkeys key				   # 获取哈希 key 内所以的键
hlen key				   # 获取哈希 key 内所以键值对的数目

redis 提供了发布订阅的功能,可以通过 publish 将消息发布到指定的频道,然后通过 subscribe 命令来订阅这个频道。但是这样的简单的发布和订阅功能具有一些局限性,比如消息无法持久化,无法记录历史消息等等

subscribe channel			# 订阅频道 channel
publish channel message		# 像频道 channe 发布消息 message

# Stream 消息队列

消息队列 Stream,是 redis5.0 引入的一个新的数据结构,他是一个轻量级的消息队列,可以实现消息的持久化、记录历史消息等。

# Stream 操作
xadd key id field value				# 往消息队列 key 内添加一条消息(消息的 id,消息的内容 (field, value)), id 为 *,则 redis 则会自动生成,id 为 (时间戳 - 序号) 的形式;redis 自动生成的 id 保证其为递增,如果手动指定 id 需要自己保证插入消息 id 为递增的
xlen key						   # 获取消息队列 key 的消息数目
xrange key - + 					    # 获取消息队列 key 内的所以消息信息
xrange key start end				# 获取消息队列 key 内 id 在 [start, end] 范围内的消息信息
xdel key id						    # 删除消息队列 key 内 ID 为 id 的消息
xtrim key maxlen count				# 删除消息队列 kye 内的消息,直到消息队列长度为 count(可能比 count 多)
xread [count count_num] [block milliseconds] streams key id   # 读取消息队列可以内 count_num 条消息,ID>id,若没有则堵塞 milliseconds 毫秒,如果 id 为 $, 表示获取当前时刻之后的 count_num 条消息

# Genspatial 地理空间

地理空间 Genspatial 是 redis3.2 版本的新特性,它提供了一种存储空间位置信息的数据结构,同时支持对地理位置进行的各种计算操作。

# 地理空间 genspatial
geoadd key longitude latitude member 	# 往空间地理位置 key 内添加名称为 member 的地理位置信息(经度,纬度)
geopos key member					  # 获取空间地理位置 key 内 member 的位置信息 
geodist key member1 member2 [km]			   # 获取空间地理位置 key 内 member1 与 member2 之间的距离,默认为 m

# HyperLogLog

HyperLogLog 是一种用来做基数统计的算法,它并不是 redis 特有的算法。基数:集合中元素数目(去重之后)。它的原理是使用随机算法来计算,通过牺牲一定的精度来换取更小的内存消耗。

# hyperloglog 操作
pfadd key element1 element2 ...        # 往基数容器 key 内添加 element1,element2... 元素
pfcount key							# 获取基数容器 key 内元素的数目
pfmerge destkey sourcekey1 sourcekey2  # 合并多个基数容器,最终存放于 destkey 基数容器内

# 位图

位图是字符串类型的扩展,可以使用一个 string 类型来模拟一个 Bit 数组,数组的下标就是偏移量,值只有 0 和 1,也支持一些位运算,比如与、或、非和异或等等。他们的运用非常广泛,比如用来记录用户的签到情况,在线状态,点赞状态。

# bitmap 操作
setbit key offset value				# 设置位图 key 偏移量为 offset 的位置为 value (0/1)
getbit key offset				    # 获取位图 key 偏移量为 offset 的位置的值
set key value					   # 位图本质是 string,可以通过设置 string 的方法来设置位图,value 转化为二进制即为对应位图的值
bitcount key 					   # 获取位图 key 内 1 的个数
bitpos key bit					   # 获取位图 key 内第一次出现 bit 的下标 (0 开始)

位域能够将很多小的整数存储到一个较大的位图中,这样就可以更加高效的使用内存

# 面试题

redis 支持事务,也就是可以在一次请求中执行多个命令;redis 中的事务主要通过 multiexec 这两个命令来实现的; multi 命令用来开启一个事务,事务开启之后所以的命令都会被放进一个队列中,最后通过一个 exec 命令来执行所以的命令。redis 中是事务和 mysql 或者 oracle 中的数据库的事务不太一样,在关系型数据库中,事务一般是一个原子操作,要么全部执行成功,要么全部执行失败;而在 redis 中,事务并不能保证所以命令都会执行成功,它的执行结果取决于事务中的命令,但是 redis 可以保证如下三点:

  • 在发送 exec 命令之前,所以的命令都会被放入到一个队列中缓存起来,不会立即执行
  • 在收到 exec 命令之后事务开始执行,事务中的任何一个命令执行失败其他命令依然会被执行(不会以为其中的命令执行失败而影响后续的命令的执行)
  • 在事务的执行过程中,其他客户端提交的命令请求并不会被插入到执行命令序列中

持久化的 redis 一个非常重要的功能,因为 redis 是一个基于内存的数据库,如果没有持久化的话,那么一旦服务器重启或者断点,那么之前的所以数据都会丢失,这对于一个数据库来说是非常致命的。redis 中的持久化主要由两种方式:

  • RDB 方式(redis databse),在指定的时间间隔内,将内存中的数据快照写入磁盘,他是某一时间点上数据的完整副本
  • AOF 方式(Append-Only File),追加文件,每次在执行写命令的时候,不仅将命令写入到内存中,还会将命令写入到一个追加的文件中,这个文件就是 AOF 文件,它会以日志的形式来记录每一个写操作,当 redis 重启的时候,就会通过重新执行 AOF 文件中的命令来在内存中重建整个数据库的内容

主从复制是指将一台服务器(主节点)的数据复制到其他 redis 服务器中(从节点)。一个主节点可以有多个从节点,而每个从节点只可以有一个主节点,数据的复制是单向的,只能由主节点到从节点;一般来说主节点负责写操作,从节点负责读操作,主节点会将自己的数据变化通过异步的方式发送给从节点,从节点接收到主节点的数据之后,更新自己的数据,这样就达到的了数据一致性的目的。

# 应用场景

Edited on Views times

Give me a cup of [coffee]~( ̄▽ ̄)~*

Value WeChat Pay

WeChat Pay