Redis分布式锁的基本实现
前言 随着分布式系统的普遍运用,分布式锁的重要性也得到了体现 在单机系统中,我们可以运用普通的锁/信号量机制来实现对公共资源的有序访问;但在分布式系统中显然就不行了 因此业界常用的解决方案通常是借助于一个第三方组件,利用它自身的排他性来达到多进程的互斥;如: 基于 DB 的唯一索引 基于 ZK 的临时有序节点 基于 Redis 的 NX EX 参数 本文就主要以Redis分布式锁展开 需要了解的几个词 锁机制:锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足(Wiki百科) 死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程 ZK:即ZooKeeper,ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等 Redis分布式锁的基本原理 既然是选用了 Redis, ...
从Redis事务到Redis pipeline
前言 相信对关系性数据库有使用经验的,都对事务操作很熟悉,为了确保连续多个操作的原子性,我们常用的数据库都会有事务的支持,Redis 也不例外;但它又和关系型数据库支持的事务不太一样 需要了解的几个词 事务:数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的: 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰 ACID:关系性数据库事务具有的四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁 乐观锁(Optimistic Lock) ...
Redis内存碎片的产生与清理
前言 在做redis内存清理时我们会关注redis的实时内存占用,即通过info memory命令查看内存使用情况: 我们比较常关注的是used_memory以及used_memory_rss,这两项分别是redis中的数据占用的内存以及redis向操作系统申请的所有内存,可以看到这里这两项差距是很大的,我们也可以通过另一项更直观的观察这两项的差距,即mem_fragmentation_ratio mem_fragmentation_ratio = used_memory_rss / used_memory 但Redis申请了这么多内存是在干啥呢???非常的疑惑 需要了解的几个词 used_memory: Amount of memory (in bytes) used by Redis used_memory_rss: Memory allocated by the operating system mem_fragmentation_ratio: Ratio of memory allocated by the operating system to memory re ...
Python-asyncio异步编程基础
前言 asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持,并且如今asyncio的单线程异步性能已经做到与Go / Node持平 目前还没有基于asyncio开发大型项目的经历(主要还是在用golang) 需要了解的几个词 协程(coroutine):与线程很相似,不同之处在于多协程是同一个线程来执行的,这样就省去了线程切换的时间,而且不需要多线程的锁机制了,执行效率高很多 异步IO:异步IO的概念和同步IO相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者 事件循环:事件循环是一种处理多并发量的有效方式,在维基百科中它被描述为「一种等待程序分配事件或消息的编程架构」,我们可以定义事件循环来简化使用轮询方法来监控事件,通俗的说法就是「当A发生时,执行B」 asyncio 是什么 asyncio模块提供了使用协程构建并发应用的工具,它使用一种单线程单进程的的方式实现并发,应用的各个部分彼此合作, 可以显式的切换任务,一般会在程序阻塞I/O操作的时候发生上下文切换如等待读写文件,或 ...
Python-yield关键字详解
前言 yield这个关键字很早的时候就了解过,但一直都只了解其基本使用,即转变函数为生成器的使用,节省大型迭代时的内存空间,但其实yield在python的很多特性中都起着重要的作用 这篇文章就详细展开一下yield关键字 需要了解的几个词 容器(container):python中容器指一个用来存储多个元素的数据结构,常见的list,tuple,dict,set,string都是容器 可迭代对象(iterable):在python中能被迭代获取的对象,iterable的对象一定实现了__iter__()方法 迭代器(iterator):迭代器实现了__iter__()和 __next__()方法,是一个带状态的对象,迭代器内部持有一个状态,该状态用于记录**当前迭代所在位置,**以便于下次迭代的时候获取正确的元素,迭代器可以通过next()方法来迭代获取下一个值 生成器(generator):生成器是一种特殊的迭代器,特殊在我们可以通过send()方法向生成器中传入数据,而迭代器只能将数据输出 协程(coroutine):与线程很相似,不同之处在于多协程是同一个线程来执行的,这 ...
Python日志管理
前言 一个长时间运行的项目,不管是从可维护性还是其他角度来说,日志管理都是必不可少的(我相信还有不少同学是直接输出日志到控制台的吧),将日志输出到日志文件中,不仅方便我们查看程序运行时的情况,也可以让我们在项目出现故障时根据运行时产生的日志快速定位问题出现的位置 需要了解的词 单例模式:单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为(Wiki百科),我在另一篇文章里写了Go单例模式的实现:Go单例模式 好像暂时没有了,这篇文章很简单 日志级别 Python 标准库 logging 用作记录日志,默认分为六种日志级别(括号为级别对应的数值),NOTSET(0)、DEBUG(10)、INFO(20)、WARNING(30)、ERROR(40)、CRITICAL(50);如果需要自定义日志级别时注意不要和默认的日志级别数值相同,logging 执行时输出大于等于设置的日志级别的日志信息(不重要的不归我管),如设置日志级别是 IN ...
Redis分布式锁
前言 随着分布式系统的普遍运用,分布式锁的重要性也得到了体现 在单机系统中,我们可以运用普通的锁/信号量机制来实现对公共资源的有序访问;但在分布式系统中显然就不行了 因此业界常用的解决方案通常是借助于一个第三方组件,利用它自身的排他性来达到多进程的互斥;如: 基于 DB 的唯一索引 基于 ZK 的临时有序节点 基于 Redis 的 NX EX 参数 本文就主要以Redis分布式锁展开 需要了解的几个词 锁机制:锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足(Wiki百科) 死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程 ZK:即ZooKeeper,ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等 Redis分布式锁的基本原理 既然是选用了 Redis, ...
Go单例模式
前言 近期手上有一些需要定时任务的需求(Go定时任务可以看这一篇:Go-并发编程与定时器),而单例模式可以很好的保证定时任务不被重复创建,Go在官方库中也提供了优雅的单例模式实现方式,即sync包中的Once类型 Once 官方描述 Once is an object that will perform exactly one action,即 Once 是一个对象,它提供了保证某个动作只被执行一次功能,最典型的场景就是单例模式 需要了解的几个词 单例模式:单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理(Wiki百科) Goroutine:Go 程(goroutine)是由Go 运行时管理的轻量级线程。 go f(x, y, z). 会 ...
Redis的过期策略&内存淘汰策略
前言 Redis作为当下最受欢迎的NoSQL数据库之一,在很多场景下都会使用到;Redis的存储分为内存存储、磁盘存储和log文件三部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化 而内存存储向来都离不开内存管理的问题,本文就从Redis的内存过期策略和内存淘汰机制展开来讲 需要了解的几个词 LRU:LRU是Least Recently Used的缩写,即最久没有访问的内容作为替换对象,是一种常用的页面置换算法,其它常见的还有FIFO、LFU、NMRU等;值得一提的是,Redis中的LRU实现与常规的LRU并不相同,我在以后的文章中可能会总结(咕咕咕) 定时器:这里的定时器指通过各种方式(如管道)实现的定时任务触发器,Go中的定时器可见我的另一篇文章:Go 并发编程与定时器 持久化存储:一般对比于缓存存储,即cache-only模式,此模式下若服务停止 / 停机,则会造成数据丢失;而持久化存储则会为内存中的数据持久备份到磁盘文件,在服务重启后可以恢复,此模式下数据相对安全 内存过期策略 内存过期策 ...
细探Redis scan命令
前言 这周遇到的一个小需求是通过Go实现对Redis的hash field实时上限检查,而因为是线上的服务,所以这个上限检查不能对redis pod造成负担,跟组内导师交流学习后了解到可以通过redis的HScan命令来实现这个需求 需要了解的几个词 cursor(游标):数据库中常见的一个概念,通常提供一种从表中检索出的数据进行操作的灵活手段,能从包含数据记录的结果集中每次提取一条记录的机制 rehash:在redis的具体实现中,使用了一种叫做**渐进式哈希(rehashing)**的机制来提高dict的缩放效率 迭代完整性:保证完整遍历被遍历对象的性质 生产环境:不敢乱增加负载的环境(跑一下redis keys命令直接重大事故) Scan命令 Scan命令是什么 SCAN命令是基于游标(cursor)迭代的,SCAN命令并不单纯指代SCAN命令,还包含SSCAN、HSCAN、ZSCAN,每种命令操作对象是有区别的,但用法及功能基本相同 为什么要用Scan命令 当Redis中的数据量很大时,因为Redis是单线程服务,所以一些数据操作会导致Redis服务卡顿,甚至宕机 ...