
redis
文章平均质量分 87
哈哈哈张大侠
不积跬步无以至千里
展开
-
Redis:性能优化之Redis使用的规范
关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(原创 2023-04-11 23:03:05 · 85 阅读 · 0 评论 -
Redis:性能优化之Redis使用的规范
根据业务的时长,设置合理的过期时间,因为如果不设置过期时间,redis实例内存满了会触发数据淘汰,这个时候会释放内存的操作会阻塞主进程,并且设置过期时间时候尽量避免批量过期的情况。Redis针对读写命令的处理是单线程的,因此bigkey的操作会阻塞线程,尤其是针对时间复杂度为O(n)的数据结构进行并交集、全量查询等耗时的操作。这样做的好处是,这两种格式的可读性好,便于调试,不同的开发语言都支持这两种格式的解析。这样一来,既可以避免单实例的内存使用量过大,也可以避免不同业务的操作相互干扰。原创 2023-04-11 23:02:09 · 353 阅读 · 0 评论 -
Redis:性能优化之Redis 6.0的新特性
这里只会发送一次invalidate消息,只有当客户端下一次请求key时才会再次监控,监控是一次性的,这样是为了节省服务端有限的内存空间,如果客户端都不使用(读)这个key了,那么监控自然是没有意义的。所谓区分编码,就是指直接通过不同的开头字符,区分不同的数据类型,这样一来,客户端就可以直接通过判断传递消息的开头字符,来实现数据转换操作了,提升了客户端的效率。实际应用中,我们会让客户端注册希望监听的key前缀,只有当匹配的key发生修改时才会通知,和普通模式不同的是,针对key的注册一次。原创 2023-04-11 22:58:53 · 560 阅读 · 0 评论 -
Redis:性能优化之Redis Cluster的通信详解
Redis Cluster集群环境下,实例越多真的越好吗,吞吐量就越大吧redis官方建议是一个集群不超过1000个实例,原因是再多可能吞吐量反而会有降低的风险,那么为什么会这样呢?我们可以继续往下看。原创 2023-04-11 22:58:09 · 380 阅读 · 0 评论 -
Redis:代码实战之数据倾斜
第4步,我们把刚才获取的100个key中的key1迁移到目标实例5上(IP为192.168.10.5),同时把要迁入的数据库设置为0号数据库,把迁移的超时时间设置为timeout。数据访问量倾斜往往都是由于hot key导致,这里我们可以考虑hot key是否涉及写的场景,如果只有只读场景的话,我们可以将hot key的key拷贝多分,通过key的设置散列到多个实例,如果有读的场景就不能这样做了。因为Slot中的key数量可能很多,所以我们需要在客户端上多次执行下面的这条命令,分批次获得并迁移key。原创 2023-04-11 23:00:13 · 430 阅读 · 0 评论 -
Redis:代码实战之秒杀场景
秒杀系统最重要的是,把大部分请求拦截在最前面,只让很少请求能够真正进入到后端系统,降低后端服务的压力,常见的方案包括:页面静态化(推送到CDN)、网关恶意请求拦截、请求分段放行、缓存校验和扣减库存、消息队列处理订单。这里我们可以让请求都去请求锁,只有请求到锁的请求才能继续往下走,在请求层面我们就过滤掉了一大批请求。其中最重要的就是查询库存操作,因为只有当我们查询到了库存有余量才会走下面的步骤,所以大部分的请求都会请求库存,因此面对大量的并发请求我们需要将库存放到redis中进行处理。原创 2023-04-11 22:56:07 · 474 阅读 · 0 评论 -
Redis:代码实战之事务
因为采取MULTI、EXEC每次都得发送指令给redis,网络开销相较于pipline大,并且pipline中的命令会一起执行,由于redis是单线程,这样就不存在发送MULTI命令,其他并发请求数据的情形了,自然保证了数据的隔离性。事务的ACID特性,是事务保证正确性的基本要求,而Redis能够保证事务的一致性、隔离性,但是无法保证事务的持久性,在事务中命令语法有误时,也无法保证原子性。采取RDB,由于事务执行时,RDB无法运行,因此事务执行过程中如果发生了实例的故障,那么数据就会丢失,无法保证持久性。原创 2023-04-09 19:36:14 · 288 阅读 · 0 评论 -
Redis:代码实战之锁和原子操作
第三步:完成了与所有实例的加锁操作之后需要计算整个过程的耗时,用于比较锁的过期时间,如果请求锁的时间大于了过期时间,则将该锁释放,如果客户端请求成功的实例不占大多数,也会释放锁。解决办法:区分当前锁是那个客户端申请的,其实就是给锁的变量设置一个唯一id进行客户端的区分,删除的时候也比较这个值是不是和申请锁的客户端的唯一id相等,相等才能执行删除锁操作。删除锁变量,释放锁过程包含了读取锁变量、判断值、删除锁变量多个操作,因此使用Lua脚本,原子性的方式执行保证释放锁操作的原子性。原创 2023-04-09 19:30:56 · 750 阅读 · 0 评论 -
Redis:代码实战之缓存污染
缓存污染指的是缓存中存在很多冷数据或者说查询频次很少的数据,如果这些数据占用的内存过大,会引发缓存的淘汰,会影响其性能。原创 2023-04-09 19:33:04 · 182 阅读 · 0 评论 -
Redis:代码实战之缓存异常场景
针对这种缓存类型的数据不一致的问题,大致与读场景相同,其实二者的区别也就是写请求的处理,读写缓存针对写请求是同步缓存,而读缓存是删除缓存,因此读写缓存场景下,新增的不一致的类型包括:新增请求,并发下的写写(执行顺序导致)请求。写+读:线程A删除缓存后,由于网络延迟还没有更新到库,此时线程B读取数据发现缺失,从库读出再同步入缓存,此时A才写入库,造成了缓存存在数据,但是数据不一致的情形。新增操作:新增数据,数据会直接写入到数据库,不涉及缓存操作,因此不会出现不一致的情形,且数据符合一致性的第一种情形。原创 2023-04-09 19:29:53 · 153 阅读 · 0 评论 -
Redis:代码实战之淘汰策略
LRU会将数据组织成一个列表,两端分别为MRU端(最常被访问的数据),LRU端(最不常被访问的数据),当链表中元素被访问则置于MRU端。但是Redis使用链表的方式存在的缺陷就是,链表缓存所有的数据会带来额外开销,并且并发访问的时候会带来链表许多的移动操作,影响redis的性能。redis作为旁路缓存时,不可能将所有的数据都存储在缓存中,并且数据存储具有“二八原则”,即80%的请求只会请求20%的数据,那么缓存的。,其中候选集合就是一个链表结构,但是redis无需用链表维护所有的键值对,只需维护候选集合。原创 2023-04-09 19:31:49 · 160 阅读 · 0 评论 -
Redis:代码实战之旁路缓存
但是当一个系统引入缓存时,需要面临最大的问题就是,如何保证缓存和后端数据库的一致性问题,最常见的3个解决方案分别是Cache Aside、Read/Write Throught和Write Back缓存更新策略,也就是下面所描述的两张缓存类型。缺点:高并发下的同步直写可能会发生缓存和数据库不一致的情形,由于写入数据库后写入缓存操作存在竞态条件(更新覆盖,由于请求数据库可能先请求后返回),需要配合分布式锁。所有写请求现在缓存处理,等增改的数据被从缓存中淘汰时,将需要淘汰的数据写入后端数据库。原创 2023-04-09 19:28:37 · 975 阅读 · 0 评论 -
Redis:性能风险之缓存
缓冲区溢出导致网络连接关闭:普通客户端、订阅客户端,以及从节点客户端,它们使用的缓冲区,本质上都是Redis客户端和服务器端之间,或是主从节点之间为了传输命令数据而维护的。这些缓冲区一旦发生溢出,处理机制都是直接把客户端和服务器端的连接,或是主从节点间的连接关闭。网络连接关闭造成的直接影响,就是业务程序无法读写Redis,或者是主从节点全量同步失败,需要重新执行。缓冲区溢出导致命令数据丢失:主节点上的复制积压缓冲区属于环形缓冲区。原创 2023-04-09 19:30:44 · 253 阅读 · 0 评论 -
Redis:性能风险之内存碎片及清理
2KB、4KB、8KB分配空间,申请大小N,则分配2的次幂大于且最接近N的空间大小进行分配、好处在于多分配的空间等再次需要且这块多余的空间能满足时,无需重复分配,应用申请内存总是一块连续的空间,可能机器的内存剩余容量够但是应用无法正常的申请内存,由于剩余内存没有连续的大小为N的内存了,正是由于这些剩余内存都是内存碎片导致的,可以理解为连续空间中间断的未使用内存。不过我们可以通过设置redis的参数来控制redis碎片清理的开始时间、结束时间、CPU的占用,从而减少对redis的影响。原创 2023-04-09 19:27:33 · 885 阅读 · 0 评论 -
Redis:性能风险之定位及解决Redis变慢
实际的生产环境中不建议开启大页机制,因为redis在fork子进程生成快照以及重写AOF日志时,主线程仍然可以接收写请求,因为采取了写时复制的机制,如果开启了大页机制,则可能对100k的数据进行写操作,此时需要复制一页也就是2MB的内存,且此时会阻塞主进程。**对redis的影响:**当Redis和其他对内存需求大的应用一起运行时,redis是访问内存才能完成,一旦发生swap,redis的请求操作需要等待磁盘的读写操作执行完成才能继续,并且与fsync不同的是,swap影响的是redis的主线程。原创 2023-04-09 19:27:00 · 1622 阅读 · 0 评论 -
Redis:性能风险之CPU核和NUMA架构的影响
在多CPU的NUMA架构下,如果你对网络中断程序做了绑核操作,建议你同时把Redis实例和网络中断程序绑在同一个CPU Socket的不同核上,这样可以避免Redis跨Socket访问内存中的网络数据的时间开销。在给Redis实例绑核时,我们不要把一个实例和一个逻辑核绑定,而要和一个物理核绑定,也就是说,把一个物理核的2个逻辑核都用上,这样,Redis的主线程、子进程和后台线程可以共享使用一个物理核上的两个逻辑核。:CPU中一般有多个运行核心,一个运行核心称作物理核,每个物理核都可以独立的运行程序。原创 2023-04-09 19:28:11 · 515 阅读 · 0 评论 -
Redis:性能风险之内部阻塞风险
可见,即使开启了lazy-free,String类型的bigkey,在删除时依旧有阻塞主线程的风险。开启lazy-free后,Redis在释放一个key的内存时,首先会评估代价,如果释放内存的代价很小,那么就直接在主线程中操作了,没必要放到异步线程中执行(不同线程传递数据也会有性能消耗)。删除操作需要释放键值对所占用的内存空间,而操作系统在释放空间之后会插入一个空的内存块的链表,便于后续的管理和再分配,因此再,这个过程会阻塞应用程序,特别是对于释放大量的数据的时候。什么情况才会真正异步释放内存?原创 2023-04-08 20:39:27 · 134 阅读 · 0 评论 -
Redis:应用实践之消息队列
关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(消费消息的过程中可能由于应用宕机或没有处理完成的消费失败的场景,能够做到应用重启后该消息不丢失并重新供给消费者消费。消费者从消费消息时候,可能会由于网络堵塞而出现消息重复发送的情况,此时消费者可能会接收到多条重复的消息。虽然消费者是异步处理消息,但是,消费者仍然需要按照生产者发送消息的顺序来处理消息,这个也是得区分场景,原创 2023-04-08 20:38:37 · 230 阅读 · 0 评论 -
Redis:应用实践之时序数据的保存
利用hash的二级key作为时间,二级value存储数据可以解决插入频繁,查找快速的问题,但是没有按照时间排序,以及支持聚合,这个时候就可以引入zset解决该问题,但是此时会出现同时插入hash和zset的原子性问题。关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(我认为真正的时序数据库的场景可能不会真正的使用redis,而是会使用influxdb、普罗米修斯等替代。原创 2023-04-08 20:35:28 · 447 阅读 · 1 评论 -
Redis:应用实践之GEO与定义新的数据类型
组成type:表示值的类型。五大类型(String、Hash、set、zset、list)encoding:值的编码方式,用来表示value的底层数据结构,例如SDS、压缩列表等lru:记录这个对象最后一次被访问了时间,用于淘汰策略refcount:记录引用的次数*ptr:指向数据的指针自定义数据的步骤。原创 2023-04-08 20:37:33 · 121 阅读 · 0 评论 -
Redis:应用实践之集合的统计
关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(基数统计就是统计一个元素中不重复的元素个数,例如统计网页UV(uv是unique visitor的简写,是指通过互联网访问、浏览这个网页的自然人,统计人数)用于统计基数的数据集合类型,最大优势在于元素数量非常多的时候,它计算基数的空间总是固定的,而且很小。统计多个集合元素的聚合结果,集合之间的交集(公有)、并集(全部)、差集(独有)等。原创 2023-04-08 20:34:25 · 481 阅读 · 0 评论 -
Redis:应用实践之内存占用
Redis不同的数据类型包含一些相同的原数据,这些原数据就统一放在RedisObject结构体中,RedisObject包含一个指针指向具体的结构体,为了节省内存空间,Redis还对Long和字符串类型做了特殊的处理。哈希桶实际只占用24个字节,但是redis的空间分配使用的是jemalloc,jemalloc在分配N个字节的数据时,会开辟大于N的2的次幂的大小,所以24个字节的数据实际开辟了32个字节的空间。字节数组,保存实际数据,\0表示数组的结束,\0会额外占用一个字节的开销。原创 2023-04-08 20:33:36 · 511 阅读 · 0 评论 -
Redis:切片集群
当客户端与集群建立连接时候,会获得哈希槽与实例的映射信息,客户端并且会将映射信息缓存到本地(这样就能够通过key取模得到槽,去请求对应的实例了),其中实例之间相互连接后,会将哈希槽的信息同步给其他实例。增删实例后,会将哈希槽再实例中重新分配,这个时候实例之间是能够知道哈希槽的分配信息的,但是客户端本地缓存的信息可能就与当前信息出现不一致的场景,这个时候客户端再次读写请求会发生什么呢?第二步:此时key未迁移到新的实例,则返回正常数据,若此时key已迁移到新的实例,就会返回。命令手动建立实例连接,再使用。原创 2023-04-08 20:32:58 · 78 阅读 · 0 评论 -
Redis:哨兵机制
客观下线:但是哨兵可能会由于网络,或主库负载较大出现误判的情形,因此这里可以引入多个哨兵组成集群(哨兵集群),同时进行判断并少数服从多数,如果有2n+1个哨兵认为主节点下线(个数可配置),则标记为“客观下线”,否则则为上线。哨兵也是一个redis服务,因此其也提供订阅/通知机制,客户端可以从哨兵订阅频道并获得不同的消息,例如订阅+switch-master来获得主从切换的通知,从消息中拿到新的主节点的信息并建立连接。的频道,通过该频道,哨兵能够知道其他哨兵的地址,因此就能够互相之前通过建立连接进行通信。原创 2023-04-08 20:32:26 · 478 阅读 · 0 评论 -
Redis:数据同步之主从复制
详细来说,主库fork()出bgsave子进程生成RDB快照,将快照发送给从库后,从库会先清空数据(为了避免之前加载了其他数据),再本地加载数据,再主库同步的这个过程中不会产生堵塞,主库仍然接受读写请求,再同步RDB快照的这个过程中,会将生产快照的时刻之后的读写请求写入replication buffer,为了保证主从一致性。实例超时后又被判定为异常。,其超时时间的计算是指执行命令的当前时间后推ttl秒过期,所以命令通过给从节点时,主从之间的过期时间会存在延迟,所以就从从节点读到了在主节点过期的数据。原创 2023-04-08 20:31:51 · 212 阅读 · 0 评论 -
Redis:AOF日志和RDB快照
详细来说,主库fork()出bgsave子进程生成RDB快照,将快照发送给从库后,从库会先清空数据(为了避免之前加载了其他数据),再本地加载数据,再主库同步的这个过程中不会产生堵塞,主库仍然接受读写请求,再同步RDB快照的这个过程中,会将生产快照的时刻之后的读写请求写入replication buffer,为了保证主从一致性。实例超时后又被判定为异常。,其超时时间的计算是指执行命令的当前时间后推ttl秒过期,所以命令通过给从节点时,主从之间的过期时间会存在延迟,所以就从从节点读到了在主节点过期的数据。原创 2023-04-08 20:28:53 · 120 阅读 · 0 评论 -
Redis:AOF日志和RDB快照
但是此时父进程依旧是会有流量写入的,如果父进程操作的是一个已经存在的key,那么这个时候父进程就会真正拷贝这个key对应的内存数据,申请新的内存空间,这样逐渐地,父子进程内存数据开始分离,父子进程逐渐拥有各自独立的内存空间。针对内存数据,当主进程修改一块数据时,这块数据会被复制一份,生成该数据的副本,然后bgsave把这块数据写入RDB文件,而这个过程中主进程仍然可以修改这块数据,这样就保证了快照的完整性。这样,就将6条命令,重写为了1条命令就可解决,那么这个重写过程会阻塞主进程吗?原创 2023-04-07 23:33:20 · 394 阅读 · 0 评论 -
Redis:Redis的IO模型
因为多线程并不一定就代表线程越多速度越快,再多线程的场景下,我们不得不去考虑针对共享变量的管理,也就是说针对并发所需要进行的处理往往会导致额外的开销或者说通过互斥锁等机制让并行变串行,因此增加线程并未让系统的吞吐率变高,反而因为加入了同步的机制,往往造成程序难于维护和调试。redis网络框架调用epollo机制,就不会出现上面所说的阻塞点的情况的产生,因为redis不会阻塞在一个特定的连接/监听套接字上,所以不会因为一个客户端的请求而堵塞其他客户端的请求,提高了并发性。耗时的操作包括以下几种。原创 2023-04-07 23:30:12 · 695 阅读 · 0 评论 -
Redis:键值存储结构(压缩列表、跳表等)
redis为了使hash更加高效,redis默认使用了两个全局哈希表,哈希表1和哈希表2,刚插入数据时候默认使用哈希表1,此时哈希表2并未分配空间,随着数据增大,这个时候会将哈希表1中的数据再哈希到数据表2,主要分为如下三步。针对不同的value数据类型,有不同的操作方式,例如Hget、Hset、SAdd,也有操作多个元素的,或者对整个元素进行遍历的,不同的操作时间复杂度又有不同,所以复杂度的高低又是我们选择集合类型的一个指标。时间复杂度为O(logn)原创 2023-04-07 23:29:34 · 657 阅读 · 0 评论 -
Redis:Redis整体架构
根据key能够找到value存储的具体位置,redis不太一样,找到redis的value后,还需要从value的复杂接口(例如集合和列表)中找到具体的数据。不同的I/O模型对键值数据库的性能和可扩展性会有不同的影响。关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(由于redis的数据都保存在内存中,针对内存的随机访问的特性,哈希表O(1)的操作复杂度比较匹配。针对内存的分配和释放。原创 2023-04-07 23:31:22 · 761 阅读 · 0 评论