redis笔记

笔记

redis

各种数据结构的使用

  • 字符类型
    一个字符类型的key默认存储的最大容量是512m
    set key value
    get key
    incr key
    append key value
    strlen key 获取key对应的value长度
    mget key key 同时获得多个key的value
  • 列表类型
    list,可以存储一个有序的字符串列表,可以用来做分布式消息队列
    lpush/rpush
    llen num
    lrange key start stop
    lpop/rpop
  • 散列类型
    hash, 比较适合存储对象
    hash key value
    hset key field value
    hexists key field 判断字段是否存在。存在返回1,不存在返回0
  • 集合类型
    set跟list不一样的店。集合类型不能存重复的数据,而且是无序的
    sadd key member [member …] 增加数据
    srem key member 删除元素
    smembers key 获取所有数据
    sdiff key key 对多个集合执行差集运算
  • 有序集合
    zadd key score member
    如果两个元素的score相同的话,那么根据(0<9<A<Z<a<z)方式从小到大

分布式锁的解决方案

  1. 数据库锁
    数据库,通过唯一约束
lock(
	id int(11),
	method_name varchar(100),
	remark varchar(1000),
	modify_time timestamp
	unique key uk_mn(method_name) -- 唯一约束
)

获取锁的伪代码

try{
	exec insert into lock(methodName, remark)
	values('method', 'desc');
	return true;
} catch (DuplicateException e){
	return false;
}
//释放锁
delete from lock where methodName='xxx';

需要考虑的问题

  1. 锁没有失效时间,一旦释放锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得锁
  2. 锁是非阻塞的,数据的insert操作,一旦插入失败就会直接报错
  3. 锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁

基于缓存的分布式锁实现

public class RedisManager {
	private static JedisPool jedisPool;
	static {
		JedicPoolConfig jpc = new JedicPoolConfig();
		jpc.setMaxTotal(20);
		jpc.setMaxIdle(10);
		jedisPool = new JedisPool(jpc, "192.168.11.140", 6379);
	}
	public static Jedis getJedis() throws Exception {
		if (null != jedisPoll) {
			return jedisPool.getResource();
		}
		throw new Exception("");
	}
}

//获得锁
public String getLock(String key, int timeout) {
	try {
		Jedis jedis = RedisManager.getJedis();
		String value = UUID.randomUUID().toString();
		long end = System.currentTimeMillis() + timeout;
		while (System.currentTimeMillis() < end) {	//阻塞
			if (jedis.setnx(key,value) == 1) {
				jedis.expire(key, timeout);
				//锁设置成功,redis操作成功
				return value;
			}
			if (jedis.ttl(key) == -1) {//检测过期时间
				jedis.expire(key, timeout);
			}
			Thread.sleep(1000);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

//释放锁
public boolean releaseLock(String key, String value) {
	try {
		Jedis jedis = RedisManager.getJedis();
		while(true) {
			jedis.watch(key);
			if(value.equals(jedis.get(key)) {
				Transaction ts = jedis.multi();
				ts.del(key);
				List<Object> list = ts.exec();
				if(list == null) {
					continue;	
				}
				return true;
			}
			jedis.unwatch();
			break;
		}
	} catch (Exception e) {
	}
}

redis持久化

RDB的持久化策略:按照规则定时将内存的数据同步到磁盘
redis在指定情况下回触发快照

  1. 自己配置的快照规则
    save [second] [changes] 当在second秒内被更改的key的数量大于changes时,执行快照
  2. save或者bgsave
    save:执行内存的数据同步到磁盘操作,这个操作会阻塞客户端的请求
    bgsave:在后台异步执行快照操作,不会阻塞客户的请求
  3. 执行flushall的时候
    清除内存的所有数据,只要快照的规则不为空,那么redis会执行快照
  4. 执行复制的时候

快照的实现原理

  1. redis使用fork函数复制一份当前进程的副本(子进程)
  2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中数据写入硬盘中的临时文件
  3. 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,一次快照操作完成

RDB的优缺点

  1. 使用RDB方式实现持久化,一单redis异常退出,就会丢失最后一次快照以后更改的所有数据
  2. fork比较耗时,造成一段时间内停止客户端请求

AOF
aof将redis执行的每一条写命令追加到硬盘文件中;
aof文件损坏以后如何修复

  1. 为现有的aof文件创建一个备份
  2. 使用redis附带的redis-check-aof程序,进行aof文件恢复

RDB和AOF,如何选择
如果可以承受数分钟的数据丢失,可以只使用RDB持久化。如果同时使用,redis重启时,会优先使用aof文件还原数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值