Git Product home page Git Product logo

redis's Introduction

redis.go

redis.go is a client for the redis key-value store.

Some features include:

  • Designed for Redis 2.6.x.
  • Support for all redis types - strings, lists, sets, sorted sets, and hashes
  • Very simple usage
  • Connection pooling ( with configurable size )
  • Support for concurrent access
  • Manages connections to the redis server, including dropped and timed out connections
  • Marshaling/Unmarshaling go types to hashes

This library is stable and is used in production environments. However, some commands have not been tested as thoroughly as others. If you find any bugs please file an issue!

Installation

Just run go get github.com/hoisie/redis

Examples

Most of the examples connect to a redis database running in the default port -- 6379.

Hello World example

package main

import "github.com/hoisie/redis"

func main() {
    var client redis.Client
    var key = "hello"
    client.Set(key, []byte("world"))
    val, _ := client.Get("hello")
    println(key, string(val))
}

Strings

var client redis.Client
client.Set("a", []byte("hello"))
val, _ := client.Get("a")
println(string(val))
client.Del("a")

Lists

var client redis.Client
vals := []string{"a", "b", "c", "d", "e"}
for _, v := range vals {
    client.Rpush("l", []byte(v))
}
dbvals,_ := client.Lrange("l", 0, 4)
for i, v := range dbvals {
    println(i,":",string(v))
}
client.Del("l")

Publish/Subscribe

sub := make(chan string, 1)
sub <- "foo"
messages := make(chan Message, 0)
go client.Subscribe(sub, nil, nil, nil, messages)

time.Sleep(10 * 1000 * 1000)
client.Publish("foo", []byte("bar"))

msg := <-messages
println("received from:", msg.Channel, " message:", string(msg.Message))

close(sub)
close(messages)

More examples coming soon. See redis_test.go for more usage examples.

Commands not supported yet

  • MULTI/EXEC/DISCARD/WATCH/UNWATCH
  • SORT
  • ZUNIONSTORE / ZINTERSTORE

redis's People

Contributors

cloudaice avatar cthom06 avatar gihnius avatar gmcintire avatar hoisie avatar kenshinx avatar matiasinsaurralde avatar qm1004 avatar wladh avatar yohcop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis's Issues

generalized redis format

Hi, I just wanted to get your opinion on this... We're using a generalized form of the redis protocol format in doozer, and I thought it would be neat to split out the protocol parsing code into a standalone library.

Of course redis.go is already out there and I don't want to step on your toes. In fact, we would have just used redis.go except that it's a little too specific to the actual redis server.

Here's the code we're using:
https://github.com/bmizerany/doozer/blob/master/src/pkg/proto/proto.go

https://github.com/bmizerany/doozer/blob/master/src/pkg/proto/fit.go

And we're consuming this code in our client and server packages:
https://github.com/bmizerany/doozer/tree/master/src/pkg/client

https://github.com/bmizerany/doozer/tree/master/src/pkg/server

What would you think of providing a lower-level interface similar to this in redis.go? I'm primarily referring to functions encode, decode, and Fit in the code linked above. Or, alternatively, pulling the formatting code into a separate package that we could both share in redis.go and doozer?

There are two things here that I'm fond of.

First is generalization of the format -- a "multi-bulk" response can contain any data: "bulk" data, integers, even other multi-bulk data recursively. Also, we don't treat requests or responses specially -- the full format can be used and parsed in either direction. This is useless when talking to the redis server, but handy when designing a new server-client pair that wants to use the redis format (as in the case of doozer).

Second is an interface similar to the json and gob packages, where the user can provide a pointer to any object and get it filled in by incoming data. But the code for that is pretty involved and it only makes sense if the library is intended to be general-purpose and used by many people. If we wind up not sharing any code after all, we'll likely rip out that feature and replace it with a few simple special-case functions.

If you're amenable to the idea, I'll be happy to redo these thoughts in the form of patches to redis.go (or a separate package) so we can have a more concrete discussion about it.

Compile Error: goto jumps over declaration

Error Message on gomake

redis.go:191: goto End jumps over declaration of b at redis.go:194
redis.go:218: goto End jumps over declaration of reader at redis.go:221
redis.go:231: goto End jumps over declaration of errs at redis.go:245
redis.go:241: goto End jumps over declaration of errs at redis.go:245
make: *** [go.6] Error 1

Environment

$ 6g -V
6g version release.r59 9022

The latest release of go compiler

Reason

From The Go Programming Language Specification: Executing the "goto" statement must not cause any variables to come into scope that were not already in scope at the point of the goto.

Yes, I think they changed the rule.

Solution

Move variable declaration before goto statement or simply get rid of goto

Redis Error: Expecting Prefix '$' or ':'

I'm consistently getting this error from Windows Azure Redis Cache (running v2.8.12 ) on simple GET/SET operations.

Here's server info:

rollercoaster.redis.cache.windows.net:6379> info
# Server
redis_version:2.8.12
redis_git_sha1:6401849
redis_git_dirty:0
redis_build_id:58e765299a8a5ae4
redis_mode:standalone
os:Windows
arch_bits:64
multiplexing_api:winsock_IOCP
gcc_version:0.0.0
process_id:1324
run_id:bdc9e7aa3f75b31e6851d7b318404df9dd580577
tcp_port:10226
uptime_in_seconds:1128
uptime_in_days:0
hz:10
lru_clock:15704668
config_file:C:\Resources\directory\cec74e3c29454ab8aa2abafdc90578c1.Kernel.localStore\1\redis_712_port10226.conf

# Clients
connected_clients:5
client_longest_output_list:0
client_biggest_input_buf:0
client_total_writes_outstanding:0
client_total_sent_bytes_outstanding:0
blocked_clients:0

# Memory
used_memory:138207840
used_memory_human:131.81M
used_memory_rss:201326592
used_memory_rss_human:192.00M
used_memory_peak:138239592
used_memory_peak_human:131.84M
used_memory_lua:33792
mem_fragmentation_ratio:1.46
mem_allocator:dlmalloc-2.8

# Persistence
loading:0
rdb_changes_since_last_save:3
rdb_bgsave_in_progress:0
rdb_last_save_time:1408212488
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:1
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:290
total_commands_processed:1351
instantaneous_ops_per_sec:0
rejected_connections:0
sync_full:1
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:10077

# Replication
role:master
connected_slaves:1
slave0:ip=100.69.98.41,port=10226,state=online,offset=1638,lag=1
master_repl_offset:1638
repl_backlog_active:1
repl_backlog_size:104857600
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1637

# CPU
used_cpu_sys:0.13
used_cpu_user:0.08
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Keyspace
db0:keys=1,expires=0,avg_ttl=0

How do I follow the command?

ZRANGE test_name 0 -1 withscores

This‘s method.
func (client *Client) Zrange(key string, start int, end int) ([][]byte, error)

Can not meet the conditions.

If you want to design like this?
func (client *Client) Zrange(key string, start int, end int) ([]map[[]byte]uint64, error)

map with interface{} values not supported in Hmset

I'm not sure if that's by design, but maps with interface{} values are not supported in Hmset.
E.g.:
var c redis.Client
m := make(map[string]interface{})
m["string"] = "five"
m["int"] = 5
c.Hmset("testkey", m)

I would expect that upon reading I would get a hash { "string" : "five", "int" : 5 } but what I seem to get is { "string" : None, "int" : None } (None because reading was done from Python client) i.e. the hash values don't seem to be serialized properly.

This is using the latest git version on 06/03 (http://github.com/hoisie/redis.go/commit/58bc97f48a1427f6990cb2da0ba108013d53fbec)

hang of subscribe

package main

import (
    "fmt"
    "github.com/hoisie/redis"
)

func main() {
    var client redis.Client

    sub := make(chan string, 1)
    sub <- "foo"
    messages := make(chan redis.Message, 0)
    go client.Subscribe(sub, nil, nil, nil, messages)

    client.Publish("foo", []byte("bar"))
    for {
        select {
        case msg := <-messages:
            fmt.Println("received from:", msg.Channel, " message:", string(msg.Message))
            fmt.Printf("%#v\n", msg)
        }
    }
    defer close(sub)
    defer close(messages)
}

when sending something strange:

127.0.0.1:6379> PUBLISH foo 啦asdasd
(integer) 2
127.0.0.1:6379> PUBLISH foo 啦?asda    <-  ? is a special character that can't describe (takes the size of two english characters) and 啦 is a normal character which takes the size of three english characters
(integer) 2
127.0.0.1:6379> PUBLISH foo 啦?asdaxx
(integer) 2
127.0.0.1:6379> 

output:

received from: foo  message: 啦asdasd
redis.Message{ChannelMatched:"foo", Channel:"foo", Message:[]uint8{0xe5, 0x95, 0xa6, 0x61, 0x73, 0x64, 0x61, 0x73, 0x64}}
hang...............(but it should act to display two lines more as redis-cli does)

redis-cli subscribe output:

1) "message"
2) "foo"
3) "\xe5\x95\xa6asdasd"

1) "message"
2) "foo"
3) "\xe5\x95\xa6\xe5\x95asda"      <- here  i copied 啦 twice and deleted the last position

1) "message"
2) "foo"
3) "\xe5\x95\xa6\xe5\x95asdaxx"

Update to recent Go api changes

Hi, this is a trivial patch:

diff -ru redis.go/redis-load.go redis.foo/redis-load.go
--- redis.go/redis-load.go  2011-05-18 14:42:07.000000000 +0200
+++ redis.foo/redis-load.go 2011-05-19 14:20:52.708237354 +0200
@@ -13,7 +13,7 @@
         addr = "127.0.0.1:" + strconv.Itoa(port)
     }

-    c, err := net.Dial("tcp", "", addr)
+    c, err := net.Dial("tcp", addr)

     if err != nil {
         println(err.String())

missing strlen API

the STRLEN function is missing from the API list. I'm not sure if this is on purpose or not, however, it is terribly inefficient to transmit very long strings from the redis server to the client just so the client can perform a len() locally instead of simply requesting the info from the redis server.

Reconnection of clients

How can we reconnect when the redis servers stop and restarts? It seems when we create a global redis.Client, it doesn't reconnect to the server.

Publish/Subscribe: runtime error on channel close

Consider the following snippet

func Subscribe(channel string, subscr Subscriber) (quit chan int) {
    sub := make(chan string, 1)
    quit = make(chan int)
    messages := make(chan redis.Message, 0)

    go func() {
        if err := client.Subscribe(sub, nil, nil, nil, messages); err != nil {
            log.Error(err)
        }
        fmt.Println("UNBLOCKED")
    }()

    sub <- channel

    go func() {
    L:
        for {
            select {
            case <-quit:
                break L
            case msg := <-messages:
                subscr.Recv(msg.Channel, msg.Message)
            }
        }
        fmt.Println("EXIT")
        close(sub)
        close(quit)
        close(messages)
    }()
    return
}

If any attempt is made to close a channel, it instantly results in

panic: runtime error: send on closed channel

goroutine 12 [running]:
github.com/hoisie/redis.func·002()
.../redis/redis.go:265 +0x81
created by github.com/hoisie/redis.(*Client).sendCommands
.../redis/redis.go:271 +0x38b

Status of Project

What’s the status of this project? I see some PRs that have been created a few months ago, but they don’t appear to have been merged in with master.

Any chance these changes could be merged in? I use this codebase where I work and some of the changes made in some of the PRs definitely would be great to leverage!

Thanks and keep up the good work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.