rongxionga 2020-07-28
Redis
Redis的五大数据类型:
String(字符串):String是redis最基本的类型,一个key对应一个value;String类型是二进制安全的。 即redis的String可以包含任何数据。比如jpg图片或者序列化的对象;String类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M。 Hash(包含键值对的无序散列表):Redis hash是一个键值对集合;Redis hash是一个String类型的field和value的映射表,hash特别适合用于存储对象。类似Java中的Map<String,Object>。 List(列表):Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部或者尾部,它的底层实际是个链表。 Set(集合):Redis的Set是string类型的无序集合。它是通过HashTable实现实现的。 Zset(有序集合):Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。 端口号:6379
常用指令
key: keys * exists key的名字,判断某个key是否存在 move key db --->当前库就没有了,被移除了 expire key 秒钟:为给定的key设置过期时间 ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期 type key 查看你的key是什么类型 String:单值单value set/get/del/append/strlen Incr/decr/incrby/decrby,一定要是数字才能进行加减 getrange/setrange setex(set with expire)键秒值/setnx(set if not exist) mset/mget/msetnx getset(先get再set) List:单值多value lpush/rpush/lrange lpop/rpop lindex,按照索引下标获得元素(从上到下) llen lrem key 删N个value ltrim key 开始index 结束index,截取指定范围的值后再赋值给key rpoplpush 源列表 目的列表 lset key index value linsert key before/after 值1 值2 Set:单值多value sadd/smembers/sismember scard,获取集合里面的元素个数 srem key value 删除集合中元素 srandmember key 某个整数(随机出几个数) spop key 随机出栈 smove key1 key2 在key1里某个值 作用是将key1里的某个值赋给key2 数学集合类 差集:sdiff 交集:sinter 并集:sunion Hash:KV模式不变,但V是一个键值对 hset/hget/hmset/hmget/hgetall/hdel hlen hexists key 在key里面的某个值的key hkeys/hvals hincrby/hincrbyfloat hsetnx Zset:在Set基础上加一个Score值 zadd/zrange Withscores zrangebyscore key 开始score 结束score zrem key 某score下对应的value值,作用是删除元素 zcard/zcount key score区间/zrank key values值,作用是获得下标值/zscore key 对应值,获得分数 zrevrank key values值,作用是逆序获得下标值 zrevrange zrevrangebyscore key 结束score 开始score
RDB(Redis DataBase)
是什么:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。 Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
RDB的缺点是最后一次持久化后的数据可能丢失。
Fork的作用:复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。 优势:适合大规模的数据恢复;对数据完整性和一致性要求不高的情况 劣势:在一定时间间隔做一次备份,所以如果redis以外down掉,会丢失最后一次快照后的所有修改; Fork时,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。
AOF(Append Only File)
是什么:以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据, 换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。 Rewrite: 是什么:AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩, 只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof。 重写原理:AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename), 遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。 触发机制:Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。 优势:可以有每次修改同步、每秒同步、不同步三种方式。 劣势:相同数据集的数据,AOF文件要远大于RDB文件,恢复速度慢;AOF在不同步时运行效率才能和RDB相同。
RDB和AOF比较
1.RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储 2.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾. Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。 3.只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式. 建议: 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。 如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO, 二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率, AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。 如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。 代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构
事务
是什么:可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞。 常用命令:DISCARD / EXEC / MULTI / UNWATCH / WATCH key[key ...] watch监控:Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行。 通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败 特性: 1.单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 2.没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行, 也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题。 3.不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
主从复制
是什么:主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。 优点:读写分离,容灾恢复。 缺点:由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟, 当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。 如何做: 1.配置从库,不配置主库。 2.从库配置:slaveof 主库IP 主库端口 3. 一主二仆:(一个Master,两个Slave) 薪火相传:上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力 反客为主:SLAVEOF no one,使当前数据库停止与其他数据库的同步,转成主数据库 复制原理:Slave启动成功连接到master后会发送一个sync命令 Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行 哨兵模式(sentinel): 反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库 一组sentinel能同时监控多个Master
JedisPool
JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。 maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制; 如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。 maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例; whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。 WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException; WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException; WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用; maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException; testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的;