1 Redis 基本知识与命令
1.1 Redis 五大数据类型
官方文档的介绍中,提到了这点:
(英)
(中)
- string(字符串)
- hash(哈希)
- list(列表)
- set(集合)
- zset(sorted set:有序集合)
1.1 默认 16 个数据库
Redis 默认有 16 个数据库,可在配置文件 redis.conf 中查看
根据上图注释可知,用命令 SELECT 下标
可以选择切换数据库并且,数据库的下标从 0 开始,默认使用第 0 个数据库
1.2 查看数据库大小
DBSIZE
1.3 查看所有的键(key)
KEYS *
1.4 清空当前数据库
FLUSHDB
1.5 清除全部数据库的内容
FLUSHALL
2 Key-Value 常用命令
2.1 设置 key-value
SET 键名 值
2.2 获取 value
GET 键名
2.3 判断键是否存在
EXISTS 键名
2.4 设置 k-v 的过期时间
EXPIRE 键名 时间(秒)
2.5 查看键过期剩余秒数
ttl 键名
2.6 查看键的数据类型
TYPE 键名
3 String 类型常用命令
3.1 追加 value
APPEND 键名 追加的值(可用双引号引起来)
若当前键名不存在,则 APPEND 相当于 SET
3.2 获取 value 的长度
STRLEN 键名
3.3 将 key 中储存的数字值增一/减一
INCR 键名 / DECR 键名
3.4 将 key 中储存的数字值增 n / 减 n
INCRBY 键名 要增加的值 / DECRBY 键名 要减少的值
3.5 截取字符串 value 值
GETRANGE 键名 start end (注:区间为 [start, end],-1 下标标识最后一个字符的下标)
3.6 替换字符串 value 部分值
SETRANGE 键名 start 要替换的值
3.7 在指定的 key 不存在时,为 key 设置指定的值
SETNX 键名 值
(注:此命令在分布式锁中会用到)
3.8 为指定的 key 设置值及其过期时间
SETEX 键名 过期时间(秒) 新值
(注:若键之前存在,则新值替换旧值)
3.9 批量设置 key-value
MSET 键名1 值1 键名2 值 2 … 键名n 值n
3.10 批量获取 value
MGET 键名1 键名2 键名3
3.11 批量设置 key-value,且预先判断是否存在
MSETNX 键名1 值1 键名2 值 2 … 键名n 值n
(注:根据下图可知,此命令操作为原子性操作,因 k1 已存在,而导致不存在的 k4 也不能正常添加)
3.12 以对象形式批量设置 key-value
例如:user:{id}:{filed},可以动态设置值
3.13 获取并返回旧值同时设置新值
3.14 应用
(此部分,学习自:链接)
(1)计数器
string类型的incr和decr命令的作用是将key中储存的数字值加一/减一,这两个操作具有原子性,总能安全地进行加减操作,因此可以用string类型进行计数,如微博的评论数、点赞数、分享数,抖音作品的收藏数,京东商品的销售量、评价数等。
(2)分布式锁
string类型的setnx的作用是“当key不存在时,设值并返回1,当key已经存在时,不设值并返回0”,“判断key是否存在”和“设值”两个操作是原子性地执行的,因此可以用string类型作为分布式锁,返回1表示获得锁,返回0表示没有获得锁。例如,为了保证定时任务的高可用,往往会同时部署多个具备相同定时任务的服务,但是业务上只希望其中的某一台服务执行定时任务,当定时任务的时间点触发时,多个服务同时竞争一个分布式锁,获取到锁的执行定时任务,没获取到的放弃执行定时任务。定时任务执行完时通过del命令删除key即释放锁,如果担心del命令操作失败而导致锁一直未释放,可以通过expire命令给锁设置一个合理的自动过期时间,确保即使del命令失败,锁也能被释放。不过expire命令同样存在失败的可能性,如果你用的是Java语言,建议使用JedisCommands接口提供的String set(String key, String value, String nxxx, String expx, long time)方法,这个方法可以将setnx和expire原子性地执行,具体使用方式如下(相信其它语言的Redis客户端也应当提供了类似的方法)。jedisCommands.set(“IAmAKey”, “1”, “NX”, “EX”, 60);//如果"IAmAKey"不存在,则将其设值为1,同时设置60秒的自动过期时间
(3)存储对象
利用JSON强大的兼容性、可读性和易用性,将对象转换为JSON字符串,再存储在string类型中,是个不错的选择,如用户信息、商品信息等。
4 官方文档的命令介绍
5 知识补充
5.1 默认端口 6379 的由来(插曲)
网上有很多相关文章,总结来说就是6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被Redis的作者antirez及其朋友当作愚蠢的代名词(作者平时喜欢造梗)。Redis 作者 Antirez 早年看电视节目,觉得 Merz 在节目中的一些话愚蠢可笑,Antirez 喜欢造“梗”用于平时和朋友们交流,于是造了一个词 “MERZ”,形容愚蠢,与 “stupid” 含义相同。后来 Antirez 重新定义了 “MERZ” ,形容”具有很高的技术价值,包含技艺、耐心和劳动,但仍然保持简单本质“。到了给 Redis 选择一个数字作为默认端口号时,Antirez 没有多想,把 “MERZ” 在手机键盘上对应的数字 6379 拿来用了。
5.2 Redis 为什么是单线程?为什么这么快?
至于 Redis 为什么是单线程的,官方解释如下:因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。(多线程反而会因线程切换而造成多于开销)
至于为什么这么快,下面内容引用自:此处
-
Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快。
-
Redis使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。
-
Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。
-
Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
-
Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。