内容简介:欢迎关注公众号:【如果有需要后台回复
欢迎关注公众号:【 爱编码 】
如果有需要后台回复 2019 赠送 1T的学习资料 哦!!
简介
Redis是一个开源(BSD许可)的内存数据结构存储,用作数据库、缓存和消息代理。它支持诸如 字符串、散列、列表、集、带范围查询的 排序 集、位图、hyperloglog、带半径查询和流的地理空间索引 等数据结构。
Redis具有内置的复制、 Lua 脚本、LRU清除、事务和不同级别的磁盘持久性,并通过Redis Sentinel和 Redis 集群的自动分区提供高可用性。
原理与架构
Redis使用了 单线程架构和I/O多路复用模型 来实现高性能的内存数据库服务。
单线程模型
因为Redis是 单线程 来处理命令的,所以一条命令从客户端达到服务端不会立刻被执行。所有命令都会进入一个队列中,然后逐个被执行,因此 不会产生并发问题 。
为什么单线程还能这么快
- 1. 纯内存访问 ,Redis将所有数据放在内存中,内存的响应时长大
约为100纳秒,这是Redis达到每秒万级别访问的重要基础。
- 2. 非阻塞I/O ,Redis使用 epoll作为I/O多路复用技术 的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间,如下图所示
-
- 单线程避免了 线程切换和竞态产生 的消耗。
注:阻塞的操作是会非常影响Redis性能,这个下次再总结
API使用场景
命令语法可以到下面地址查,本节仅仅说使用场景。
https://www.runoob.com/redis/...字符串
- 1.缓存功能
Redis作为缓存层,MySQL作为存储层,绝大部分请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。
类似下面这样子的伪代码
// 从 MySQL 获取用户信息 userInfo = mysql.get(id); // 将userInfo序列化,并存入Redis redis.setex(userRedisKey, 3600, serialize(userInfo)); // 返回结果 return userInfo
- 2.计数
例如使用Redis作为文章点赞数计数的基础组件,用户每一次点赞,相应的点赞数就会自增1
long incrLikeCounter(long id) { key = "article:like:" + id; return redis.incr(key); }
- 3.共享Session
使用Redis将用户的Session进行集中管理,每次用户更新或者查询登录信息都直接从Redis中集中获取。
- 4.限速
很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率。
类似如下伪代码
phoneNum = "138xxxxxxxx"; key = "shortMsg:limit:" + phoneNum; // SET key value EX 60 NX isExists = redis.set(key,1,"EX 60","NX"); if(isExists != null || redis.incr(key) <=5){ // 通过 }else{ // 限速 }
哈希
关系型数据表记录的两条用户信息,用户的属性作为表的列,每条用户信息作为行。
相比于使用字符串序列化缓存用户信息,哈希类型变得更加直观,并且在更新操作上会更加便捷。可以将每个用户的id定义为键后缀,多对fieldvalue对应每个用户的属性。
类似如下伪代码:
UserInfo getUserInfo(long id){ // 用户id作为key后缀 userRedisKey = "user:info:" + id; // 使用hgetall获取所有用户信息映射关系 userInfoMap = redis.hgetAll(userRedisKey); UserInfo userInfo; if (userInfoMap != null) { // 将映射关系转换为UserInfo userInfo = transferMapToUserInfo(userInfoMap); } else { // 从MySQL中获取用户信息 userInfo = mysql.get(id); // 将userInfo变为映射关系使用hmset保存到Redis中 redis.hmset(userRedisKey, transferUserInfoToMap(userInfo)); // 添加过期时间 redis.expire(userRedisKey, 3600); } return userInfo; }
列表
列表是一种比较灵活的数据结构,它可以充当栈和队列。
相关命令时间复杂度表:
- 消息队列
Redis的 lpush+brpop 命令组合即可实现阻塞队列,生产者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。如图所示:
口诀:
- lpush+lpop=Stack(栈)
- lpush+rpop=Queue(队列)
- lpsh+ltrim=Capped Collection(有限集合)
- lpush+brpop=Message Queue(消息队列)
集合
集合类型比较典型的使用场景是 标签(tag) 。例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。
有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。
例如一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。
相关命令时间复杂度表:
标签实现基本思路
1.给用户添加标签
sadd user:1:tags tag1 tag2 tag5 sadd user:2:tags tag2 tag3 tag5 ... sadd user:k:tags tag1 tag2 tag4 ...
2.给标签添加用户
sadd tag1:users user:1 user:3 sadd tag2:users user:1 user:2 user:3 ... sadd tagk:users user:1 user:2 ...
3.使用 sinter 命令,来 计算用户共同感兴趣的标签
sinter user:1:tags user:2:tags
注:1,2步应该在同一个事务(下一篇文章再讲)中执行,否则会导致数据不正确。
更多组合应用:
- sadd=Tagging(标签)
- spop/srandmember=Random item(生成随机数,比如抽奖)
- sadd+sinter=Social Graph(社交需求)
有序集合
它保留了集合 不能有重复成员 的特性,给每个元素设置一个 分数(score) 作为排序的依据。
场景
排行榜系统
例如视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数。
本节使用赞数这个维度,记录每天用户上传视频的排行榜。
主要需要实现以下4个功能
- 1.添加用户赞数
//获得一个赞。 zadd user:ranking:2016_03_15 mike 3 //第一个赞之后自增。 zincrby user:ranking:2016_03_15 mike 1
- 2.取消用户赞数
zrem user:ranking:2016_03_15 mike
- 3.展示获取赞数最多的十个用户
zrevrangebyrank user:ranking:2016_03_15 0 9
- 4.展示用户信息以及用户分数
hgetall user:info:tom zscore user:ranking:2016_03_15 mike zrank user:ranking:2016_03_15 mike
总结
Redis还有什么场景,欢迎各位大神指教。
本文所有知识点来自于【 Redis开发与运维(付磊) 】,这本书非常值得一读。
关注公众号【爱编码】回复 付磊 即可获取。
最后
如果对 Java 、大数据感兴趣请长按二维码关注一波,我会努力带给你们价值。觉得对你哪怕有一丁点帮助的请帮忙点个赞或者转发哦。
关注公众号【 爱编码 】, 回复2019 有相关资料哦。
以上所述就是小编给大家介绍的《【数据库】Redis基础篇》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- django基础之数据库操作
- django基础之数据库操作
- 详解MongoDB数据库基础操作及实例
- SQL Server数据库入门基础知识
- PHP面试之MySQL数据库部分基础知识
- python框架之Flask基础篇(二)-------- 数据库的操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript设计模式
Ross Harmes、Dustin Diaz / 谢廷晟 / 人民邮电出版社 / 2008 / 45.00元
本书共有两部分。第一部分给出了实现具体设计模式所需要的面向对象特性的基础知识,主要包括接口、封装和信息隐藏、继承、单体模式等内容。第二部分则专注于各种具体的设计模式及其在JavaScript语言中的应用,主要介绍了工厂模式、桥接模式、组合模式、门面模式等几种常见的模式。为了让每一章中的示例都尽可能地贴近实际应用,书中同时列举了一些JavaScript 程序员最常见的任务,然后运用设计模式使其解决方......一起来看看 《JavaScript设计模式》 这本书的介绍吧!