)
以下内容均以CentOS7为背景。一、Redis安装及启动mysql读2000/s写600/sredis读10w/s写8w/s通过官方给出的数据单机并发可以达到10w/sredis是基于key-value型的非关系型数据库目前redis无法取代关系型数据库的根本原因redis是基于内存的断电即丢失虽然有rdb和aof两种持久化机制但是因为持久化是异步的所以还是会存在数据丢失的情况redis官方版本以6.2.7为例版本号第一位是大版本第二位如果是奇数则该版本为非稳定版本偶数则相反首先在CentOS7中使用命令安装redis6.2.7wget https://download.redis.io/releases/redis-6.2.7.tar.gz当使用以上命令从官网获取到完整redis6.2.7安装包后再使用解压命令解压至opt/redis-6.2.7下tar -zxvf redis-6.2.7.tar.gz随后进入解压后的redis6.2.7文件夹中使用命令进行编译make至此redis安装完毕虽然redis是用c写的但是只依赖linux系统基本的类库一般情况下很少出问题。如果执行make命令报错cc未找到命令是因为虚拟机系统中缺少gcc库执行以下命令安装gcc库即可yum -y install gcc automake autoconf libtool make如果执行make命令报错致命错误:jemalloc/jemalloc.h:没有那个文件或目录则需要在make指定分配器为libc执行以下命令即可make MALLOClibcbin目录下可执行文件redis-server: 启动redisredis-cli: 命令行工具redis-benchmark: 基准测试工具redis-check-aof: AOF持久化文件检测和修复工具redis-check-rdb: RDB持久化文件检测和修复工具redis-sentinel: 启动哨兵启动方式一默认启动进入bin目录执行以下命令./redis-server二带参数启动以指定端口为例进入bin目录执行以下命令./redis-server --port 6380三配置文件启动进入bin目录执行以下命令./redis-server ../redis.conf如果要设置登陆密码则需要修改配置文件中的requirepass参数redis-cli命令行工具支持两种方式:一不带参数默认是连本地的redis服务./redis-cli二带参数单条命令./redis-cli -p 6379 set key value停止redis一杀死进程强制停止直接杀死进程会使redis还没有来得及做持久化就被强制停止导致数据丢失kill -9 pid二在命令行工具内shutdown有NOSAVE|SAVE两种默认是SAVE二、Redis全局命令查看所有键keys *(查看所有不推荐使用该命令如果数据量过大该命令会导致线程阻塞时间复杂度为O(n))keys u*带通配符dbsize查看redis内key总数该命令基于计数器所以效率很快时间复杂度为O(1)exists(查看某一键是否存在存在返回1不存在则返回0)del(删除指定键后面可跟多个key返回删除键的数量)expire(对指定键设置过期时间以秒为单位成功返回1失败返回0)pexpire(对指定键设置过期时间以毫秒为单位成功返回1失败返回0)ttl查看指定键的过期时间如果键存在且设置的有过期时间则返回剩余的过期时间如果键存在但是没有设置过期时间则返回-1如果键不存在则返回-2存在过期时间但是还没有过期返回剩余过期时间键存在但是永不过期返回-1键不存在返回-2expireat(对指定键设置指定时间过期时间戳成功返回1失败返回0)对于key设置过期时间需要注意如果对一个可以设置完过期时间之后再次进行set 这个key时会将之前的key覆盖掉同时会将对之前key设置的过期时间抹去type查看指定key的数据类型如果存在返回该key的数据类型如果不存在则返回nonerename对指定key重命名成功返回OK失败返回no such key对于某一个key重命名不会导致过期时间失效如果在重命名的过程中发现key已经存在则会将value进行覆盖renamenx如果新key已经存在则不修改成功返回1失败返回0randomkey从已有的key中随机返回一个key三、数据类型String:Redis的String类型并没有直接使用C的String类型而是自己去实现的。字符串最大不能超过512M。一般用于缓存、共享session、计数器等时间复杂度基本都是O(1)。命令set key value n次网络n次命令get key 获取指定key的value值setnx key value添加的键必须不存在才可以设置set key value nx上一条命令的变种效果一样不存在才设置set key value xx 存在才设置mset [key value]批量添加 1次网络n次命令mget [key value]批量获取 1次网络n次命令incr key 键自增decr key 键自减incrby key increment 指定键按照指定步长自增decrby key decrement 指定键按照指定步长自减incrbyfloat key increment指定键按照指定步长自增append key value 指定键后面追加内容strlen key 返回字符串value的长度getset key value 返回set之前的value值setrange key offsetvalue 在指定key的value指定位置上添加值getrange key start end返回指定key指定范围内的数据Hash:命令hset key field value哈希添加hget key field 哈希获取hsetnx key field value 不存在添加hdel key field 删除指定key的指定字段hlen key 获取指定key的字段数hmset key field value 批量添加hmget key field 批量获取hexists key field 查看指定key下指定字段是否存在hkeys key 获取指定key下所有fieldhvals key 获取指定key下所有valuehgetall key 获取指定key下所有field-valuehincrby key field increment 指定key下指定field按照指定步长自增List:有序的可以有重复的元素list最大的存储元素个数2的32次方-142 9496 7295文章列表分页等消息队列命令rpush key element从右边插入元素lpush key element从左边插入元素rpop key 从右边弹出元素lpop key 从左边弹出元素lrang key start end 从左边截取指定长度的数据并返回lrem key count element 删除指定key中指定数量的指定元素ltrim key start end 保留从指定起止裁剪指定key的listlset key index element 将指定key的指定位置设置为指定元素lindex key index 获取指定key指定位置上的元素llen key 获取指定key的元素长度blpop key timeout 阻塞式左边弹出如果有元素直接返回如果没有元素则阻塞至超时返回如果将timeout设置为0则一直阻塞brpop key timeout 阻塞式右边弹出如果有元素直接返回如果没有元素则阻塞至超时返回如果将timeout设置为0则一直阻塞Set:无序的不允许有重复的元素最大的存储元素个数2的32次方-142 9496 7295标签、共同爱好等命令sadd key member添加元素并且过滤掉重复元素smembers key 查看指定key的元素集合srem key member 删除指定key下的指定元素scard key 统计指定key下有多少个元素sismember key member 判断指定key下是否包含指定元素1存在0不存在srandmember key count 随机返回指定key下的某个元素不设置count默认为1个spop key 从指定key中随机弹出一个元素sinter keys查看多个指定key中的交集sunion keys查看多个指定key中的并集sdiff keys查看多个指定key中的差集sinterstore destination keys 查看多个指定key中的交集并将结果保存为一个集合Zset:有序的不允许有重复的元素可以用作排行榜命令zadd key score member添加指定key中的score和memberzcard key查看指定key中包含的元素zscore key member 查看指定key中指定member的scorezrank key member查看指定key中指定member的排名zrevrank key member在上一条命令的基础上进行排名的反转zrem key member删除指定key中指定memberzincrby key increment member 将指定key中的指定member增加指定的数zrange key min max按照指定范围内查看指定key中的结果集默认升序zrevrange key min max 基于上条命令的倒序zrangebyscore key min max 按照score指定范围内指定key中的memberBitmaps:按位存储网站统计访问量、布隆过滤器关于布隆过滤器误判的问题本质是hash冲突导致的通过hash计算在数组上的不一定在但是不在数组上的一定不存在解决方案是增大数组增加hash函数缓存穿透命令setbit key offset value对指定key的某个偏移量上设置valuegetbit key offset 获取指定key下指定偏移量是否存在1存在0不存在bitcount key start end 统计指定key中的数量GEO:地理定位信息支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能命令geoadd key lon lat member向指定key中添加元素以及经纬度geopos key member 获取指定key中member的经纬度HyperLogLog:大型网站每个网页每天的UV独立访客数据HyperLogLog提供不精确的去重计数方案标准误差是0.81%HyperLogLog基于概率论中伯努利试验并结合了极大似然估算方法并做了分桶优化命令pfadd key element 指定key添加elementpfcount key 统计指定key下的所有元素四、Redis高级特性与应用慢查询redis的慢查询记录在slowlog的链表中内存队列链表的长度在redis.conf中由参数slowlog-max-len控制通过slowlog-log-slower-than配置慢查询阈值以微秒为单位可以通过动态的设置如果设置为负值则都不记录redis执行命令分为四个阶段第一阶段为发送命令将命令由客户端发送至服务端第二阶段排队接收到客户端发送的命令后排队第三阶段执行命令慢查询指的就是在第三阶段的耗时第四阶段就是返回结果。在redis-cli工具中可以通过以下命令动态设置慢查询阈值并回显到配置文件中config set slowlog-log-slower-than 20000设置慢查询阈值config rewrite 回显可以通过以下命令查看慢查询记录slowlog subcommand argument可以通过以下命令清空内存中的慢查询记录链表slowlog resetPipelineredis执行命令大多都很快但是由于网络io可能会导致RTTRound-Trip Time 往返时间在计算机网络中它是一个重要的性能指标表示从发送端发送数据开始到发送端收到来自接收端的确认不包含数据传输时间总共经历的时间RTT由三个部分决定链路的传播时间、末端系统的处理时间、路由器的缓存中的排队和处理时间变长所以可以使用Pipeline技术批量操作减少网络io带来的延迟提高吞吐量。事务redis中的事务只能判断最基本的语法错误运行时的错误无法回滚无法保证事务的原子性所以一般不采用redis的事务机制。multi开启事务exec执行watch机制属于一种cas操作将指定的元素监控起来如果该元素被其他客户端修改则该事务执行失败。watch keyLualua脚本语言是c开发的类似于存储过程在lua脚本中可以把多个命令放在同一个脚本中运行redis会将整个脚本作为一个整体执行中间不会被其他命令插入可以减少网络开销客户端发送的脚本会存储在redis中这意味着其他客户端可以复用这一脚本来完成同样的逻辑应用场景分布式限流。redis2.6及以上内嵌支持了lua脚本。eval script numkeys key arg script脚本 numkeys key的数量 key key列表 arg 参数列表script load 缓存指定脚本evalsha 从缓存中引用指定脚本发布 订阅发送即忘publish channel message此时返回的0是当前订阅该消息的订阅者数量因为当前消息组没有人订阅该消息被丢弃再起一个客户端去订阅这个组当订阅完成再去发送消息此时订阅该消息的客户端将会接收到消息查看当前所有消息组也支持通配符查找查看指定消息组的订阅者数量更多的命令可以通过help查看StreamStream是一种新的数据类型于Redis 5.0版本中引入。它是一个有序、持久化、可重复读的消息流可以用于实现消息队列、日志系统等应用场景。向指定队列添加消息*代表通配符表示id由redis生成查看指定队列中的消息查看指定队列中消息的数量删除指定生产者中的消息从指定生产者中读取指定数量及范围的消息从指定生产者中阻塞式读取指定数量及范围的消息对指定生产者创建消费者群组查看指定生产者的信息查看订阅了指定生产者的消息群组指定消费群组的消费者来消费指定生产者的消息确认接受消息五、Redis数据结构redis采用全局哈希表的方式哈希表由数组加链表构成每一个entry包含key指针、value指针、以及next指针如果数组长度过短会导致链表过长当链表数据过长时会rehash对数组进行扩容数组扩容之后之前的链表上的数据需要迁移到数组重新计算之后的索引上如果数据量过大会导致IO阻塞redis则采用两张全局hash表以及渐进式rehash的方式解决六、Redis的持久化Redis支持RDB和AOF两种持久化方式RDB有两个命令可以手动去生成快照save会占用主线程导致阻塞执行完之后会在执行目录中多出一个dump.rdb的文件bgsave非阻塞式redis默认的保存快照的方式会创建一个子线程用于保存快照在redis的配置文件中可以去配置触发自动保存的策略在redis.conf中如下save 3600 1 3600秒之内保存一次触发save 300 100 300秒之内保存100次触发save 60 10000 60秒之内保存10000次触发如上触发策略可以有多个只要满足一个就会触发bgsave操作。bgsave操作避免阻塞的原理当触发bgsave操作时Redis会fork出一个子进程负责将Redis当前内存中的数据写入RDB文件中。子进程首先将所有键值对写入临时文件中。当所有键值对都写入完毕后子进程用新的RDB文件替换旧的RDB文件。在此期间Redis主进程仍然可以处理客户端请求并向子进程发送新的写命令以更新临时文件。与此同时Redis还会记录RDB文件生成的时间戳以及最后一次成功执行bgsave命令的时间戳。Redis的自动持久化机制1、在使用shutdown结束Redis时Redis会自动使用RED的方式进行持久化2、从节点执行全量赋值操作主节点会自动执行bgsave操作生成一个RDB文件发送给从节点。在redis.conf文件中可以通过dbfilename属性设置生成的RDB文件的名字dir属性设置文件保存路径如果不想触发任何保存操作则将save保存策略全部注释掉并添加save “ ”则Redis不会再触发自动保存操作或者可以通过在redis-cli工具中执行config set value命令动态的进行设置。RDB文件是一种二进制的压缩文件在redis.conf中rdbcompression属性默认为yes指开启动态压缩算法采用了一种LZF的压缩算法。可通过redis-check-rdb或redis-check-aof对rdb或aof文件进行校验返回ok则成功Redis的AOF持久化Redis中的AOF持久化机制遵循RESP的文本协议appendonly开启AOF持久化的参数 默认为no 不开启appendfilename指定aof文件名以命令的形式触发aof重写appendfsync always 每一次写命令同步一次会导致redis的效率非常低appendfsync everysec 每秒钟同步一次写命令appendfsync no 由操作系统控制一般默认周期为30秒可能会导致数据丢失aof重写时文件的最小体积Redis重启加载流程Redis采用混合持久化模式通过配置文件中aof-use-rdb-preamble参数控制默认为yes开启混合持久化流程通过info stats命令可以查看fork出子进程消耗的时间单位微秒七、Redis的分布式锁基于Redis中setnx命令的互斥以上可能会造成死锁的问题可以通过加过期时间解决八、Redis的复制由于时间原因后面还有很长的篇幅随缘更新。。。