redis의 bitset은 bit 단위의 값을 저장하고 읽을 때 유용하다. c나 c++ 쪽으로 개발했던 사람이라면 bit opersation은 일종의 flag 연산에 최고의 희열을 느꼈을 만하다.
http://redis.io/commands/setbit
사용법은 아주 간단하다.
setbit <key> <offset> <0 or 1> |
jedis를 사용해서 테스트를 진행해본다. 잘 저장되고 잘 받을 수 있다.
private static void test1() throws Exception { |
내부를 잠깐 살펴보면..
jedis.setbit() 메소드는 key값, offset, boolean 을 넣도록 되어 있다.
public Long setbit(byte[] key, long offset, byte[] value)
public boolean setbit(String key, long offset, boolean value);
두 개의 메소드의 원형을 본다.
1. 2. key과 value가 byte[] 타입
BinaryJedis.java
public Long setbit(byte[] key, long offset, byte[] value) {
client.setbit(key, offset, value);
return client.getIntegerReply();
}
BinaryClient.java
public void setbit(byte[] key, long offset, byte[] value) {
sendCommand(SETBIT, key, toByteArray(offset), value);
}
Connection.java
protected Connection sendCommand(final Command cmd, final byte[]... args) {
connect();
protocol.sendCommand(outputStream, cmd, args);
pipelinedCommands++;
return this;
}
Protocol.java
public void sendCommand(final RedisOutputStream os, final Command command,
final byte[]... args) {
sendCommand(os, command.raw, args);
}
private void sendCommand(final RedisOutputStream os, final byte[] command,
final byte[]... args) {
try {
os.write(ASTERISK_BYTE);
os.writeIntCrLf(args.length + 1);
os.write(DOLLAR_BYTE);
os.writeIntCrLf(command.length);
os.write(command);
os.writeCrLf();
for (final byte[] arg : args) {
os.write(DOLLAR_BYTE);
os.writeIntCrLf(arg.length);
os.write(arg);
os.writeCrLf();
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
}
여기까지 write 하기..
read하는 부분이다.
Connection.java
public Long getIntegerReply() {
flush();
pipelinedCommands--;
return (Long) protocol.read(inputStream);
}
Protoocol.java
public Object read(final RedisInputStream is) {
return process(is);
}
private Object process(final RedisInputStream is) {
try {
byte b = is.readByte();
if (b == MINUS_BYTE) {
processError(is);
} else if (b == ASTERISK_BYTE) {
return processMultiBulkReply(is);
} else if (b == COLON_BYTE) {
return processInteger(is);
} else if (b == DOLLAR_BYTE) {
return processBulkReply(is);
} else if (b == PLUS_BYTE) {
return processStatusCodeReply(is);
} else {
throw new JedisConnectionException("Unknown reply: " + (char) b);
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
return null;
}
2. key과 value가 각각 String, boolean 타입
public boolean setbit(String key, long offset, boolean value) {
client.setbit(key, offset, value);
return client.getIntegerReply() == 1;
}
Client.java
public void setbit(final String key, final long offset, final boolean value) {
setbit(SafeEncoder.encode(key), offset, toByteArray(value ? 1 : 0));
}
public class SafeEncoder {
public static byte[] encode(final String str) {
try {
if (str == null) {
throw new JedisDataException(
"value sent to redis cannot be null");
}
return str.getBytes(Protocol.CHARSET);
} catch (UnsupportedEncodingException e) {
throw new JedisException(e);
}
}
public static final byte[] toByteArray(final int value) {
return SafeEncoder.encode(String.valueOf(value));
}
잘 못 사용하는 경우에 “ERR bit is not an integer or out of range” 가 일어날 수 있다.
boolean 값으로 들어갈 0,1 을 제외한 다른 값이 들어오면 “ERR bit is not an integer or out of range” Data Exception 발생이 된다. 서버에서 ‘–’ 마이너스 값을 던져준다.
jedis.setbit(new byte[] {0}, 1, toByteArray(3)); byte[] a = jedis.get(new byte[]{0}); System.out.println(a[0]); |
Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: ERR bit is not an integer or out of range
at redis.clients.jedis.Protocol.processError(Protocol.java:54)
at redis.clients.jedis.Protocol.process(Protocol.java:61)
at redis.clients.jedis.Protocol.read(Protocol.java:122)
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:178)
at redis.clients.jedis.BinaryJedis.setbit(BinaryJedis.java:2965)
at BitSetTest.main(BitSetTest.java:14)
'general java' 카테고리의 다른 글
ubuntu에서 thrift 0.6 installation(설치) 가이드 (0) | 2012.04.25 |
---|---|
Redis와 BitSet (jedis 이용) (1) | 2012.04.10 |
[Hudson+Spring Batch] master/slave 구성하기 (0) | 2012.03.26 |
전화번호와 관련된 자바 라이브러리 (0) | 2012.03.19 |
카산드라(cassandra)의 블룸필터 (bloom filter) (0) | 2012.03.02 |