概述
应用场景:
缓存数据库,
消息队列(发布订阅)
缓存数据同步方式:
双读双写:应用面对缓存与数据库;读时先读缓存,没有数据时再读数据库,并将读取到的数据更新到缓存;写时先写数据库再写缓存
异步更新:加一个更新工具,定时将数据库中的数据写入缓存,应用只读缓存,只写数据库;
串联模式:应用只面对缓存,缓存作为一个代理;应用只读写缓存,缓存读写数据库;
数据结构:string, list, hash, set, zset
string:
存储:字符串、整型(相当于long)、浮点型(双精度)
结构:int/SDS(simple dynamic string, 可以根据要存储的string的长度,自动分配指定大小规模的内存(默认2^8-1),可以节省内存占用)
list:
存储:很多string
特性:有序性、不唯一
结构:linkedlist(双向循环列表;访问稍慢插入删除快,内存占用多)、
ziplist(压缩列表,内存占用连续,可以认为是数组;访问快插入删除慢,内存占用少)、
quicklist(ziplist与linkedlist的组合)
hash:
存储:Java中的对象,对应与数据库表中的一行
(注:value类型只能为string,也就是说hash结构不能够嵌套其他结构!)
结构:ziplist(数据量少时)、hashmap(散列表结构)
set:
存储:很多string,*value为null的hash*
特性:无序性、唯一性
结构:intset(数组结构,只包括整型的时候使用inset)、hashmap(value为null)
使用:标签
zset:
存储:很多string,*key为score的hash*
特性:唯一性,有序性
结构:ziplist(数据量少时)、skiplist + hashmap(key为score)
使用:排名
内部原理:
1.缓存过期策略:
expire key seconds
缓存的过期主要通过 定期删除 + 惰性删除
定期删除:周期性地、随机地扫描,并使一些key过期
惰性删除:当key被访问的时候,才使相应的key过期
2.pub/sub:
通过channel实现pub/sub,channel的名称支持正则/全称,
与消息中间件的pub/sub的不同:不支持多协议,不支持持久化,不支持回滚,可靠性不高
3.持久化:
使用场景:当把redis作为主数据库、避免redis重启导致的缓存大量击穿
持久化方式:RDB、AOF
RDB:当满足条件时,fork一个子进程,将当前数据快照到文件,每次都全量快照;
优缺点:数据恢复速度快;可能会导致数据丢失;
条件:配置save seconds changes、用户主动执行save(阻塞所有客户端请求),bgsave(不会阻塞客户端请求)、flushall、复制(主从)
AOF:append only file,实时记录用户的事务性操作命令;
优缺点:可以避免数据丢失;影响性能;
指令压缩:避免aof文件过大;fork一个子进程,将当前内存中的数据生成指令记录在aof中,俗称“指令压缩”
4.内存淘汰机制:
物理内存的有限,导致涉及到内存的中间件必须要考虑限制自己的内存使用,考虑内存回收策略,比如redis,jvm
淘汰策略:
noeviction(默认),无内存可用时,报错
allkeys-lru:面向所有的key,最近最少使用的key被淘汰(LRU算法,类比LinkedHashMap)
allkeys-random:面向所有的key,随机淘汰
Volatile-lru:面向设置了过期时间的key,最近最少使用的key被淘汰
Volatile-ttl:面向设置了过期时间的key,快要达到过期的时间的key被淘汰
volatile-random:面向设置了过期时间的key,随机淘汰
5.单线程为什么可以处理高并发?
使用多线程的原因是为了更多的使用CPU资源,而redis的瓶颈并不在于CPU,而在于内存和网络,所以选择单线程
IO多路复用机制:虽然是单线程,但是通过IO多路复用,可以使用单线程来处理多个网络请求
6.lua脚本:
原子性问题:
redis虽然是单一线程的,但是仍然会存在线程安全问题,当然,这个线程安全问题不是来源于Redis服务器内部,
而是Redis作为数据服务器,是提供给多个客户端使用的,多个客户端的操作就相当于同一个进程下的多个线程,
如果多个客户端之间没有做好数据的同步策略,就会产生数据不一致的问题。
多个客户端的命令之间没有做请求同步,导致实际执行顺序可能会不一致,最终的结果也就无法满足原子性了
效率问题:
redis本身的吞吐量是非常高的,因为它首先是基于内存的数据库。在实际使用过程中,有一个非常重要的因素影响redis的吞吐量,那就是网络。
我们在使用redis实现某些特定功能的时候,很可能需要多个命令或者多个数据类型的交互才能完成,那么这种多次网络请求对性能影响比较大。
当然redis也做了一些优化,比如提供了pipeline管道操作,但是它有一定的局限性,就是执行的多个命令和响应之间是不存在相互依赖关系的。
所以我们需要一种机制能够编写一些具有业务逻辑的命令,减少网络请求
特点:
减少网络开销:在Lua脚本中可以把多个命令放在同一个脚本中运行
原子操作:redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件
复用性:客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑
使用:
lua是一种脚本语言,redis支持lua脚本在redis-cli上执行,lua脚本语言有针对redis的库;
eval “lua脚本”:执行lua脚本(redis.call(...))
evalsha “lua脚本摘要”:通过脚本摘要执行lua脚本,避免每次传输lua脚本,脚本体积大导致的网络传输慢的问题
最后
以上就是迷路西牛为你收集整理的Redis基本知识的全部内容,希望文章能够帮你解决Redis基本知识所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复