1. 设置远程 Redis demo
demo工具网站:https://app.redislabs.com
远程登录
redis-cli -u redis://<username>:<password>@redis-16985.c14.us-east-1-2.ec2.cloud.redislabs.com:16985
性能测试:redis-benchmark
2. 在 MacOs 上查看 Redis 配置文件
cat /usr/local/etc/redis.conf
默认 16 个数据库,可以使用SELECT <index>
切换数据库
DBSIZE # 查看数据库当前使用的大小
KEYS * # 查看所有的key
FLUSHDB # 清空当前库
FLUSHALL # 清空全部库
MOVE <key> <db> # 移动到指定数据库
EXPIRE <key> <seconds>
TTL <key> # 查看剩余时间 -1表示不会过期 -2表示已过期
TYPE <key> # 查看key类型
3. Redis 使用单线程的原因主要有以下几点:
减少锁竞争:Redis 的核心操作是基于内存的,使用单线程可以避免多线程环境下的锁竞争问题,提高性能。由于单线程模型避免了线程切换和上下文切换的开销,可以更高效地利用 CPU。
避免复杂性:多线程编程涉及到线程同步、数据一致性等复杂问题。使用单线程可以避免这些复杂性,使代码更加简单、可靠,减少潜在的错误。
避免资源竞争:Redis 的主要瓶颈是 CPU 和内存带宽,而不是计算能力。使用单线程可以充分利用 CPU 的计算能力,避免了多线程之间因为资源竞争而导致的性能下降。
高效的网络模型:Redis 使用非阻塞的 I/O 多路复用模型,单线程可以处理大量的并发连接。这种模型在处理高并发读写请求时非常高效,避免了线程间切换的开销。
需要注意的是,尽管 Redis 主线程是单线程的,但它通过使用异步 I/O 和多路复用技术实现了非阻塞的网络通信和高并发处理能力。此外,Redis 也提供了一些并发操作的指令,如使用多个 Redis 实例进行数据分片来提高整体性能。
4. String 字符串
字符串:可以用来做最简单的数据,可以缓存某个简单的字符串,也可以存某个 json 格式的字符串,Redis 分布式锁的实现就利用了这种数据结构,还包括可以实现技数器、Session 共享、分布式 ID。
- SET
- GET
- APPEND 如果不存在,相当于
SET <key>
- EXISTS
- INCR
- DECR
- INCRBY
- DECRBY
- GETRANGE
包含start和end,end为-1在倒数第1的位置 - SETRANGE
从offset开始替换成value,替换的范围为value的长度 - SETEX
设置key-value和过期时间,不存在则创建 - SETNX 成功返回 1,否则 0(在分布式锁中常常会使用)
- MSET
- MGET
- MSETNX 有一个存在则全部失败,原子性操作
- GETSET 先get再set,不存在返回nil,同样会设置新值
5. List 列表
List of strings,实际上是个链表。Redis的列表通过命令的组合,既可以当做栈,也可以当做队列来使用,可以用来缓存类似微信公众号、微博等消息流数据。
- LLEN
- LINSERT
- LPUSH 不存在则创建
- RPUSH 在尾部添加值
- LPOP
- RPOP
- LINDEX
找到第 index 个 key 的位置,从 0 开始,末尾从 -1 开始,越界报错 - LRANGE
- LREM
最多移除 count 个数的 value,精确匹配 - LTRIM
截取 list 部分元素 - RPOPLPUSH
- LSET
没有 key 或者超出原有 key 的 index 范围都报错 - LINSERT
BEFORE|AFTER
6. Hash 哈希表
可以用来存储一些 key-value 对,更适合用来存储对象。
- HGET
- HSET
[field value ...] - HMGET
- HGETALL
- HMSET
- HDEL
- HLEN
- HEXISTS
- HKEYS
- HVALS
7. Set 集合
和列表类似,也可以存储多个元素,但是不能重复,集合可以进行交集、并集、差集操作,从而可以实现类似,我和某人共同关注的人、朋友圈点赞等功能。
- SADD
- SREM
- SCARD 获取元素总个数 cardinality 基数
- SDIFF [key ...] 差集
- SINTER [key ...] 交集
- SUNION [key ...] 合集
- SISMEMBER
- SMEMBERS # 显示所有元素
- SPOP # 随机移除元素
- SRANDMEMBER
随机count个数的获取元素 - SMOVE
8. Sorted Set 有序集合
集合是无序的,有序集合可以设置顺序,可以用来实现排行榜功能。
- ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
- ZDIFF
- ZCOUNT
- ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
- ZREVRANGEBYSCORE 逆序
9. Bitmap
Kind of like a collection of booleans
- BITOP
- BITCOUNT
- BITPOS
10. Hyperloglog
Kind of like a collection of booleans
- PFADD
- PFCOUNT
- PFMERGE
11. JSON
Nested JSON structure
- JSON.SET
- JSON.GET
- JSON.DEL
12. Index
Internal data used for searching
- FT.SEARCH
- FT.CREATE
- FT.PROFILE
Documentation for commands: https://redis.io/commands
13. geospatial 地理位置
底层由 Zset 实现
GEOADD key [NX | XX] [CH] longitude latitude member [longitude latitude member ...] 地球两极无法直接添加 经度纬度
GEODIST # 单位m,km,mi,ft
GEOHASH
GEOPOS
GEORADIUS # 可以限制数量
GEORADIUSBYMEMBER
14. Hyperloglog
基数,不重复的元素个数,可以接受误差
- PFADD key [element [element ...]]
- PFMERGE
- PFCOUNT
15. Bitmap 位存储
- SETBIT key offset value 最大32位
- BITCOUNT 统计1的位数个数
16. 缓存穿透、缓存击穿、缓存雪崩分别是什么
缓存中存放的大多都是热点数据,目的就是防止请求可以直接从缓存中获取到数据,而不用访问 MySQL。
- 缓存雪崩:如果缓存中某一时刻大批热点数据同时过期,那么就可能导致大量请求直接访 MySQL 了,解决办法就是在过期时间上增加一点随机值,另外如果搭建一个高可用的 Redis 集群也是防止缓存雪崩的有效手段
- 缓存击穿:缓存雪崩类似,缓存雪前是大批热点数据失效,而存击穿是指某一个热点 key 突然失效,也导致了大量请求直接访问 MySQL 数据库,这就是缓存击穿,解决方案就是考虑这个热点 key 不设过期时间
- 缓存穿透:假如某一时刻访问 Redis 的大量 key 都在 Redis 中不存在,比如黑客意造一些乱七八的 key,那么也会给数据库造成压力,这就是缓存穿透,解决方案是使用布隆过滤器,它的作用就是如果它认为一个 key 不存在,那么这个 key 就肯定不存在,所以可以在缓存之前加一层布隆过滤器来拦截不存在的 key
17. 如何降低内存穿透风险?
布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。 它实际上是一个很长的二进制向量和一系列随机映射函数。 布隆过滤器可以用于检索一个元素是否在一个集合中。 它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。