Redis应用
什么是Redis?
Remote Dictionary Server(Redis) 是一个 key-value 存储系统,它是基于内存的数据库,是跨平台的非关系型数据库。你可以把它作为数据库,缓存和消息中间件来使用。
由于数据量的增长,读写数据压力的不断增加,对于传统关系型数据库来说,硬盘I/O是一个很大的瓶颈,单台数据库承受四五千 QPS 压力已经很高了。关系型数据库擅长数据持久化存储,并不擅长平常服务高读写的操作,无法应对高并发、高性能、高可用的互联网使用。
数据结构是 key-value,从缓存中读取时,不是输入多个搜索条件来获得匹配的结果,而是输入一个 key 获得一个 value。每份缓存数据是 value,其标识是 key。
安装Redis
访问github.com/tporadowski…,点击Redis-x64-5.0.14.1.zip即可自动下载,下载完成后 ,将其解压缩,在其解压缩后的文件夹运行cmd,输入
redis-server.exe redis.windows.conf
显示以下图片所示即为运行成功。
保持此终端页面不要关,再运行一个cmd,输入
redis-cli.exe -h 127.0.0.1 -p 6379
终端变为 127.0.0.1:6379> 证明已经连接到Redis数据库了。
操作
指定的 key 不存在时,为 key 设置指定的值:
setnx KEY_NAME VALUE
在原有的数值上+1:
incr KEY_NAME
将 key 中储存的数字值减一
decr KEY_NAME
删除已存在的键
del KEY_NAME
设置过期时间(在指定时间后过期):
expireat KEY_NAME TIME_IN_UNIX_TIMESTAMP
队列推送:
lpush KEY_NAME VALUE1.. VALUEN
移出并获取列表的最后一个元素:
brpop LIST1 LIST2 .. LISTN TIMEOUT
返回列表中指定区间内的元素
lrange KEY_NAME START END
同时将多个 field-value (字段-值)对设置到哈希表中
hmset KEY_NAME FIELD1 VALUE1 ...FIELDN VALUEN
对Hash表中的字段增加值:
hincrby KEY_NAME FIELD_NAME INCR_BY_NUMBER
返回哈希表中指定字段的值:
hget KEY_NAME FIELD_NAME
让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
ltrim KEY_NAME START STOP
移除列表的最后一个元素,返回值为移除的元素:
rpop KEY_NAME
Redis注意事项
大Key(用户访问一个Key的QPS特别高,导致Server示例出现CPU负载突增或者不均的情况)会导致:
客户端执行命令的时长变慢。
Redis内存达到max memory参数定义的上限引发操作阻塞或重要的Key被逐出,甚至引发内存溢出(Out Of Memory)。
集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。
对大Key执行读请求,会使Redis实例的带宽使用率被占满,导致自身服务变慢,同时易波及相关的服务。
对大Key执行删除操作,易造成主库较长时间的阻塞,进而可能引发同步中断或主从切换。
热key(String类型:value的字节数大于10KB即为大key;Hash/ Set/ Zset/ list等复杂数据结构类型:元素个数大于5000个或总value字节数大于10MB即为大key)会导致:
占用大量的CPU资源,影响其他请求并导致整体性能降低。
集群架构下,产生访问倾斜,即某个数据分片被大量访问,而其他数据分片处于空闲状态,可能引起该数据分片的连接数被耗尽,新的连接建立请求被拒绝等问题。
在抢购或秒杀场景下,可能因商品对应库存Key的请求量过大,超出Redis处理能力造成超卖。
热Key的请求压力数量超出Redis的承受能力易造成缓存击穿,即大量请求将被直接指向后端的存储层,导致存储访问量激增甚至宕机,从而影响其他业务。
解决大key的方法
1.拆分 将大key拆分为小key。例如一个String拆分成多个String
2.压缩 将value压缩后写入redis,读取时解压后再使用。压缩算法可以是gzip、snappy、 1z4等。 通常情况下,一个压缩算法压缩率高、则解压耗时就长。需要对实际数据进行测试后,选择一个合适的算法。 如果存储的是JSON字符串,可以考虑使用Message Pack进行序列化。
3.集合类结构hash、list、set (1)拆分:可以用hash取余、 位掩码的方式决定放在哪个key中 (2)区分冷热:如榜单列表场景使用zset,只缓存前10页数据,后续数据走db
解决热key的方法
1.设置local cache 在访问Redis前,在业务服务侧设置local cache,降低访问Redis的QPS。Local Cache中 缓存过期或未命中,则从Redis中将数据更新到local Cache。Java的Guava、 Golang的Big cache就是这类local Cache。
2.拆分 将key : value这一个热Key复制写入多份, 例如key1 : value , key2 : value,访问的时候访问多个key,但value是同一个,以此将QPS分散到不同实例上,降低负载。代价是,更新时需要更新多个key,存在数据短暂不一致的风险。