分布式缓存技术的应用
缓存的主要作用:解决低速io和高速应用之间的一个差异
缓存技术的大规模使用也是在一些互联网公司里面和所谓的传统软件行业的区分
缓存的使用不光光是解决了我们的一些问题,但同时会带来更多的问题
去面试互联网公司都会问你缓存的使用,比如:
多种数据类型应该怎么去选择如何保证数据的一致性?
怎么去保证缓存的高可用?
怎么去保证缓存的热点数据?
这些问题需要你彻底了解缓存的本质
缓存的应用场景:
在传统的软件开发过程中,我们访问量和数据量都不是很高的情况下,一个数据库就可以满足我们的需求,一个数据库的性能是有限的
传统项目:
1、电商平台,随着快速发展,访问量的递增是非常可怕的,有可能是十倍,上百倍的上涨
2、成本很高,部署一个数据库服务器,当你每个月的数据量都是上千万的时候,你需要多少服务器对这个数据做一个分片
3、单从数据库层次的优化是无法满足整个吞吐性的要求的
在这种情况下怎么解决应用访问数据库这块的性能问题?
实际上在我们这个操作系统的资源里有一个东西最好用,内存,内存访问性能是最好的,如果把数据放到内存里面的话,对我们整个数据读取来说会有非常大的提升,但是在互联网的架构下,我们把所有的数据都放到内存中,这是一个不现实的,首先,内存资源是很昂贵的,同时它还是一个有限的,而且在互联网里面大部分场景下,二八理论,80%的时间都在访问20%的热点数据,这个理论在整个数据访问这块也是存在的
所以我们可以引用缓存的组件把一些热点数据(高频次)的访问数据放到缓存里面,可以提升整个系统的承载能力
一般来说使用缓存有几种方式(也就是数据同步的方式):
1、读的时候去触发,把数据写入数据库以后,然后把相应的数据写入到缓存
2、先去查询数据库里面的数据,然后把相应的数据写入到缓存
3、定时去刷新,可以选择定时调度周期性的去把我们的数据做一个同步
Redis的魅力
缓存大致可以分为两类:
1、应用类的缓存,比如像hashmap、ehcache (java提供的第三方库)
2、缓存组件,memcached、redis
redis:基于key/value的高性能存储系统 ,缓存中间件
redis 比memcached提供了更丰富的数据存储结构
redis提供了哪五种数据存储结构:
1、Stirng 字符串
2、list 列表
3、hash 跟java中使用hashmap一样,基于key/value存储
4、set 集合
5、sorted-set 带有序的集合
redis是一个字典结构存储的服务器,一个redis实例可以提供多个用来存储数据的字典,客户端去使用的时候,可以指定把相应的数据存储到哪一个类型的字典里面。(跟传统数据库差异比较大的一点)
1、redis实例中db类似命名空间的概念,但是没有做到完全隔离
2、redis支持数据的持久化,我们可以把数据放到内存里面,但是要考虑到内存中的数据出现系统故障的时候,有可能出现数据丢失的情况
3、基于redis这么多种数据结构,我们可以在数据结构基础上开发不同的一些功能,包括redis实现分布式锁、实现限流、分布式队列和缓存,基于它本身的特性去实现不同的应用场景
4、支持发布订阅的模式,跟消息中间件的发布订阅类似,会建立一个管道
Redis在Linux中的安装指引
https://redis.io 官网下载
1、tar -zxvf tar包名
2、cd 到解压目录中,执行make;tcl 、gcc
3、make test 测试编译状态
4、make install 正常执行完cd //
make test报错:
You need tcl 8.5 or newer in order to run the Redis test
解决方式:
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make
sudo make install
此方法如果不行的话可以参考该博客依次操作:
https://www.cnblogs.com/biboxie/p/4233292.html
如下:
#wget http://downloads.sourceforge.net/tcl/tcl8.6.0-src.tar.gz
#tar xzvf tcl8.6.0-src.tar.gz -C /usr/local/
#cd /usr/local/tcl8.6.0/unix/
#./configure --prefix=/usr \
--without-tzdata \
--mandir=/usr/share/man \
$([ $(uname -m) = x86_64 ] && echo --enable-64bit) &&
make &&
sed -e "s#$SRCDIR/unix#/usr/lib#" \
-e "s#$SRCDIR#/usr/include#" \
-i tclConfig.sh &&
sed -e "s#$SRCDIR/unix/pkgs/tdbc1.0.2#/usr/lib/tdbc1.0.2#" \
-e "s#$SRCDIR/pkgs/tdbc1.0.2/generic#/usr/include#" \
-e "s#$SRCDIR/pkgs/tdbc1.0.2/library#/usr/lib/tcl8.6#" \
-e "s#$SRCDIR/pkgs/tdbc1.0.2#/usr/include#" \
-i pkgs/tdbc1.0.2/tdbcConfig.sh &&
sed -e "s#$SRCDIR/unix/pkgs/itcl4.0.2#/usr/lib/itcl4.0.2#" \
-e "s#$SRCDIR/pkgs/itcl4.0.2/generic#/usr/include#" \
-e "s#$SRCDIR/pkgs/itcl4.0.2#/usr/include#" \
-i pkgs/itcl4.0.2/itclConfig.sh &&
unset SRCDIR
#make test
#make install &&
make install-private-headers &&
ln -v -sf tclsh8.6 /usr/bin/tclsh &&
chmod -v 755 /usr/lib/libtcl8.6.so
这个地方要注意的是#不是命令中的一部分仅仅表示从这个#到下个#为一条命令
redis-server未找到命令解决方案:
https://www.cnblogs.com/hujinshui/p/10160787.html
redis怎样后台运行?
通过 vi 编辑器修改 redis.conf 文件中的 daemonize no 为 yes 并保存
Redis的数据类型及常用命令
字符串类型
字符串类型: 可以存储任何形式的字符串,包括二进制数据,session、用户的信息、图片都可以,对应一个key-value形式,字符串默认支持字符串、整数和浮点数数据存储,可以对不同的数据做不同的操作,可以使用INCR对整数进行原子递增操作,数据结构int/SDS(存储字符串和浮点类型的数据)
使用场景:
1、session信息序列化以后存储到redis字符串结构中
2、ip限制,incr原子递增 短信验证,防止爆刷
注意: namespace 命令空间进行区分不同应用之间的缓存,在key上以更短的方式表达当前的数据的一个所属,这种好处对以后的维护是很有帮助的,包括后面去定位哪些key是干嘛的,这个时候会非常清楚,可读性能搞,但是如果key的长度设置很长的话,会造成一些反面的问题,整个数据存储会占用我们内存空间,如果数据比较大的话,占用的内存就大,同时,在做网络传输的时候,数据量越大传输性能也就越慢,所以这个地方要选一个合理的值
列表类型
列表类型: 可以存储一个有序的字符串列表,它的操作是可以向列表的两边添加元素以及获取元素的值或者某一段元素的值,一个key对应多个value的形式,
数据结构:
redis 3.2之前linkedList(在两端做push或pop操作复杂度比较低,但是内存开销比较大)和zipList(减少内存的占用,一段连续的内存存储,存储效率比较高,但是它的插入和删除需要频繁申请内存,所以效率比较低),当list元素个数和单个元素的长度比较小的时候会选择zipList,压缩列表来实现,如果元素个数比较多或者单个元素的长度比较长的时候会选择linkedList来存储
redis 3.2之后quickList,结合了quickList和linkedList两者的特性 双向链表,基于zipList的双向链表
typedef struct quicklist{
quicklistNode *head;
quicklistNode *tail;
unsigned long count; 列表中所有数据项的总和
unsigned int len; quicklist的节点数
int fill : 16; ziplist的大小限定
unsigned int compress:16;
}
使用场景:
1、队列(【分布式】消息队列 生产者lpush,消费者brpop)
队列:先进先出 通过lpush+rpop实现
消息队列:lpush+brpop实现
2、栈:后进先出 通过lpush+lpop实现
hash类型:跟hashmap结构相似,一个key对应一个table(可多列),
hash有两种结构:hash/ziplist (数据量小的时候选择)
集合类型
集合类型:不允许重复,并且它是一个无序的数据(特征),一个key对应多个value的形式,
数据结构:
1、intset(当set里面只包含整数类型的元素,它会通过intset去存储这样一个集合)
把整数元素按照顺序存储到数组里面,并且通过二分查找法去降低时间复杂度做一个数据的查询
2、hashtable(key,value(null))(包含不同数据类型用hashtable存储,只用key来存储元素,value为null)
使用场景:
1、标签,比如用户打一个lable,定位你是哪一类的学员,听了一次课的,五次课的…,对这些标签用户做一些定点的推送,大型的电商平台,千人千面的营销功能,需要一些大数据的分析,分析完之后会对用户形成一个结果,把这个标签设置到用户身上,这个时候再根据用户推送信息的时候可以根据标记去推送,
2、共同好友,可以通过set做一些并集,交集,差集(diff),通过交集查看一些相同的爱好,通过差集查看一些不同的点
有序集合
有序集合:有序集合跟集合的区别就是多了一个顺序,顺序是怎么体现的?score
数据结构: ziplist或者skiplist+hashtable skiplist 变种的二分查找法
使用场景:
1、根据pv排序一些热门的文章,根据点击量去排名文章
2、根据时间去排序一些新闻列表