前期文章:
redis快速入门1 五种数据类型之String篇 你的个人网站访问统计怎么做
redis快速入门2 五种数据类型之Lists篇 好好排队,别挤了,会轮到你的!!
前记
开篇之前,还是先絮叨絮叨一下。上一篇讲到redis的lists的时候,课后给大家一道作业,讲讲链表和数组的优缺点,这个我会在这次的课后作业里给出见解。
这次的博客,也吸取了一些朋友的建议,增加代码的实现,因为我们团队的主要技术栈是javascript+java。实战方面,就以nodejs实现为主。
Hash数据结构
先看图
阴影部分就是我们hash的结构,它也是个key-value的结构,但区别于redis的存储数据的key键,我们把hash的key称为field.hash的结构很适合对象的保存。如描述人的姓名,身高,体重,生日等。拿csdn博文来说,一篇博文,有标题、内容,流量数,点赞数等属性,这个对象就适合用hash的数据格式保存了。
常用指令
常用指令,我们还是用redis的指令来练习。
- 我们创建一篇博文blog,标题是“我的第一篇博文”
# hset key field value 设置hashkey键,字段field的值为value,返回1表明成功
127.0.0.1:6379> hset blog title 我的第一篇博文
(integer) 1
- 填写我们博文的正文。
127.0.0.1:6379> hset blog content 这是正文
(integer) 1
- 初始化我们的点赞数和浏览数
127.0.0.1:6379> hset blog like 0
(integer) 1
127.0.0.1:6379> hset blog views 0
(integer) 1
这里要注意的点:如果你是redis命令行操作的时候,查询中文数据的时候,会出现以下的情况。
127.0.0.1:6379> hget blog title "\xe6\x88\x91\xe7\x9a\x84\xe7\xac\xac\xe4\xb8\x80\xe7\xaf\x87\xe5\x8d\x9a\xe6\x96\x87"
这是序列化的方式造成的,我们只需登录redis的时候,添加
--raw
即可redis-cli -p 6379 --raw 127.0.0.1:6379> hget blog title 我的第一篇博文
- 当我们需要修改标题,或者修改内容时
127.0.0.1:6379> hset blog title 这是我第二篇了
0
127.0.0.1:6379> hget blog title
这是我第二篇了
# 修改内容同理
- 当你浏览了这篇博文,觉得还不错的时候,举手点了个赞☺
# HINCRBY hashkey field increment 将hashkey的field字段增加increment
127.0.0.1:6379> hincrby blog like 1 # 将博客的点赞数加1
1
127.0.0.1:6379> hget blog like # 读取点赞数
1
# 浏览量实现同理
至此,我们通过一片博文的操作,讲解了常用的hash散列的操作指令。
优点
我们从上面的例子开始分析,用hash有什么优点。我们加入不用hash来实现上面的数据存储,我们可以用什么方式来存储呢?(我们主要从redis的5种数据类型做比较)
- 我们很自然可以想到利用redis的k-v键值对来保存数据,key可以用
blog::title
的格式来表示博客的标题,value就是标题名。这样,我们就有了blog::title-这是我的第一篇博文
、blog::content-这是正文
、blog::like-0
、blog::views-0
四个数据了,这样我们就能满足需求了,但这有什么不好的地方呢?我们只描述一个对象,但却创建了4个键,如果一个对象的属性很多,用户写的博文越来越多的时候,创建key的内存消耗也是很大的。这是有优化的空间的。
- 既然创建多个key,是种消耗,那么我就保持一个key :blog, 然后将title,content,like,views一个对象序列化之后,保存起来就好了。如
那么这个有什么问题呢? 如果我们需要去修改标题,我们需要将整个字符串查出来,然后反序列化成对象,修改了标题之后,再序列化,然后在保存。整个过程,“序列化/反序列化”的操作,就很消耗资源了。而hash结构,允许我们对某一字段做修改,而无需全部拿出来,在处理。
而且,
假设整个博文对象拿出来,只修改其中的标题,在你修改的这个时候,有另外一个人来浏览你的文章,会有什么情况发生呢?出现的情况就是,你开始编辑的时候,拿到的博文对象,浏览量是1,标题改成新的,而另一个人浏览文章时,也会读取整个博文对象,浏览量加1变成2,此时,你们保存的时候,会出现浏览量或标题相互覆盖的问题/(ㄒoㄒ)/~~
处理此类并发的问题,有一个CAS(compare and swap, 即比较并交换)的思想,这个后续随着我们知识体系渐渐深入之后,单独讲讲。
由此可见,对于对象的存储,hash带来的显而易见的好处是
- 节省存储空间
- 允许更细粒度的操作
真的要学会精打细算、真的要学会精打细算、真的要学会精打细算,架构设计的一个很重要的出发点,就是减少浪费,提高效率
课后作业
-
好了,补回上一篇关于链表和数组的区别
数组的优缺点- 随机查找效率高(优点)
- 可能浪费内存(缺点)
链表的优缺点
- 动态添加删除 大小可变(优点)
- 不能随机查找,必须从第一个开始遍历,查找效率低(缺点)
其实,数组和链表的优缺点的原因,归根到底还是它的存储方式导致的。大家有兴趣的,可以查查他们存储的方式是怎样的。
- 大家可以用redis的hash数据类型实现一个计算器,实现加减法。黄健翔大神的<<redis使用手册>>里用python实现了个简单的计算器。大家可以看看。(我的橱窗里有这本书的电子书,如果你真的想对redis有很深的了解的话。可以点击购买。以我个人的习惯,更喜欢在微信读书里看书,看到内容不错,再决定买纸质书,纸质书的那种味道,电子书真的替代不了,(__) 嘻嘻……)
写完,已经1点30分了。真的又肝了一晚。欢迎点赞,关注,收藏。希望这些知识,对于刚踏入职场的或者即将步入IT行业的同学们有所帮助。