Redis使用bitmap、zset、hash、list等结构完成骚操作?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis使用bitmap、zset、hash、list等结构完成骚操作?相关的知识,希望对你有一定的参考价值。

参考技术A

当同时满足以下条件时,使用ziplist编码:

SpringBoot—实现n秒内出现x个异常报警

思路:
借助Redis的zSet集合,score存储的是异常时的时间戳,获取一定时间范围内的set集合。判断set个数是否满足条件,若满足条件则触发报警;

注意点:

相关API:

Redis实现延迟队列方法介绍
基于Redis实现DelayQueue延迟队列设计方案

相关API:

SpringBoot2.x—使用Redis的bitmap实现布隆过滤器(Guava中BF算法)

布隆过滤器: 是专门用来检测集合中是否存在特定元素的数据结构。
存在误差率: 即将不在集合的元素误判在集合中。

所以布隆过滤器适合查询准确度要求没这么苛刻,但是对时间、空间效率比较高的场景。

实现方式:Redis实现布隆过滤器——借鉴Guava的BF算法:

SpringBoot2.x中使用Redis的bitmap结构(工具类)

注意:bitmap使用存在风险,若仅仅计算hash值,会导致bitmap占用空间过大。一般需要对hash值进行取余处理。

根据Redis是否存在key,判断锁是否被获取;

锁应该是一个对象,记录持有锁的线程信息、当前重入次数。所以应该使用Redis的Hash结构来存储锁对象。

3.1 网络波动造成释放锁失败怎么解决?

需要为锁加上超时时间;

3.2 任务未执行完毕时,锁由于超时时间被释放?

线程一旦加锁成功,可以启动一个后台线程,每隔多少秒检查一次,如果线程还持有锁,可以不断延长锁的生存时间。

主从切换时,从服务器上没有加锁信息,导致多个客户端同时加锁。

list结构底层是ziplist/quicklist(可看着一个双端队列)。常用命令:

使用list作为对象的缓存池。通过rpush放入对象,通过lpop取出对象。

若是阻塞取,可以使用blpop命令实现。

Redis和Lua脚本(实现令牌桶限流)

数据结构选择hash。
hash里面维护:最后放入令牌时间、当前桶内令牌量、桶内最大数量、令牌放置速度(元数据)。

被动式维护:

命令:incr原子累加;

对一段固定时间窗口内的请求进行计数,如果请求数超过了阈值,则舍弃该请求;如果没有达到设定的阈值,则接受该请求,且计数加1。当窗口时间结束,重置计数器为0。

优点:实现简单,容易理解;
缺点:流量曲线可能不够平滑,有“突刺现象”。

1. 一段时间内(不超过时间窗口)系统服务不可用。 比如窗口大小1s,限流为100,恰好某个窗口第1ms来了100个请求,然后2ms-999ms请求都会被拒绝。这段时间用户会感觉系统服务不可用(即不够平滑)。

2. 窗口切换时可能会出现两倍于阈值流量的请求。 比如窗口大小1s,限流大小100,然后在某个窗口的第999ms有100个请求,窗口前期没有请求。所以这100个请求都会通过。然后下一个窗口的第1ms又来100个请求,然后全部通过。其实也是1ms内通过的200个请求。

命令:Redis的incr命令

是对固定窗口计数器的优化,解决的是切换窗口两倍阈值流量的场景。

具体解决方案是:将限流窗口分为多个小的限流窗口,各个限流窗口分别计数。当前时间大于窗口最大时间时,将头部的小窗口数据舍弃,尾部新增小窗口来处理新请求。

优点:本质上是对固定窗口的优化

Redis 5.0部署

**redis支持的数据类型:**

* 字符串(string)
* 哈希表(hash)
* 列表(list)
* 集合(set)
* 有序集合(zset)
* 位图(bitmaps)
* HyperLoglogs、GEO等
**redis特性如下:**

* 速度快:基于内存工作,使用离OS最近的C语言编写,使用单线程架构,预防了多线程可能产生的竞争问题。
* 基于键值对的数据结构服务器:redis中的值不仅仅可以是字符串,关于其支持的数据类型已经在文章开头列出来了。
* 丰富的功能:
* 1.键过期功能,用来实现缓存。
* 2.发布订阅功能,用来实现消息系统。
* 3.支持Lua脚本,可以利用Lua创造出新的Redis命令。
* 4.简单的事务功能,能在一定程度上保证事务的特性。
* 5.提供了流水线(pipeline)功能,这样客户端能将一批命令一次性传到redis,较少网络开销。
* 简单稳定。
* 客户端语言多:支持java、PHP、Python、C、C++、Nodejs等。
* 数据持久化:redis工作在内存中,支持两种持久化方式:RDB、AOF来写入到硬盘中。
* 主从复制:Redis提供了复制功能,实现了多个相同数据的redis副本。
* 高可用和分布式:Redis从2.8版本正式提供了高可用实现redis Sentinel,它能够保证Reids节点的故障发现和故障自动转移,从3.0版本提供了分布式实现Redis
* Cluster,他是redis真正的分布式实现,提供了高可用、读写和容量的扩展性。
**redis的7个使用场景:**

* 缓存。
* 计数器。
* 队列。
* 位操作(大数据处理)。
* 分布式锁与单线程机制。
* 最新列表。
* 排行榜。

一 、 部署redis 5.0
1、下载并解压


[root@redis ~]# wget http://download.redis.io/releases/redis-5.0.5.tar.gz
[root@redis ~]# tar zxf redis-5.0.5.tar.gz 
[root@redis ~]# cd redis-5.0.5/
[root@redis redis-5.0.5]# make

2、准备工作目录及redis所需文件


[root@redis redis-5.0.5]# mkdir -p /usr/local/redis/{bin,conf,data}   #创建目录
[root@redis redis-5.0.5]# cp src/redis* /usr/local/redis/bin/    #拷贝命令
[root@redis redis-5.0.5]# cp redis.conf /usr/local/redis/conf/    # 拷贝配置文件
[root@redis redis-5.0.5]# cd /usr/local/redis/bin/   #进入命令目录下,删除不必要的文件
[root@redis bin]# rm -rf *.c
[root@redis bin]# rm -rf *.h
[root@redis bin]# rm -rf *.o
[root@redis bin]# cd ../conf/
[root@redis conf]# cp redis.conf{,.bak}    #备份配置文件
[root@redis conf]# egrep -v ‘^$|^#‘ redis.conf.bak > redis.conf   
#过滤注释及空行以便生成新的配置文件

3、修改配置文件


[root@redis conf]# vim redis.conf      #更改配置文件如下
bind 0.0.0.0    #更改位监听所有地址
port 6379
daemonize yes     #启用守护进程
pidfile /usr/local/redis/data/redis_6379.pid    #指定pid文件
logfile "/usr/local/redis/data/redis.log"   #指定日志文件
#添加命令路径到全局命令搜索路径下
[root@redis bin]# echo ‘export PATH=${PATH}:/usr/local/redis/bin‘ >> /etc/profile
[root@redis bin]# source /etc/profile
[root@redis bin]# redis-server -v   #查看redis版本
Redis server v=5.0.5 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=94d37e8f5f58aed5

4、启动redis


[root@redis bin]# redis-server /usr/local/redis/conf/redis.conf   #启动redis
[root@redis bin]# ss -anpt | grep 6379    #确定端口在监听
LISTEN     0      128          *:6379                     *:*                   users:(("redis-server",pid=66992,fd=6))
[root@redis bin]# redis-cli    #本机可直接使用redis-cli进行登录
127.0.0.1:6379> 
[root@redis bin]# redis-cli -h 192.168.171.134 -p 6379   #若远端登录,则需要指定IP及端口
192.168.171.134:6379> 

5、查看redis日志,解决warning问题


[root@redis bin]# cat /usr/local/redis/data/redis.log   #查看redis日志

会发现redis在启动时,报有以下几个warning:
技术图片
接下来就解决这些warning问题(如果不解决这些问题,redis的性能会受到很大的影响)。
1)解决最大打开文件数问题


[root@redis ~]# ulimit -n    #查看当前值
1024
[root@redis ~]# vim /etc/security/limits.conf      #在文件末尾写入下面内容
*   -   nofile      10240
#修改后,重新登录即可生效,重新登录后再次查看当前值
[root@redis ~]# ulimit -n
10240

2)解决TCP积压值过小问题


[root@redis ~]# echo "net.core.somaxconn = 1024" > /etc/sysctl.d/redis.conf
[root@redis ~]# sysctl -p /etc/sysctl.d/redis.conf   #刷新使其生效
net.core.somaxconn = 1024

3)解决内存方面warning问题


[root@redis ~]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.d/redis.conf
[root@redis ~]# sysctl -p /etc/sysctl.d/redis.conf   #刷新使其生效
net.core.somaxconn = 1024
vm.overcommit_memory = 1

4)解决其他warning问题


[root@redis ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
#上述指令只是当前生效,重启后就会失效,接下来改为永久生效
[root@redis ~]# echo ‘echo never > /sys/kernel/mm/transparent_hugepage/enabled‘ >> /etc/rc.local
[root@redis ~]# chmod +x /etc/rc.d/rc.local

至此,reboot重启服务器也好,只是重启redis服务也好,都不会再报哪些warning问题了。如下:
技术图片

以上是关于Redis使用bitmap、zset、hash、list等结构完成骚操作?的主要内容,如果未能解决你的问题,请参考以下文章

Redis基础认识内存式NoSQL数据库及简单使用Redis

Redis入门--- 五大数据类型 以及三大特殊类型 ---Zset,Geospatial,Hyperloglog,Bitmap

Redis使用总结

Redis 使用场景分析

Redis高级数据类型HyperloglogBitmap快速带你上手!!!

Redis常用数据结构操作与底层原理