手机网站横向切换,做门户类网站报价,上海网站建设心得,公司网站建设找哪家Redis概念
Redis#xff0c;英文全称是remote dictionary service#xff0c;也就是远程字典服务。这是kv存储数据库。Redis#xff0c;包括所有的数据库#xff0c;都是请求-回应模式#xff0c;通俗来说就是数据库不会主动地要给前台推送数据#xff0c;只有前台发送了…Redis概念
Redis英文全称是remote dictionary service也就是远程字典服务。这是kv存储数据库。Redis包括所有的数据库都是请求-回应模式通俗来说就是数据库不会主动地要给前台推送数据只有前台发送了申请才能数据才能响应从而相应并且发送出数据。
为什么会有redis在分布式场景中不同的节点可能之间经常会共享某些数据因此我们可以把这些共享数据存放在redis当中哪些节点需要就可以去redis当中提取数据。
Redis的特点
kv-存储。所有的数据都是以键值对的方式存在的当然这个“值”也有可能是键值对。内存数据库。redis所有的数据都存储在内存中可以快速地响应请求。关系型数据库的数据一般大部分都是放在磁盘中其中一部分放在内存中可以提升取数据的速度。Redis不是关系型数据库。数据结构数据库。体现在redis的kv存储v支持丰富的数据类型最常用的有五种数据结构stirng字节串能存储二进制数据和字符串list链表hashzset有序集合能有序尽量有序set无序集合以及stream消息队列很少使用用的话一般用kafkahyperloglog很少使用。
不同的数据结构会对应不同的命令。Value的类型由第一次涉及到它的命令的类型决定。
图解redis
Redis的kv关系直观图
如图value为list的时候是双向循环链表value为hash 的时候是个kv形式的hash表。value为zset的时候给每个m元素都搭配一个cscore通过对score的排序实现有序。
所有的key都是string字节串因为支持存储二进制数据。 Redis的安装与启动教程
安装
进入redis官网下载redis
本文中选择下载6.2版本的redis
下载好了之后解压缩成一个文件夹。
cd redis-6.2
su
make
make test
make install
安装好了之后/usr/local/bin下会看到redis-server和redis-cli分别对应了redis的服务器和客户端。
启动
创建一个新文件夹mkdir redis-data
将redis-6.2文件夹下的redis.conf文件移动到redis-data下
修改redis.conf文件吧requirepass和daemonize属性修改如下的白字部分 修改好了之后redis服务器启动命令如下 查询redis服务器是否启动成功 用redis-cli连接到redis-server 之后的redis命令都在redis-cli上操作。
redis-cli案例
设置并获取string的kv存储 设置并获取list的kv存储 设置并获取hash的kv存储。 设置并获取set的kv存储 设置并获取zset的kv存储 Redis存储结构
Redis的底层数据结构是散列表。什么是散列表简单来说散列表是一系列的链表redis的这些链表的一个节点一对kv键值对同时这些链表的头节点指针分别放在了同一个数组的不同位置被串起来了。
当有一个新的键值对产生需要存储进入redis的时候redis先先对这个key做一个hash和取余看看要把这个键值对放在散列表的第几个链表中然后顺着数组找到这个链表的头节点把它插入到这个链表中。
下图中是一个redis存储结构的概念图部分value用了一些冷门数据结构不必太在意。跳表是用来实现zset存储的整型数组是用来实现set存储的动态字符串是用来实现string存储的当然只能说大多数情况下是如此并不绝对。 以下是redis的不同数据结构类型的value在不同的情况下会用到的存储结构一般是面试的时候会问日常开发不必太深究。第一层是数据结构数据对象类型第二层是数据结构可能会调用的存储结构底层存储类型。 Redis各种数据的特点
string 是一个安全的二进制字符串
双端队列 链表list有序插入有序
散列表 hash对顺序不关注field 是唯一的
无序集合 set对顺序不关注里面的值都是唯一的
有序集合 zset对顺序是关注的里面的值是唯一的根据
member 来确定唯一根据 score 来确定有序。
redis常用的数据类型
redis常用命令一般在官方文档里查询。
string
string存储结构介绍
当value为string类型的时候字符串长度小于等于 20 且能转成整数则使用 int 存储
字符串长度小于等于 44则使用 embstr 存储
字符串长度大于 44则使用 raw 存储。
为什么会有embstr和raw存储的区别主要是为了字节对齐。
redis的string数据类型小于44字节的时候在底层的存储结构如下 在没有存储string之前这个结构体实例包括了前三个属性的大小16字节头部信息3个字节buf数组\0结尾1个字节总共20个字节。
cache line缓存存储的最小单位用户数据部分大小为64个字节减去20个字节后还剩44个字节给可以用于string存储。当string小于44个字节会连同整个结构体一同存储在cache line中也就是embstr存储。当string大于44个字节redis会申请一块内存给string也就是raw存储。
string 与key
redis的key一般也是string类型的。但是key的取名有个点需要注意比如如果有多个teacher可能取名就是就是不同的teacher对应的key可能就是teacher:10001teacher:10002。为什么要用冒号分隔一般是因为redis-cli的可视化工具可以根据冒号更好地进行可视化展开。
string的应用举例
#累加器
# 统计阅读数 累计加1
incr reads
# 累计加100
incrby reads 100#分布式锁
# 加锁 加锁 和 解析 redis 实现是 非公平锁 ectd
zk 用来实现公平锁
# 阻塞等待 阻塞连接的方式
# 介绍简单的原理 事务
setnx lock 1 # 不存在才能设置 定义加锁行为 占用锁
setnx lock uuid # expire 30 过期
set lock uuid nx ex 30
# 释放锁
del lock
if (get(lock) uuid)del(lock);
#位运算
# 猜测一下 string 是用的 int 类型 还是 string 类型
# 月签到功能 10001 用户id 202106 2021年6月份的签到 6月
份的第1天
setbit sign:10001:202106 1 1
# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106
# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2list
list存储结构介绍
双向链表实现列表首尾操作删除和增加时间复杂度O(1)查找中间元素时间复杂度为O(n) 列表中数据是否压缩的依据1. 元素长度小于 48不压缩2. 元素压缩前后长度差不超过 8不压缩。
list的应用举例
注意如果要实现阻塞队列需要至少需要两个进程起redis-cli一个负责取数据阻塞一个负责push数据。
#栈
LPUSH LPOP
# 或者
RPUSH RPOP#队列
LPUSH RPOP
# 或者
RPUSH LPOP
#阻塞队列
LPUSH BRPOP
# 或者
RPUSH BLPOP#操作与队列一样但是在不同系统间生成者和消费者
hash hash存储结构介绍
散列表在很多高级语言当中包含这种数据结构
cunordered_map 通过 key 快速索引 value
hash常用命令
# 获取 key 对应 hash 中的 field 对应的值
HGET key field
# 设置 key 对应 hash 中的 field 对应的值
HSET key field value
# 设置多个hash键值对
HMSET key field1 value1 field2 value2 ... fieldn
valuen
# 获取多个field的值
HMGET key field1 field2 ... fieldn
# 给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
# 获取 key 对应的 hash 有多少个键值对
HLEN key
# 删除 key 对应的 hash 的键值对该键为field
HDEL key field
set
set存储结构介绍
集合用来存储唯一性字段不要求有序存储不需要有序操作交并差集的时候排序
set常用命令
# 添加一个或多个指定的member元素到集合的 key中
SADD key member [member ...]# 计算集合元素个数
SCARD key# SMEMBERS key
SMEMBERS key# 返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member# 随机返回key集合中的一个或者多个元素不删除这些元素
SRANDMEMBER key [count]# 从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]# 返回一个集合与给定集合的差集的元素
SDIFF key [key ...]# 返回指定所有的集合的成员的交集
SINTER key [key ...]# 返回给定的多个集合的并集中的所有成员
SUNION key [key ...]#并集
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
# C可能认识的人sdiff follow:A follow:C#交集
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
sinter follow:A follow:Czset
hset存储结构介绍
有序集合实现用来实现排行榜它是一个有序唯一
zst常用命令
# 添加到键为key有序集合sorted set里面
ZADD key [NX|XX] [CH] [INCR] score member [score
member ...]
# 从键为key有序集合中删除 member 的键值对
ZREM key member [member ...]
# 返回有序集key中成员member的score值
ZSCORE key member
# 为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
# 返回key的有序集元素个数
ZCARD key
# 返回有序集key中成员member的排名
ZRANK key member
# 返回存储在有序集合key中的指定范围的元素 order by id
limit 1,100
ZRANGE key start stop [WITHSCORES]
# 返回有序集key中指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]zset应用举例
延时队列将消息序列化成一个字符串作为 zset 的 member这个消息的到期处理时间作为 score然后用多个线程轮询 zset 获取到期的任务进行处理。
def delay(msg):msg.id str(uuid.uuid4()) #保证 member 唯一value json.dumps(msg)retry_ts time.time() 5 # 5s后重试redis.zadd(delay-queue, retry_ts, value)
# 使用连接池
def loop():while True:values redis.zrangebyscore(delayqueue, 0, time.time(), start0, num1)if not values:time.sleep(1)continuevalue values[0]success redis.zrem(delay-queue,
value)if success:msg json.loads(value)handle_msg(msg)
loop 是多线程竞争两个线程都从zrangebyscore获取到数据但是zrem一个成功一个失败。
时间窗口限流系统限定用户的某个行为在指定的时间范围内动态只能发 生 N 次
# 指定用户 user_id 的某个行为 action 在特定时间内
period 只允许发生该行为做大次数 max_count
local function is_action_allowed(red, userid,
action, period, max_count)local key tab_concat({hist, userid,
action}, :)local now zv.time()red:init_pipeline()-- 记录行为red:zadd(key, now, now)-- 移除时间窗口之前的行为记录剩下的都是时间窗口内的记录red:zremrangebyscore(key, 0, now - period*100)-- 获取时间窗口内的行为数量red:zcard(key)-- 设置过期时间避免冷用户持续占用内存 时间窗口的长度1秒red:expire(key, period 1)#commit_pipeline用于执行 Redis 流水线中的所有命令。#返回的列表中的每个元素对应一个命令的执行结果local res red:commit_pipeline()#res[3] 表示时间窗口内的行为数量即 red:zcard(key) 命令的返回值return res[3] max_count
end