1.redis的工作原理
redis的单线程模型
核心:文件事件处理器 包括多个socket, IO多路复用程序,文件事件分派器,事件处理器,因为它 是单线程的 所以redis单线程
客户端连接redis, 使用socket连接,采用IO多路复用机制同时监听多个socket,将socket放入队列中排队,每次从队列中取出一个socket给事件分派器,事件分派器根据socket的请求(read write close),分派给相应的事件处理器。
IO多路复用的好处就在于单个process就可以同时处理多个网络连接的IO ,
既实现了高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性
2.为什么redis是单线程 还能够支持高并发
- IO多路复用程序基于非堵塞,可以同时监听几百上千个socket
- 事件处理器是基于纯内存操作的,速度极快
3.redis有哪些数据类型,分别在哪些场景下使用, 是怎么使用的
- string set get 做简单的kv缓存, 如图片验证码
- hash 用于存储对象,对象结构为属性、值 ,值的类型为string,如用户购物车部分 user_id {sku_id: count}
- list 有序列表,lrange可以实现分页、消息队列, 如商品浏览历史记录, 粉丝列表、评论列表
- set 无序集合 自动去重,如购物车的全选和非全选
- zset /sorted set 有序集合 自动去重,具有权重, 可以通过加权重的形式实现排序存储,如排行榜
在django项目中使用redis,需要先在配置文件中添加redis的配置,然后使用get_redis_connection连接redis,如果要连接远端redis的话,需要修改远端redis的redis.conf文件,关闭bind 127.0.0.1
flask项目中使用StrickRedis() 进行连接redies, session 和 图片验证码都是保存在redis中的
4.redis的过期策略 内存淘汰机制
定期删除+惰性删除
定期删除:指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。
惰性删除:在获取某个key的时候,redis会检查一下,如果设置了过期时间并且已经过期,那么此时就会删除,,不返回任意东西
内存淘汰机制:allkeys_lru :移除最近最少使用的key
5.手写LRU算法
LRU 最近最少使用算法, 按时间倒序排列,从尾部删除元素
import collections
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = collections.OrderedDict()
def get(self, key):
try:
value = self.cache.pop(key)
self.cache[key] = value
return value
except KeyError:
return -1
def set(self, key, value):
try:
self.cache.pop(key)
except KeyError:
if len(self.cache) >= self.capacity:
self.cache.popitem(last=False)
self.cache[key] = value
6.redis是如何实现高并发和高可用的
redis高并发: 做主从架构, 搭建一主多从多台服务器,单台主服务器,用来写入数据, 多台从服务器用来查询数据
redis高可用:在做主从架构的时候,加上sentinel 哨兵的配置就可以了,保证了redis集群的高可用性,实现任何一个redis实例宕机,都会进行主备切换,不会导致数据的丢失。因为mater node如果宕机或重启,数据是100%丢失的,切不能恢复,只能靠做主从备份。
7.redis的可持久性
8.redis的横向扩容
redis与memcached的比较
- 数据类型比memcached要多,支持更多复杂的场景,更好用
- redis是单线程,memcached是多线程
- memcached不支持原生集群,redis支持cluster 集群模式