Redis
什么是 Redis
Redis 是一个开源(BSD 许可)的内存数据结构存储,用作数据库,缓存和消息代理。它支持数据结构,如字符串,散列,列表,集合,带有范围查询的排序集,位图,超级日志,具有半径查询和流的地理空间索引。Redis 具有内置复制,Lua 脚本,LRU 驱逐,事务和不同级别的磁盘持久性,并通过 Redis Sentinel 提供高可用性并使用 Redis Cluster 自动分区。
- redis 是由 C 语言写成
- 开源 key-value 型数据库
特点
速度快,因为数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是 O(1)
支持丰富数据类型,支持 string,list,set,sorted set,hash
支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除
应用场景
缓存
缓存是 redis 最常见的应用场景,主要是因为 redis 读写性能优异,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value DB。其次 redis 支持保存多种数据结构,此外单个 value 的最大限制是 1GB,而 memcached 只能保存 1MB 的数据。
分布式锁
因为 redis 单线程的这个特性,其中有个很重要的应用场景就是分布式锁。对于高并发的系统,都是用多服务器部署,其中程序进行逻辑处理时就可以用到分布式锁来限制程序的并发。
自动过期
redis 针对数据都可以设置过期时间,可以自动的去清理过期的数据。常见的应用场景有:短信验证码,活动开始和截止日期等具有时间性的商品展示等
计数器和排行榜
redis 在内存中对数字进行递增或递减的操作支持很好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些排行操作的时的非常简单。
秒杀的缓冲层
秒杀是现在互联网系统中常见的营销模式,但是通常由于并发太高导致、程序阻塞等原因给开发带来很大困难。可以利用 redis 单线程的特性来控制并发,可将 redis 作为缓存平台,由于 redis 的读写能力很强,所以不易产生程序阻塞现象。
处理签到和其他状态(大数据处理)
当用户量庞大时,如何去在极短的时间里去统计用户的状态,签到情况等,如 QQ 打卡、 查看好友状态等。redis 中的位图可以很好的解决这个问题。
发布/订阅
可以使用 redis 的发布订阅去实现的社交聊天系统。
实战
Redis 发布/订阅实现聊天室
1 | const rclient = redis.createClient(6379, "localhost"); |
1 | io.on("connection", socket => { |
Redis 队列实现秒杀 秒杀实例
https://www.jianshu.com/p/31f59426c779
痛点解决
短时间内大量并发
保证不会超卖
使用 Redi 提供缓冲层
内存型数据库性能远优于关系型数据库
Redis 单进程方式保证操作原子性
使用 Redis 队列投放秒杀商品
1 | router.get("/create", async ctx => { |
秒杀从商品队列中取出商品
使用哈希表作为临时订单
1 | router.get("/buy", async ctx => { |
打印订单列表
1 | router.get("/order", async ctx => { |
清空订单
1 | router.get("/order/clear", async ctx => { |
压力测试验证
1 | (async () => { |
Redis API
通用命令
- keys: 计算所有的键 O(n)
- dbsize: 数据库大小
- exists keys: key 是否存在
- del:删除 key
- expire key seconds: 设置过期时间
- type key: 获取 key 的数据类型
- ttl key: 查看 key 的剩余过期时间
- persist key: 去掉 key 的过期时间
列表类型
- rpush key value1 value2 valueN O(1-n)
- lpush key value1 value2 valueN O(1-n)
- linsert key before|after value newValue O(n)
- lpop key
- rpop key
- lrem key count value (删除 count 个 value 元素) 0(n)
- ltrim key start end (按照索引范围修剪列表) o(n)
- lrange key start end (包含 end) (获取列表制定索引范围)
- lindex key index o(n)
- llen key
- lset key index newValue
- blpop key timeout (lpop 的阻塞版本)
- brpop key timeout (rpop 的阻塞版本)
- lpush + lpop = stack
- lpush + rpop = queue
- lpush + ltrim = Capped Collection
- lpush + brpop = Message Queue
字符串类型
- 场景:缓存、计数器、分布式锁
- get key
- set key value
- incr key
- decr key
- incrby key k
- decrby key k
- setnx key value 值不存在才设置
- set key value xx 存在才设置
- mget 批量获取 O(n)
- mset 批量设置 O(n)
- getset key newvalue 设置新值返回旧值
- append key value 将新值追加到旧值
- strlen 获取值的长度
- incrbyfloat key 3.5 增加对应 key 3.5
- getrange key start end
- setrange key start value
集合类型
- 无序 无重复 支持集合间操作
- sadd key element (添加)
- srem key element (删除)
- scard key
- sismember key element
- srandmember key count (随机选出 count 个元素)
- spop key (随机弹出一个元素)
- smembers key (取出所有元素 小心使用)
- sscan (遍历集合)
- sdiff 差集
- sinter 交集
- sunion 并集
- sadd = 打标签
- spop/srandmember = 随机
- sadd + sinter = Social Graph
有序集合类型
- zadd key score element O(logN)
- zrem key element (删除)
- zscore key element
- zincrby key increScore element (增加分数)
- zcard key (返回个数)
- zrange key start end withscores (获取元素) (O(logN + m))
- zrangebyscore key minScore maxScore
- zcount key minScore maxScore (O(logN + m))
- zremrangebyrank key start end (删除指定排名内的升序元素)
- zremrangebyscore key start end (删除指定分数内的升序元素)
- zrevrank
- zrevrange
- zrevrangebyscore
- zinterstore
- zunionstore
哈希类型
- hget key filed
- hset key field value
- hdel key field
- hgetall key O(n)
- hexists key field
- hlen key 获取字段数量
- hmget key field1 field2 O(n)
- hmset key field1 value1 field2 value2 O(n)
- hincrby key field value
- hvals key 返回 hash key 对应所有 field 的 value O(n)
- hkeys key 返回 hash key 对应的所有 field O(n)
- hsetnx key field value
- hincrby key field intCounter
- hincrbyfloat key field floatCounter