主页
关于
Stay before every beautiful thoughts
在每一个美好的思想前停留
文章
>
学习笔记
>
正文
Redis 应用场景
Redis
Created at 2021-07-16 23:23
## string(字符串) #### 常用命令: set,get,decr,incr,mget 等。 #### 使用SETBIT、GETBIT 实现日活,月活的统计 Redis Setbit 命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。 假如: 日活的 数据格式 是这样的 1101010(取七天的数据) 1为 签到 0为未签到。 只要统计 1的个数 即可知道 该用户这个月(或周,年)的签到次数。 如 1101010 可表示 该月1,2,4,6号该用户进行了签到, 其他时间未签到。 签到时,只修改特定位置的数据即可。 如 源数据 1101010 第七天为未签到 修改为 已签到时。 只需要 修改字符串的 第七个位置 设置为1 即可。 即:1101011 ##### 语法 redis Setbit 命令基本语法如下: ``` redis 127.0.0.1:6379> Setbit KEY_NAME OFFSET ``` ##### 可用版本 ``` >= 2.2.0 ``` ##### 返回值 指定偏移量原来储存的位。 ##### 实例 ``` redis> SETBIT bit 10086 1 (integer) 0 redis> GETBIT bit 10086 (integer) 1 redis> GETBIT bit 100 # bit 默认被初始化为 0 (integer) 0 ``` --- ## hash(哈希) Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。 #### 常用命令: hget,hset,hgetall 等。 #### 使用 hash 的特性 做 数据缓存(用户信息缓存) ``` # 添加测试数据 127.0.0.1:6379> HMSET user:1 name 'zhangsan' age '16' sex '1' OK 127.0.0.1:6379> HMSET user:2 name 'lisi' age '18' sex '0' OK 127.0.0.1:6379> HMSET user:3 name 'wangwu' age '20' sex '1' OK 127.0.0.1:6379> HMSET user:4 name 'zhaoliu' age '22' sex '0' OK 127.0.0.1:6379> HMSET user:5 name 'tianqi' age '23' sex '1' OK # 获取user:5 的所有信息 127.0.0.1:6379> HGETALL user:5 1) "name" 2) "tianqi" 3) "age" 4) "11" 5) "sex" 6) "0" # 修改 user:5 的年龄 127.0.0.1:6379> HSET user:5 age "20" (integer) 0 # 获取 user:5 的所有信息 127.0.0.1:6379> HGET user:5 age "20" 127.0.0.1:6379> ``` ---- ## list(列表) #### 常用命令: **lpush,rpush,lpop,rpop,lrange等。** #### 应用场景: Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。 #### 实现方式: Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。 ---- #### 可以使用 redis + php 做邮件队列 例如: 在使用 通过邮箱找回密码的功能时,通常邮件不是即时发送的。 如果是即时发送,会造成用户体验不好(延迟),程序耦合等。 这时候 可以使用队列 ,先把要发送的邮箱 通过队列存储,再通过队列脚本来处理队列。这样异步操作会好很多。 ---- ## set(集合) Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。 Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 #### 常用命令: sadd,spop,smembers,sunion 等。 #### 应用场景: Redis set对外提供的功能与list类似是一个列表的功能, 特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择, 并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 #### 利用集合成员是唯一的特性 。可以用来做订票系统。 用集合来存储定已经被预定的票的编号。如果有多个用户预定了同一张票,只能有一个成功。 ------ ## zset(sorted set:有序集合) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。 有序集合的成员是唯一的,但分数(score)却可以重复。 #### 常用命令: **zadd,zrange,zrem,zcard等。** #### 使用场景: Redis sorted set的使用场景与set类似,区别是set不是自动有序的, 而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。 当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构, 比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。 #### 利用有序集合的特性 来做 排行榜 例如:现在有一个需求就是对 所有用户的钱包金额进行排序,取最富有的前十位用户。 那么redis的有序集合,就可以满足要求了。 像 日榜,周榜,月榜等等 都可以用这个做。 周榜 和 月榜 都可以通过 日榜推算。 榜单的即时性 不强,可以用mysql 在今天凌晨时 统计昨天的数据 再存入 redis的有序集合。 ## HyperLogLog(是用来做基数统计的算法) Redis 在 2.8.9 版本添加了 HyperLogLog 结构。 Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。 但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。 ### 常用命令: PFADD key element [element ...] 添加指定元素到 HyperLogLog 中。 PFCOUNT key [key ...] 返回给定 HyperLogLog 的基数估算值。 PFMERGE destkey sourcekey [sourcekey ...] 将多个 HyperLogLog 合并为一个 HyperLogLog ### 什么是基数? 比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数就是在误差可接受的范围内,快速计算基数。 #### 实例 以下实例演示了 HyperLogLog 的工作过程: ``` redis 127.0.0.1:6379> PFADD runoobkey "redis" 1) (integer) 1 redis 127.0.0.1:6379> PFADD runoobkey "mongodb" 1) (integer) 1 redis 127.0.0.1:6379> PFADD runoobkey "mysql" 1) (integer) 1 redis 127.0.0.1:6379> PFCOUNT runoobkey (integer) 3 ``` ## 取最新N个数据的操作 比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的5000条评论的ID放在Redis的List集合中,并将超出集合部分从数据库获取 使用LPUSH latest.comments<ID>命令,向list集合中插入数据 插入完成后再用LTRIM latest.comments 0 5000命令使其永远只保存最近5000个ID 然后我们在客户端获取某一页评论时可以用下面的逻辑(伪代码) ``` FUNCTION get_latest_comments(start,num_items): id_list = redis.lrange("latest.comments",start,start+num_items-1) IF id_list.length < num_items id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...") END RETURN id_list END ``` 如果你还有不同的筛选维度,比如某个分类的最新N条,那么你可以再建一个按此分类的List,只存ID的话,Redis是非常高效的 ## 排行榜应用,取TOP N操作 这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。 ## 需要精准设定过期时间的应用 比如你可以把上面说到的sorted set的score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis里这个过期时间当成是对数据库中数据的索引,用Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。 ## 计数器应用 Redis的命令都是原子性的,你可以轻松地利用INCR,DECR命令来构建计数器系统。 ## Uniq操作,获取某段时间所有数据排重值 这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。 ## Pub/Sub构建实时消息系统 Redis的Pub/Sub系统可以构建实时的消息系统,比如很多用Pub/Sub构建的实时聊天系统的例子。 ## 构建队列系统 使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。