关于redis在分布式架构当中使用的一些理解和总结

redis的特征:
1、基于内存的
2、key-value键值对的存储结构
3、对于工作流是单线程的
4、io模型 epoll(多路复用)
5、value有类型
6、value有类型使具有本地方法->触发计算向数据移动(结合redis工作单线程使redis在计算上能达到最大的性能效果)

工作模型:

下面展示一个操作模型
在这里插入图片描述
kernel是内核,redis和很多的客户端并发访问通信的时候,因为可能发数据也有可能没发数据,如何快速知道那个客户端有数据进行读取,没有数据不进行读取减少没必要的操作,就用到了epoll 多路复用器(如果内核没有epoll会降级成select或者poll)多路复用器只能返回io事件,只能通过多路复用知道事件
演变为:
在这里插入图片描述
有了事件之后程序自己调代码,比如从某个客户端的inputStream流读取数据,然后把读取的数据放在内存里进行计算
在这里插入图片描述

因为redis是单线程的,通过epoll知道有多个客户端读,但是因为是单线程,所以是遍历 inputStream,故io读取是串行的,因为读取出来一个要参与计算才能都第二个,所以计算也是串行的,所以读取计算再读取再计算整体是一个串行的。
存在问题:读取一个然后计算,然后输出结果,输出之后读取第二个,再计算,io网卡输出方向是有时间间隔的,导致有一段一段的时间被浪费。
io的输出其实是有间隔的,没有被使用
解决办法:
多开ioThread,让其中一个cpu单独进行worker的计算,另外的cpu来读取客户端数据输出数据

redis具有本地方法:

memcache 是kv 没有数据类型,只认识string串,所以存储复杂机构的数据类型,就可以使用json,下面是一个解释案例:
memcache存储一个数组,可能就会存储成k1,[a,b,c,d],但是如果我客户端只想取到下标为2的c,它需要完整的取回整个数据,在客户端实现 计算(反序列化)->转类型->截取 获取到c
数据服务器端往客户端移动,移动数据量大(占带宽),计算在客户端(反复计算)
在这里插入图片描述
redis kv v有数据类型就有了本地方法,同样的数据存在服务器,会把字符串识别为list,有本地方法,客户端拿值只需要调用本地方法,拿k1的下标为2的数据,只返回一个c从网卡里流出来,a,b,d不会参与网卡输出流的过程,本地也不需要计算实现
计算向数据移动
在这里插入图片描述

单线程(worker)

redis的工作过程应该是 io读取c1内容,读取到内存后再计算c1,计算完后再把c1的结果 返回,返回后对于c1客户端的线程就已经处理完了;才能去处理c2
在这里插入图片描述
秒杀场景:
解决高并发的场景,第一应该想到负载均衡,可以使用四层或者七层两种技术(LVS/Nginx),有了负载均衡之后其实是让服务器变多一些,将客户端分别发给不同的服务端处理,只要最终保证数据中心想接受承受的并发量和服务端能构承受的并发量,比例关系合适(负载均匀没有倾斜)
在这里插入图片描述
这个时候并发连接数是3,并行处理度是2,这时候 需要知道tomcat线程池的并行度是多少,这时候就能算出来 并行度是多少
所以衡量系统的业务性能,一个是并发连接数,一个考虑的是并行的处理能力
在这里插入图片描述
server1、server2最终访问db库存的时候,要执行严格的串行化。所以要开事务,串行化多次通信,传输数据量比较大。将db换成redis,这时候他的key是item,value是99(有value类型就有本地方法,可以进行decrement减一操作),这时候客户端访问->server1、server2->对redis进行并发调用(redis是单线程worker,串行化,所以他要先处理完一个decr,再进行第二个decr,天生的单线程),这一过程是天生的因为他单线程,前面server和redis里面只有一个io和线程处理的行为。
在这里插入图片描述
redis串行化 原子
弊端:服务器多核,redis单核只能放在一个cpu上(部署很多的redis,但是网卡吞吐量一定,一个redis消耗完网卡的性能带宽,部署其他的redis发生网卡上的资源争抢)
worker thread压在了 cpu上,这时候多起几个iothread,每个线程压在独立的cpu上,worker、两个iothread 可以达到并行执行(如果你只有一颗cpu同时跑三个程序 ,cpu的时间片切换是串行的)
在这里插入图片描述
c1让cpu2来读取同时,c2让cpu3来读取,可能cpu2先读完也可能cou3先读完,但是 worker线程可以介入,c1读完了worker可以计算处理c1,c1
worker处理完后可以把输出押给cpu2来输出,同时worker处理着c2,这个时候cpu2调度的网卡往外输出【网卡利用率提高】
在这里插入图片描述
在整个实际计算复杂度上来说,一个单位一并行,完全串行就是可能要等6个时间单位【从计算上来讲一直都是串行的】io绑定线程禁止多个线程去访问一个channel(阻止c1有人读的时候,其他的也来读c1)

场景解决方案:

String字符串完成的存储场景:
字符串:对象的存储、文件的存储、小图片的存储、css样式等等->session共享、uuid、VFS inmemory(小文件)
数值:限流器等等->限流器(用户访问一次+1操作,判断单位时间访问的次数,超过就禁止访问)、统计点击率、统计
bitMap:12306、二进制、权限(思考linux的777)

nc localhost 6379 //连接上redis
keys * //展示有多少key
set k1 hello
get k1 //hello
keys *
*1 //一个key
$2 //两个字节
k1 //读出来是k1
set k2 world
//读完$2之后切割,再读完$2再切割,redis当中传输的协议
keys *
*2
$2
k1
$2
k2
FlushAll

redis是二进制安全的,将要存储的数据由客户端存储为byte(任何类型的数据交给redis都转换为byte,其他人取也取到的是byte)

setbit k1 1(偏移量1) 1 //开辟了一个字节,一个八进制的二进制位 0000 0000->开辟一个字节在相应的偏移量打了1,0100 0000
STRLEN k1 ->1
get k1 ->@
setbit k1 7 1 //0100 0001
STRLEN k1 ->1
get k1 ->A
setbit k1 7 0
setbit k1 5 1->B
setbit k1 9999999 1
STRLEN 1250000//开辟很多的字节出去,动态的扩宽value的字节数量
bitcount k1 0(从第一个字节)-1(到最后一个字节,-1双向索引代表最后一个)//会统计从开始到结束字节的位置1的数量
在这里插入图片描述

在这里插入图片描述

二进制位有与或非的操作在这里插入图片描述
用户统计:在一个时间窗里,统计用户的登录天数
在这里插入图片描述
STRLEN sean->消耗46字节
JD登录 送礼物 2e用户 需备用多少礼物 ->算活跃用户
setbit 20210101 2 1//2021年一月一号 3号用户登陆了
setbit 20210101 8 1//2021年一月一号 9号用户登陆了
setbit 20210102 8 1//2021年一月2号 9号用户登陆了
bittop or result 20210101 or 20210102 ->2
bitcount res 0 -1 ->2

在这里插入图片描述
list类型
list有序:放入顺序
同向(lpush lpop)->实现了栈,(lpush rpop)->实现了队列,利用下标准元素取值->实现了数组,LTRIM保留热数据
场景:帖子分页、红包(lpush 2 3 4 1)

这里是引用
LTRIM k1 0 4//删除的是索引之外的数据

hash指令的服务场景:

如果没有hash’可能使用的是一个string类型的场景
在这里插入图片描述
随着key’数量变多,整个redis为一个hashtable性能下降(除了做用户io的处理还要做用户的过期)
在这里插入图片描述
减少了 redis总体的数量,sean为一个维度,减少了网络通信
HINCRBY

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值