目前啊,公司有些动荡,程序员??真是不容易呀。自己趁着空余的时间,将原来看过的书和知识点再捋一遍。
ps:
纯手打,希望大家多多关注和点赞,后续陆续更新,希望大家一起进步!
图片使用的是processOn画的,有兴趣的小伙伴可以去试一下
如果同学需要电子书,可以评论区留言
吐槽processon,非会员文件最多9个,坑!
第一部分 入门
第一章 初识 redis
1.1 Redis简介
- Redis 概念
Redis是一个速度很快的非关系型数据库
,可以存储key-value
之间的映射,可以将存储在内存中的键值对数据持久化到硬盘
,可以使用复制特性
来扩展读性能,可以使用客户端分片
来扩展写性能
- Redis与其他数据库对比
数据库名称 | 类型 | 数据存储 | 查询类型 | 附件功能 |
---|---|---|---|---|
Redis | 使用内存存储(in-memory)非关系型数据库 | 字符串、列表、集合、散列、有序集合 | 每种数据类型都有自己的专属命令,另外还有批量操作和不完成的事务支持 | 发布订阅、主从复制、持久化、脚本 |
memcached | 使用内存存储的键值缓存 | 键值对之间的映射 | 创建、读取、更新、删除等命令 | 为提升性能而设的多线程服务器 |
MySQL | 关系型数据库 | 数据库-表-行 结构 | CURD相关函数 | 支持ACID特性、主从复制、主主复制 |
postgresql | 关系型数据库 | 同上 | 同上 | 同上 |
MongoDB | 使用硬盘存储(on-disk)的非关系文档存储 | 数据库-表-BSON文档 结构 | 创建、读取、更新、删除等命令 | 支持map-reduce操作、主从复制、分片、空间索引 |
- 附加特性
- RDB 和AOF 两种持久化方式
- 支持主从复制
①执行复制的从服务器
1.2 Redis数据结构
- 字符串 string
set hello world
get hello
del hello
- 列表 list
rpush list-key item
lpush list-key item2
lrange list-key 0 -1
lindex list-key 1
lpop list-key
rpop list-key
- 集合 set
列表可以存储多个相同字符串,集合存储的字符串各不相同
sadd set-key item
添加成功返回1,已经存在返回0smembers set-key
sismember set-key item
已经存在返回1,不存在返回0srem set-key item
- 散列 hash
可以将hash看做关系型数据库的行
hset hash-key sub-key1 value1
hgetall hash-key
hdel hash-key sub-key1
hget hash-key sub-key1
- 有序集合 zset
- 有序集合和散列,都可以存储
键值对
- 有序集合中,
键:成员,值:分值,分值必须为浮点数
- Redis中唯一一个,
既可以根据成员访问元素,又可以根据分值以及分值的排列顺序
访问元素的结构zadd zset-key 123 member1
zrange zset-key 0 -1 withscores
zrangeby zset-key 0 800 withscores
根据分值的范围查找zrem zset-key member1
1.3 Redis案列分析(类stackoverflow)
1.3.1 对文章进行投票
- 业务分析
- 可以对文章进行点赞
- 文章评分:得票数 * 常量 + 文章发布时间
- 每人每篇只能投一次,只能投一周
- 数据构建设计
- hash 文章信息(标题、网址、发布用户、发布时间、投票数)
- zset 文章发布时间(文章ID、发布时间)-可以通过发布时间排序
- zset 文章评分(文章ID、评分)-可以通过评分排序
- set 文章已投用户列表(key-文章ID、value-已投用户ID)-一周后就可删除
![]()
- 实现逻辑
- 当用户尝试对一篇文章投票,先去文章发布时间的zset中(zscore命令)检查文章是否超过一周
- 如果文章仍然可以投票,zadd将用户添加到文章已投用户列表set中
- 如果添加成功,则表示该用户第一次对该文章投票,并(zincrby命令)为文章评分zset添加400(设置的常量),并(hincrby命令)为文章信息hash中投票数+1
- 代码展示 python
’‘’
这里应该使用Redis事务,后续章节再添加进来
‘’‘
ONE_WEEK_IN_SECONDS = 7 * 86400
VOTE_SCORE = 400
def article_vote(conn,uer,article):
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('time:'+ article)< cutoff
return
# -1的好处是无论前面添加了栏目,ID的索引-1
article_id = article.partition(':')[-1]
if conn.sadd('voted:' + article_id,user)
conn.zincrby('score:',article,VOTE_SCORE)
conn.hincrby(article,'votes',1)
1.3.2 发布文章
- 实现逻辑
- 首先创建一个文章ID,可以通过计数器(INCR命令)
- 将文章作者ID添加(SADD命令)到文章已投用户列表,本人默认已经投了自己的文章
- 为文章已投用户列表的set设置(EXPIRE命令)过期时间,1周后自动删除
- 存储(HMSET)文章相关信息
- 将初始评分和发布时间分别添加(ZADD)到对应的有序集合中
- 代码展示 Python
def post_article(conn,user,title,link):
article_id = str(conn.incr('article:'))
voted = 'voted:' + article_id
conn.sadd(voted,user)
conn.expire(voted,ONE_WEEK_IN_SECONDS)
now = time.time()
article = 'article:' + article_id
conn.hmset(article,{
'title':title,
'link':link,
'poster':user,
'time':now,
'votes':1
})
conn.zadd('time:',article,now)
conn.zadd('score:',article,now + VOTE_SCORE)
1.3.3 获取文章(评分最高的文章、最新发布的文章)
- 实现逻辑
- 先使用ZREVRANGE(倒序范围取值)在zset中取出多个文章ID
- 然后在hash中对每篇文章ID执行HGETALL取出文章详细信息
- 代码实现 Python
ARTICLES_PER_PAGE = 25
def get_articles(conn,page,order='score:'):
start = (page-1) * ARTICLES_PER_PAGE
end = start + ARTICLES_PER_PAGE -1
ids = conn.zrevrange(order,start,end)
articles = []
for id in ids:
article_data = conn.hgetall(id)
# 给源数据添加ID
article_data['id'] = id
articles.append(article_data)
return articles
1.3.3 对文章进行分组(分类,标签等类似功能),并取出分组中评分最高或时间最新文章
- 实现逻辑
- 分组可使用集合set
- 将分组集合set、评分有序集合zset(或者时间的有序集合zset),进行交集(ZINTERSTORE命令)计算,存储到一个有序集合
- 然后从有序集合中获取排序的文章信息,为了减少Redis计算量,将交集结果缓存60秒
![]()
- 代码实现 Python
def get_group_articles(conn,group,page,order='score:'):
#交集的key
key = order + group
if not conn.exists(key):
conn.zinterstore(key,['group:'+group,order],aggregate='max')
conn.expire(key,60)
#调用原有方法获取文章排序
return get_articles(conn,page,key)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。