cassandra getendpoints with partition key has spac

2019-09-16 16:28发布

问题:

my partition keys are id(int) and name(text). Below command works fine until there is no space in name(text). nodetool getendpoints test testtable2 1:aaa;

if am using nodetool getendpoints test testtable2 3:aac cc; it throws an error as :nodetool: getendpoints requires keyspace, table and partition key arguments See 'nodetool help' or 'nodetool help '.

i got token by executing SELECT id,name, token(id,name) FROM test.testtable2 where name='aac cc'AND id=3; and tried to search nodetool getendpoints test testtable2 -7072928299163215694; error: For input string: "-7072928299163215694" -- StackTrace -- java.lang.NumberFormatException: For input string: "-7072928299163215694"

how can i search if partition key (name) has space?

回答1:

This is an issue of nodetool command.

I have modified the nodetool script and create getendpoints script to support getendpoints with partition key has space

Here is the getendpoints code :

#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

if [ "`basename "$0"`" = 'nodeprobe' ]; then
    echo "***************************************************************" >&2
    echo "WARNING: $0 is obsolete, use `dirname "$0"`/nodetool instead" >&2
    echo "***************************************************************" >&2
fi

if [ "x$CASSANDRA_INCLUDE" = "x" ]; then
    for include in "`dirname "$0"`/cassandra.in.sh" \
                   "$HOME/.cassandra.in.sh" \
                   /usr/share/cassandra/cassandra.in.sh \
                   /usr/local/share/cassandra/cassandra.in.sh \
                   /opt/cassandra/cassandra.in.sh; do
        if [ -r "$include" ]; then
            . "$include"
            break
        fi
    done
elif [ -r "$CASSANDRA_INCLUDE" ]; then
    . "$CASSANDRA_INCLUDE"
fi

# Use JAVA_HOME if set, otherwise look for java in PATH
if [ -x "$JAVA_HOME/bin/java" ]; then
    JAVA="$JAVA_HOME/bin/java"
else
    JAVA="`which java`"
fi

if [ -z "$CASSANDRA_CONF" -o -z "$CLASSPATH" ]; then
    echo "You must set the CASSANDRA_CONF and CLASSPATH vars" >&2
    exit 1
fi

# Run cassandra-env.sh to pick up JMX_PORT
if [ -f "$CASSANDRA_CONF/cassandra-env.sh" ]; then
    . "$CASSANDRA_CONF/cassandra-env.sh"
fi

# JMX Port passed via cmd line args (-p 9999 / --port 9999 / --port=9999)
# should override the value from cassandra-env.sh
ARGS=""
JVM_ARGS=""
SSL_FILE=$HOME/.cassandra/nodetool-ssl.properties
KS=""
CF=""
KEY=""

while true
do
  if [ ! $1 ]; then break; fi
  case $1 in
    -p)
      JMX_PORT=$2
      shift
      ;;
    --port=*)
      JMX_PORT=$(echo $1 | cut -d '=' -f 2)
      ;;
    --port)
      JMX_PORT=$2
      shift
      ;;
    --ssl)
      if [ -f $SSL_FILE ]
      then 
          SSL_ARGS=$(cat $SSL_FILE | tr '\n' ' ')
      fi
      JVM_ARGS="$JVM_ARGS -Dssl.enable=true $SSL_ARGS"
      ;;
    -D*)
      JVM_ARGS="$JVM_ARGS $1"
      ;;
    -k)
      KS=$2
      shift
      ;;
    -t)
      CF=$2
      shift
      ;;
    *)
      if [ ! $KEY ]; then 
    KEY="$1"
      else
    KEY="$KEY $1"
      fi
      ;;
  esac
  shift
done

# Special-case path variables.
case "`uname`" in
    CYGWIN*) 
        CLASSPATH="`cygpath -p -w "$CLASSPATH"`"
        CASSANDRA_CONF="`cygpath -p -w "$CASSANDRA_CONF"`"
    ;;
esac

"$JAVA" $JAVA_AGENT -cp "$CLASSPATH" \
      -Xmx128m \
      -Dcassandra.storagedir="$cassandra_storagedir" \
      -Dlogback.configurationFile=logback-tools.xml \
      -Dstorage-config="$CASSANDRA_CONF" \
      $JVM_ARGS \
      org.apache.cassandra.tools.NodeTool -p $JMX_PORT getendpoints $KS $CF "$KEY"

Put getendpoints file under $CASSANDRA_HOME/bin directory.

Now you can run this file with nodetool argument,along with below argument

getendpoints -k keyspace_name -t table_name key

Example :

getendpoints -k test -t testtable2 3:aac cc


回答2:

Which Cassandra version you are using.

I have tested it from Cassandra 2.x and Cassandra 3.x version. It is working properly.

root@cqlsh:test_db> SELECT token(name) from test_temp ;

 system.token(name)
---------------------
 -907920378987128470

nodetool getendpoints test_db test_temp -907920378987128470;
192.168.8.52

Updated Answer: Got the issue

Issue is generated for when 1st part of partition key is int.

CREATE TABLE test6 (
    age int PRIMARY KEY,
    name text
);

bin/nodetool getendpoints test test6 -7072928299163215694
error: For input string: "-7072928299163215694"java.lang.NumberFormatException: For input string:"-
7072928299163215694"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:583)
    at java.lang.Integer.parseInt(Integer.java:615)

But works properly for below input

bin/nodetool getendpoints test test6 -7072
127.0.0.1

From DataStax Doc:

Provides the end points that own the partition key. The partitioner returns a token for the key. Cassandra will return an endpoint whether or not data exists on the identified node for that token. ** key is the partition key of the end points you want to get.

nodetool getendpoints actually takes the value of the partition key as input. In this case '-7072928299163215694' it is parsing it as an Integer thus end up thowing exception. It is working for long or String (it is taking '-7072928299163215694' value as a String) cause it has taken this as value of the key not actual token. It is not parsing tokens. So providing tokens as an input will not work.

getendpoints generates tokens from the value of the key and provide you the endpoints (nodes) the key is residing.

Please check this link: What node does Cassandra store data on?

A patch has been provided for this:

https://issues.apache.org/jira/browse/CASSANDRA-4551

Hope this helps.