【运维】
【1】持久化
(1)主库开启持久化或主库不设置开启自启
当主库没有开启持久化时,注意不要设置开机自启。
因为主库如果宕机重启后数据为空,这个时候如果重启了,那么主库数据为空,从库会重新同步新的空白数据 导致从库被清空。
(2)stop-writes-on-bgsave-error 参数设置为 no
当RDB持久化出现错误后,是否依然进行继续进行工作。
yes:不能进行工作
no:可以继续进行工作
可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误,如果设置成了YES则RDP文件如果持久化失败则整个实例宕机无法写入
(3)AOF参数:no-appendfsync-on-rewrite 参数设置为 no/yes
当执行bgrewriteaof 对aof文件重写时,不做预设的自动追加同步操作到aof文件上去。但默认会按30秒一次批量同步操作到aof文件中去。
该操作是为了避免大量磁盘操作导致系统卡顿
yes:当做 rewrite 操作时,不使用预设频率对新操作持久化同步到 aof 文件中去,而是用默认的30S同步一次; 该选项可能在极端情况下导致丢失30秒数据
no:当做 rewrite 操作时,继续维持原有的预设同步频率同步redis操作到 aof 文件中去。
建议HDD用 yes,SDD 用 no 。注意如果选 yes 该选项可能在极端情况下导致丢失30秒数据
【2】复制
(1)断开复制、重新连接其他主库(会清空之前数据)
切换主节点之后,从节点会清空之前的所有数据,线上操作的时候需要注意
(2)repl-backlog-size 5mb
复制积压缓冲区大小,为了避免网络闪断而缓冲区大小不够导致主从无法进行psync部分同步而重新进行全量复制同步,根据数据量来判断
复制积压缓冲区的最小大小可以根据公式 second*write_size_per_second 来估算:
- 其中second为从服务器断线后重新连接上主服务器所需的平均时间(以秒计算);
- 而 write_size_per_second 则是主服务器平均每秒产生的写命令数据量(协议格式的写命令的长度总和);
例如,如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要3秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于3MB。
【开发技巧】
使用 INCR,而不是 x=x+1
- 客户端A读取计数为10。
- 客户端B读取的计数为10。
- 客户A增加11,并将计数设置为11。
- 客户端B增加11,并将计数设置为11。
我们希望该值为12,但实际上为11!这是因为以这种方式增加值不是原子操作。在Redis中调用 INCR命令可以防止这种情况的发生,因为它是原子操作
由单个命令实现的所有Redis操作都是原子的,包括对更复杂的数据结构进行操作的操作。因此,当您使用修改某些值的Redis命令时,无需考虑并发访问。
使用setnx,而不是 set
- 原子性,可以用于实现分布式事务
- 更安全,不存在则创建
使用 mget/mset,而不是 get/set
同理,其他数据类型也一样。
1000次 get 和 1次 mget 对比表
操作 | 时间 |
---|---|
1000次get | 1000*1+1000*0.1=1100毫秒=1.1秒 |
1次mget(组装了100个键值对) | 1*1+1000*0.1=101毫秒=0.101秒 |
使用 scan/hscan 等系列,而不是 keys/getall/smembers/zrange
优势:
- scan 是渐进式遍历,不会一下子遍历所有key,它的时间复杂度是O(1)
- scan 因为是渐进式遍历不会阻塞,不会像keys那样在有大量key时比较容易造成阻塞
问题:
- scan 渐进式遍历可以有效解决keys 命令可能产生的阻塞问题,但是 scan也有自己的问题。
- 在scan的过程中如果有key有增删改变化,那么遍历的效果可能不尽人意
- 新增的键可能没有遍历到
- 遍历出现了重复的键
也就是说,scan 可能无法遍历检索出所有的key,这是我们需要考虑的。
【需要注意的点】
- persist 命令会删除任意类型键的过期时间
- set系列 命令也会删除字符串等类型的过期时间
【参考文件】
阿里云redis开发规范:https://developer.aliyun.com/article/531067