redis key命名规范
1.建议全部大写
2.key不能太长也不能太短,键名越长越占资源,太短可读性太差
3.key 单词与单词之间以 : 分开
4.redis使用的时候注意命名空间,一个项目一个命名空间,项目内业务不同命名空间也不同。
user
id | userName | age |
1 | zhangsan | 18 |
2 | lisi | 16 |
一般情况下:
1) 第一段放置项目名或缩写 如 project
1) 第二段把表名转换为key前缀 如, user:
2) 第三段放置用于区分区key的字段,对应mysql中的主键的列名,如userid
3) 第四段放置主键值,如18,16
结合起来 PRO:USER:UID:18
常见的设置登录token
key: PRO:USER:LOGINNAME:373166324
value:12kd-dsj5ce-d4445-h4sd472
redis的过期策略
redis过期策略有两种,一种是主动式过期,另一种是被动式过期,redis采用两者相结合的方式来处理,因为单纯采用主动式过期,会影响redis的性能,单纯采用被动式过期,可能会导致大量内存得不到释放。
主动式过期(定期删除):
redis会将所有设置了过期时间的key放到一个独立的字典中,以后会定时扫描这个字典,将过期的key删除。redis默认每秒进行10次过期扫描,扫描不会扫描所有的key,而是采用一种贪心的策略来进行:
1. 从过期字典中随机选择20个key。
2. 将20个key中过期的key删除。
3. 如果过期的key的比例超过1/4,redis认为过期的key相对较多,会再次从步骤1依次执行。
同时为了保证扫描不会出现过度循环影响性能,redis会限制每次扫描的时间上限为25ms。
被动式过期(惰性删除):
redis定时扫描任务可能不会将过期的key完全删除,此时redis会用一种懒惰策略来被动式的更新过期的key,即当这个key被实际访问时,redis会检查这个key的过期状态,如果过期,那么将这个key删除
定时删除(基本不用):
在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除
缺点 : 若有很多个key同时到期,将会占用cpu大量的时间来删除key,不能让cpu做要紧的事,同时给key设置定时器也需要消耗一定的时间
redis 内存淘汰机制:
noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(常用)。
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个不太适)。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。
大key问题
出现大key的两种情况:
- 字符串: 单个的key存储的value值过大
- list hash set zset存储过多的元素
大key的风险:
因为redis是单线程的,对大key的读,写,删除可能会占用很长的事件,造成阻塞
大key的判别:
redis在计算大key的时候不是以key的占用内存大小来计算的,string是使用STRLEN方法来计算,list是llen来计算。
解决大key问题:
1 . 字符串: 单个的key存储的value值过大
- 可以将一个大key的value值拆分,存储到多个key中
- 也可以将value的值存储到hash中, field代表一个具体的属性,使用hget,hmget获取值,使用hset,hmset更新值
2. list hash set zset中存储过多的元素
将这些元素进行分拆
以hash为例,原先的正常存取流程是 hget(hashKey, field) ; hset(hashKey, field, value)
现在,固定一个桶的数量,比如 10000, 每次存取的时候,先在本地计算field的hash值,模除 10000, 确定了该field落在哪个key上
newHashKey = hashKey + (*hash*(field) % 10000);
hset (newHashKey, field, value) ;
hget(newHashKey, field)
删除大key :
hash key : 通过hscan命令 , 每次获取500字段, 再用hdel命令删除
set key : 使用sscan命令, 每次扫描500字段, 再用srem命令每次删除一个元素
list key : 通过使用ltrim命令每次删除少量元素
sorted set key : 使用sortedset自带的zremrangebyrank命令删除 top100个元素
key的扫描
scan命令扫描返回两个参数:
- 下次扫面游标所在的位置
- 本次扫描出来的全部结果